using FabAccessAPI.Schema; using S22.Sasl; using System.Collections.Generic; using System.Threading.Tasks; using FabAccessAPI.Exceptions; using System.Linq; namespace FabAccessAPI { /// /// Authenticate with SASL /// public class Auth { #region Private Fields private readonly IAuthentication _AuthCap; #endregion #region Constructors public Auth(IAuthentication authCap) { _AuthCap = authCap; } #endregion #region Methods public async Task Authenticate(string mech, Dictionary properties) { SaslMechanism? saslMechanism = SaslFactory.Create(mech); foreach (KeyValuePair entry in properties) { saslMechanism.Properties.Add(entry.Key, entry.Value); } byte[] data = new byte[0]; if (saslMechanism.HasInitial) { data = saslMechanism.GetResponse(new byte[0]); } Response? response = await _AuthCap.Step(data); while (!saslMechanism.IsCompleted) { if(response.Failed != null) { switch (response.Failed.Code) { case Response.Error.badMechanism: throw new BadMechanismException(); case Response.Error.invalidCredentials: throw new InvalidCredentialsException(); case Response.Error.aborted: case Response.Error.failed: default: throw new AuthenticationFailedException(response.Failed.AdditionalData.ToArray()); } } if(response.Challenge != null) { byte[]? additional = saslMechanism.GetResponse(response.Challenge.ToArray()); response = await _AuthCap.Step(additional); } else { throw new AuthenticationFailedException(); } } if (response.Successful != null) { return response.Successful.Session; } else { throw new AuthenticationFailedException(); } } #endregion } }