using System; using System.Text; namespace S22.Sasl.Mechanisms { /// /// Implements the Sasl OAuth authentication method. /// internal class SaslOAuth : SaslMechanism { bool Completed = false; /// /// Client sends the first message in the authentication exchange. /// public override bool HasInitial { get { return true; } } /// /// True if the authentication exchange between client and server /// has been completed. /// public override bool IsCompleted { get { return Completed; } } /// /// The IANA name for the OAuth authentication mechanism. /// public override string Name { get { return "XOAUTH"; } } /// /// The access token to authenticate with. /// string AccessToken { get { return Properties.ContainsKey("AccessToken") ? Properties["AccessToken"] as string : null; } set { Properties["AccessToken"] = value; } } /// /// Private constructor for use with Sasl.SaslFactory. /// private SaslOAuth() { // Nothing to do here. } /// /// Creates and initializes a new instance of the SaslOAuth class /// using the specified username and password. /// /// The username to authenticate with. /// Thrown if the accessToken /// parameter is null. /// Thrown if the accessToken /// parameter is empty. public SaslOAuth(string accessToken) { accessToken.ThrowIfNull("accessToken"); if (accessToken == String.Empty) throw new ArgumentException("The access token must not be empty."); AccessToken = accessToken; } /// /// Computes the client response for a OAuth challenge. /// /// The challenge sent by the server. /// The response to the OAuth challenge. /// Thrown if the response could not /// be computed. protected override byte[] ComputeResponse(byte[] challenge) { // Precondition: Ensure access token is not null and is not empty. if (String.IsNullOrEmpty(AccessToken)) throw new SaslException("The access token must not be null or empty."); // Sasl OAuth does not involve another roundtrip. Completed = true; return Encoding.ASCII.GetBytes(AccessToken); } } }