diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2012-03-31 11:45:42 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2012-03-31 11:45:42 -0700 |
commit | af226f837b7bb5050ab511e66ba75714f79d8865 (patch) | |
tree | 3dba68ac08d55fa46e2b5c0b52c96d6612b12a2a /src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements | |
parent | b4aa4d4cf25f358e8ca199fe3fbd446d1bb9bc42 (diff) | |
parent | 7265452c16667c6ff499970b0d6778d5184cc8cb (diff) | |
download | DotNetOpenAuth-af226f837b7bb5050ab511e66ba75714f79d8865.zip DotNetOpenAuth-af226f837b7bb5050ab511e66ba75714f79d8865.tar.gz DotNetOpenAuth-af226f837b7bb5050ab511e66ba75714f79d8865.tar.bz2 |
Applied some refactoring of OAuth2 classes.
Diffstat (limited to 'src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements')
16 files changed, 0 insertions, 1368 deletions
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs deleted file mode 100644 index 7a68060..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs +++ /dev/null @@ -1,183 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="AccessRequestBindingElement.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Globalization; - using System.Linq; - using System.Security.Cryptography; - using System.Text; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.Messaging.Bindings; - using DotNetOpenAuth.OAuth2.Messages; - - /// <summary> - /// Decodes verification codes, refresh tokens and access tokens on incoming messages. - /// </summary> - /// <remarks> - /// This binding element also ensures that the code/token coming in is issued to - /// the same client that is sending the code/token and that the authorization has - /// not been revoked and that an access token has not expired. - /// </remarks> - internal class AccessRequestBindingElement : AuthServerBindingElementBase { - /// <summary> - /// Initializes a new instance of the <see cref="AccessRequestBindingElement"/> class. - /// </summary> - internal AccessRequestBindingElement() { - } - - /// <summary> - /// Gets the protection commonly offered (if any) by this binding element. - /// </summary> - /// <value></value> - /// <remarks> - /// This value is used to assist in sorting binding elements in the channel stack. - /// </remarks> - public override MessageProtections Protection { - get { return MessageProtections.None; } - } - - /// <summary> - /// Prepares a message for sending based on the rules of this channel binding element. - /// </summary> - /// <param name="message">The message to prepare for sending.</param> - /// <returns> - /// The protections (if any) that this binding element applied to the message. - /// Null if this binding element did not even apply to this binding element. - /// </returns> - /// <remarks> - /// Implementations that provide message protection must honor the - /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. - /// </remarks> - public override MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) { - var authCodeCarrier = message as IAuthorizationCodeCarryingRequest; - if (authCodeCarrier != null) { - var codeFormatter = AuthorizationCode.CreateFormatter(this.AuthorizationServer); - var code = authCodeCarrier.AuthorizationDescription; - authCodeCarrier.Code = codeFormatter.Serialize(code); - return MessageProtections.None; - } - - var accessTokenCarrier = message as IAccessTokenCarryingRequest; - if (accessTokenCarrier != null) { - var responseWithOriginatingRequest = (IDirectResponseProtocolMessage)message; - var request = (IAccessTokenRequest)responseWithOriginatingRequest.OriginatingRequest; - - using (var resourceServerKey = this.AuthorizationServer.GetResourceServerEncryptionKey(request)) { - var tokenFormatter = AccessToken.CreateFormatter(this.AuthorizationServer.AccessTokenSigningKey, resourceServerKey); - var token = accessTokenCarrier.AuthorizationDescription; - accessTokenCarrier.AccessToken = tokenFormatter.Serialize(token); - } - - return MessageProtections.None; - } - - var accessTokenResponse = message as AccessTokenSuccessResponse; - if (accessTokenResponse != null) { - var directResponseMessage = (IDirectResponseProtocolMessage)accessTokenResponse; - var accessTokenRequest = (AccessTokenRequestBase)directResponseMessage.OriginatingRequest; - ErrorUtilities.VerifyProtocol(accessTokenRequest.GrantType != GrantType.ClientCredentials || accessTokenResponse.RefreshToken == null, OAuthStrings.NoGrantNoRefreshToken); - } - - return null; - } - - /// <summary> - /// Performs any transformation on an incoming message that may be necessary and/or - /// validates an incoming message based on the rules of this channel binding element. - /// </summary> - /// <param name="message">The incoming message to process.</param> - /// <returns> - /// The protections (if any) that this binding element applied to the message. - /// Null if this binding element did not even apply to this binding element. - /// </returns> - /// <exception cref="ProtocolException"> - /// Thrown when the binding element rules indicate that this message is invalid and should - /// NOT be processed. - /// </exception> - /// <remarks> - /// Implementations that provide message protection must honor the - /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. - /// </remarks> - [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "unauthorizedclient", Justification = "Protocol requirement")] - [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "incorrectclientcredentials", Justification = "Protocol requirement")] - [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "authorizationexpired", Justification = "Protocol requirement")] - [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "DotNetOpenAuth.Messaging.ErrorUtilities.VerifyProtocol(System.Boolean,System.String,System.Object[])", Justification = "Protocol requirement")] - public override MessageProtections? ProcessIncomingMessage(IProtocolMessage message) { - var tokenRequest = message as IAuthorizationCarryingRequest; - if (tokenRequest != null) { - try { - var authCodeCarrier = message as IAuthorizationCodeCarryingRequest; - var refreshTokenCarrier = message as IRefreshTokenCarryingRequest; - var resourceOwnerPasswordCarrier = message as AccessTokenResourceOwnerPasswordCredentialsRequest; - var clientCredentialOnly = message as AccessTokenClientCredentialsRequest; - if (authCodeCarrier != null) { - var authorizationCodeFormatter = AuthorizationCode.CreateFormatter(this.AuthorizationServer); - var authorizationCode = authorizationCodeFormatter.Deserialize(message, authCodeCarrier.Code, Protocol.code); - authCodeCarrier.AuthorizationDescription = authorizationCode; - } else if (refreshTokenCarrier != null) { - var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServer.CryptoKeyStore); - var refreshToken = refreshTokenFormatter.Deserialize(message, refreshTokenCarrier.RefreshToken, Protocol.refresh_token); - refreshTokenCarrier.AuthorizationDescription = refreshToken; - } else if (resourceOwnerPasswordCarrier != null) { - try { - if (this.AuthorizationServer.IsResourceOwnerCredentialValid(resourceOwnerPasswordCarrier.UserName, resourceOwnerPasswordCarrier.Password)) { - resourceOwnerPasswordCarrier.CredentialsValidated = true; - } else { - Logger.OAuth.WarnFormat( - "Resource owner password credential for user \"{0}\" rejected by authorization server host.", - resourceOwnerPasswordCarrier.UserName); - - // TODO: fix this to report the appropriate error code for a bad credential. - throw new ProtocolException(); - } - } catch (NotSupportedException) { - // TODO: fix this to return the appropriate error code for not supporting resource owner password credentials - throw new ProtocolException(); - } catch (NotImplementedException) { - // TODO: fix this to return the appropriate error code for not supporting resource owner password credentials - throw new ProtocolException(); - } - } else if (clientCredentialOnly != null) { - // this method will throw later if the credentials are false. - clientCredentialOnly.CredentialsValidated = true; - } else { - throw ErrorUtilities.ThrowInternal("Unexpected message type: " + tokenRequest.GetType()); - } - } catch (ExpiredMessageException ex) { - throw ErrorUtilities.Wrap(ex, Protocol.authorization_expired); - } - - var accessRequest = tokenRequest as AccessTokenRequestBase; - if (accessRequest != null) { - // Make sure the client sending us this token is the client we issued the token to. - ErrorUtilities.VerifyProtocol(string.Equals(accessRequest.ClientIdentifier, tokenRequest.AuthorizationDescription.ClientIdentifier, StringComparison.Ordinal), Protocol.incorrect_client_credentials); - - // Check that the client secret is correct. - var client = this.AuthorizationServer.GetClientOrThrow(accessRequest.ClientIdentifier); - string secret = client.Secret; - ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(secret), Protocol.unauthorized_client); // an empty secret is not allowed for client authenticated calls. - ErrorUtilities.VerifyProtocol(MessagingUtilities.EqualsConstantTime(secret, accessRequest.ClientSecret), Protocol.incorrect_client_credentials); - - var scopedAccessRequest = accessRequest as ScopedAccessTokenRequest; - if (scopedAccessRequest != null) { - // Make sure the scope the client is requesting does not exceed the scope in the grant. - ErrorUtilities.VerifyProtocol(scopedAccessRequest.Scope.IsSubsetOf(tokenRequest.AuthorizationDescription.Scope), OAuthStrings.AccessScopeExceedsGrantScope, scopedAccessRequest.Scope, tokenRequest.AuthorizationDescription.Scope); - } - } - - // Make sure the authorization this token represents hasn't already been revoked. - ErrorUtilities.VerifyProtocol(this.AuthorizationServer.IsAuthorizationValid(tokenRequest.AuthorizationDescription), Protocol.authorization_expired); - - return MessageProtections.None; - } - - return null; - } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessTokenBindingElement.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessTokenBindingElement.cs deleted file mode 100644 index 4c63f29..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessTokenBindingElement.cs +++ /dev/null @@ -1,93 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="AccessTokenBindingElement.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Security.Cryptography; - using System.Text; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OAuth2.Messages; - - /// <summary> - /// Serializes access tokens inside an outgoing message. - /// </summary> - internal class AccessTokenBindingElement : AuthServerBindingElementBase { - /// <summary> - /// Initializes a new instance of the <see cref="AccessTokenBindingElement"/> class. - /// </summary> - internal AccessTokenBindingElement() { - } - - /// <summary> - /// Gets the protection commonly offered (if any) by this binding element. - /// </summary> - /// <value>Always <c>MessageProtections.None</c></value> - /// <remarks> - /// This value is used to assist in sorting binding elements in the channel stack. - /// </remarks> - public override MessageProtections Protection { - get { return MessageProtections.None; } - } - - /// <summary> - /// Prepares a message for sending based on the rules of this channel binding element. - /// </summary> - /// <param name="message">The message to prepare for sending.</param> - /// <returns> - /// The protections (if any) that this binding element applied to the message. - /// Null if this binding element did not even apply to this binding element. - /// </returns> - public override MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) { - var directResponse = message as IDirectResponseProtocolMessage; - IAccessTokenRequest request = directResponse != null ? directResponse.OriginatingRequest as IAccessTokenRequest : null; - - var implicitGrantResponse = message as EndUserAuthorizationSuccessAccessTokenResponse; - if (implicitGrantResponse != null) { - IAccessTokenCarryingRequest tokenCarryingResponse = implicitGrantResponse; - tokenCarryingResponse.AuthorizationDescription = new AccessToken(request.ClientIdentifier, implicitGrantResponse.Scope, implicitGrantResponse.AuthorizingUsername, implicitGrantResponse.Lifetime); - - return MessageProtections.None; - } - - var accessTokenResponse = message as AccessTokenSuccessResponse; - if (accessTokenResponse != null) { - var authCarryingRequest = (IAuthorizationCarryingRequest)request; - var accessToken = new AccessToken(authCarryingRequest.AuthorizationDescription, accessTokenResponse.Lifetime); - using (var resourceServerEncryptionKey = this.AuthorizationServer.GetResourceServerEncryptionKey(request)) { - var accessTokenFormatter = AccessToken.CreateFormatter(this.AuthorizationServer.AccessTokenSigningKey, resourceServerEncryptionKey); - accessTokenResponse.AccessToken = accessTokenFormatter.Serialize(accessToken); - } - - if (accessTokenResponse.HasRefreshToken) { - var refreshToken = new RefreshToken(authCarryingRequest.AuthorizationDescription); - var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServer.CryptoKeyStore); - accessTokenResponse.RefreshToken = refreshTokenFormatter.Serialize(refreshToken); - } - } - - return null; - } - - /// <summary> - /// Performs any transformation on an incoming message that may be necessary and/or - /// validates an incoming message based on the rules of this channel binding element. - /// </summary> - /// <param name="message">The incoming message to process.</param> - /// <returns> - /// The protections (if any) that this binding element applied to the message. - /// Null if this binding element did not even apply to this binding element. - /// </returns> - /// <exception cref="ProtocolException"> - /// Thrown when the binding element rules indicate that this message is invalid and should - /// NOT be processed. - /// </exception> - public override MessageProtections? ProcessIncomingMessage(IProtocolMessage message) { - return null; - } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerAllFlowsBindingElement.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerAllFlowsBindingElement.cs deleted file mode 100644 index 24ac020..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerAllFlowsBindingElement.cs +++ /dev/null @@ -1,83 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="AuthServerAllFlowsBindingElement.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using System.Collections.Generic; - using System.Diagnostics.Contracts; - using System.Linq; - using System.Text; - using DotNetOpenAuth.OAuth2.Messages; - using Messaging; - - /// <summary> - /// A binding element that should be applied for authorization server channels regardless of which flows - /// are supported. - /// </summary> - internal class AuthServerAllFlowsBindingElement : AuthServerBindingElementBase { - /// <summary> - /// Initializes a new instance of the <see cref="AuthServerAllFlowsBindingElement"/> class. - /// </summary> - internal AuthServerAllFlowsBindingElement() { - } - - /// <summary> - /// Gets the protection commonly offered (if any) by this binding element. - /// </summary> - /// <remarks> - /// This value is used to assist in sorting binding elements in the channel stack. - /// </remarks> - public override MessageProtections Protection { - get { return MessageProtections.None; } - } - - /// <summary> - /// Prepares a message for sending based on the rules of this channel binding element. - /// </summary> - /// <param name="message">The message to prepare for sending.</param> - /// <returns> - /// The protections (if any) that this binding element applied to the message. - /// Null if this binding element did not even apply to this binding element. - /// </returns> - /// <remarks> - /// Implementations that provide message protection must honor the - /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. - /// </remarks> - public override MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) { - return null; - } - - /// <summary> - /// Performs any transformation on an incoming message that may be necessary and/or - /// validates an incoming message based on the rules of this channel binding element. - /// </summary> - /// <param name="message">The incoming message to process.</param> - /// <returns> - /// The protections (if any) that this binding element applied to the message. - /// Null if this binding element did not even apply to this binding element. - /// </returns> - /// <exception cref="ProtocolException"> - /// Thrown when the binding element rules indicate that this message is invalid and should - /// NOT be processed. - /// </exception> - /// <remarks> - /// Implementations that provide message protection must honor the - /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. - /// </remarks> - public override MessageProtections? ProcessIncomingMessage(IProtocolMessage message) { - var authorizationRequest = message as EndUserAuthorizationRequest; - if (authorizationRequest != null) { - var client = this.AuthorizationServer.GetClientOrThrow(authorizationRequest.ClientIdentifier); - ErrorUtilities.VerifyProtocol(authorizationRequest.Callback == null || client.IsCallbackAllowed(authorizationRequest.Callback), OAuthStrings.ClientCallbackDisallowed, authorizationRequest.Callback); - ErrorUtilities.VerifyProtocol(authorizationRequest.Callback != null || client.DefaultCallback != null, OAuthStrings.NoCallback); - - return MessageProtections.None; - } - - return null; - } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerBindingElementBase.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerBindingElementBase.cs deleted file mode 100644 index 49f820d..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerBindingElementBase.cs +++ /dev/null @@ -1,81 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="AuthServerBindingElementBase.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using Messaging; - - /// <summary> - /// The base class for any authorization server channel binding element. - /// </summary> - internal abstract class AuthServerBindingElementBase : IChannelBindingElement { - /// <summary> - /// Initializes a new instance of the <see cref="AuthServerBindingElementBase"/> class. - /// </summary> - protected AuthServerBindingElementBase() { - } - - /// <summary> - /// Gets or sets the channel that this binding element belongs to. - /// </summary> - /// <remarks> - /// This property is set by the channel when it is first constructed. - /// </remarks> - public Channel Channel { get; set; } - - /// <summary> - /// Gets the protection commonly offered (if any) by this binding element. - /// </summary> - /// <remarks> - /// This value is used to assist in sorting binding elements in the channel stack. - /// </remarks> - public abstract MessageProtections Protection { get; } - - /// <summary> - /// Gets the authorization server hosting this channel. - /// </summary> - /// <value>The authorization server.</value> - protected IAuthorizationServer AuthorizationServer { - get { return ((IOAuth2ChannelWithAuthorizationServer)this.Channel).AuthorizationServer; } - } - - /// <summary> - /// Prepares a message for sending based on the rules of this channel binding element. - /// </summary> - /// <param name="message">The message to prepare for sending.</param> - /// <returns> - /// The protections (if any) that this binding element applied to the message. - /// Null if this binding element did not even apply to this binding element. - /// </returns> - /// <remarks> - /// Implementations that provide message protection must honor the - /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. - /// </remarks> - public abstract MessageProtections? ProcessOutgoingMessage(IProtocolMessage message); - - /// <summary> - /// Performs any transformation on an incoming message that may be necessary and/or - /// validates an incoming message based on the rules of this channel binding element. - /// </summary> - /// <param name="message">The incoming message to process.</param> - /// <returns> - /// The protections (if any) that this binding element applied to the message. - /// Null if this binding element did not even apply to this binding element. - /// </returns> - /// <exception cref="ProtocolException"> - /// Thrown when the binding element rules indicate that this message is invalid and should - /// NOT be processed. - /// </exception> - /// <remarks> - /// Implementations that provide message protection must honor the - /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. - /// </remarks> - public abstract MessageProtections? ProcessIncomingMessage(IProtocolMessage message); - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCode.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCode.cs deleted file mode 100644 index 111c007..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCode.cs +++ /dev/null @@ -1,110 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="AuthorizationCode.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; - using System.Security.Cryptography; - using System.Text; - using DotNetOpenAuth.Messaging; - - /// <summary> - /// Represents the authorization code created when a user approves authorization that - /// allows the client to request an access/refresh token. - /// </summary> - internal class AuthorizationCode : AuthorizationDataBag { - /// <summary> - /// The name of the bucket for symmetric keys used to sign authorization codes. - /// </summary> - internal const string AuthorizationCodeKeyBucket = "https://localhost/dnoa/oauth_authorization_code"; - - /// <summary> - /// Initializes a new instance of the <see cref="AuthorizationCode"/> class. - /// </summary> - public AuthorizationCode() { - } - - /// <summary> - /// Initializes a new instance of the <see cref="AuthorizationCode"/> class. - /// </summary> - /// <param name="clientIdentifier">The client identifier.</param> - /// <param name="callback">The callback the client used to obtain authorization, if one was explicitly included in the request.</param> - /// <param name="scopes">The authorized scopes.</param> - /// <param name="username">The name on the account that authorized access.</param> - internal AuthorizationCode(string clientIdentifier, Uri callback, IEnumerable<string> scopes, string username) { - Requires.NotNullOrEmpty(clientIdentifier, "clientIdentifier"); - - this.ClientIdentifier = clientIdentifier; - this.CallbackHash = CalculateCallbackHash(callback); - this.Scope.ResetContents(scopes); - this.User = username; - this.UtcCreationDate = DateTime.UtcNow; - } - - /// <summary> - /// Gets or sets the hash of the callback URL. - /// </summary> - [MessagePart("cb")] - private byte[] CallbackHash { get; set; } - - /// <summary> - /// Creates a serializer/deserializer for this type. - /// </summary> - /// <param name="authorizationServer">The authorization server that will be serializing/deserializing this authorization code. Must not be null.</param> - /// <returns>A DataBag formatter.</returns> - internal static IDataBagFormatter<AuthorizationCode> CreateFormatter(IAuthorizationServer authorizationServer) { - Requires.NotNull(authorizationServer, "authorizationServer"); - Contract.Ensures(Contract.Result<IDataBagFormatter<AuthorizationCode>>() != null); - - var cryptoStore = authorizationServer.CryptoKeyStore; - ErrorUtilities.VerifyHost(cryptoStore != null, OAuthStrings.ResultShouldNotBeNull, authorizationServer.GetType(), "CryptoKeyStore"); - - return new UriStyleMessageFormatter<AuthorizationCode>( - cryptoStore, - AuthorizationCodeKeyBucket, - signed: true, - encrypted: true, - compressed: false, - maximumAge: AuthorizationCodeBindingElement.MaximumMessageAge, - decodeOnceOnly: authorizationServer.VerificationCodeNonceStore); - } - - /// <summary> - /// Verifies the the given callback URL matches the callback originally given in the authorization request. - /// </summary> - /// <param name="callback">The callback.</param> - /// <remarks> - /// This method serves to verify that the callback URL given in the original authorization request - /// and the callback URL given in the access token request match. - /// </remarks> - /// <exception cref="ProtocolException">Thrown when the callback URLs do not match.</exception> - [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "redirecturimismatch", Justification = "Protocol requirement")] - [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "DotNetOpenAuth.Messaging.ErrorUtilities.VerifyProtocol(System.Boolean,System.String,System.Object[])", Justification = "Protocol requirement")] - internal void VerifyCallback(Uri callback) { - ErrorUtilities.VerifyProtocol(MessagingUtilities.AreEquivalent(this.CallbackHash, CalculateCallbackHash(callback)), Protocol.redirect_uri_mismatch); - } - - /// <summary> - /// Calculates the hash of the callback URL. - /// </summary> - /// <param name="callback">The callback whose hash should be calculated.</param> - /// <returns> - /// A base64 encoding of the hash of the URL. - /// </returns> - [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive.")] - private static byte[] CalculateCallbackHash(Uri callback) { - if (callback == null) { - return null; - } - - using (var hasher = new SHA256Managed()) { - return hasher.ComputeHash(Encoding.UTF8.GetBytes(callback.AbsoluteUri)); - } - } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCodeBindingElement.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCodeBindingElement.cs deleted file mode 100644 index d602cae..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCodeBindingElement.cs +++ /dev/null @@ -1,101 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="AuthorizationCodeBindingElement.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using Messages; - using Messaging; - using Messaging.Bindings; - - /// <summary> - /// A binding element for OAuth 2.0 authorization servers that create/verify - /// issued authorization codes as part of obtaining access/refresh tokens. - /// </summary> - internal class AuthorizationCodeBindingElement : AuthServerBindingElementBase { - /// <summary> - /// Initializes a new instance of the <see cref="AuthorizationCodeBindingElement"/> class. - /// </summary> - internal AuthorizationCodeBindingElement() { - } - - /// <summary> - /// Gets the protection commonly offered (if any) by this binding element. - /// </summary> - /// <value>Always <c>MessageProtections.None</c></value> - /// <remarks> - /// This value is used to assist in sorting binding elements in the channel stack. - /// </remarks> - public override MessageProtections Protection { - get { return MessageProtections.None; } - } - - /// <summary> - /// Gets the maximum message age from the standard expiration binding element. - /// </summary> - /// <value>This interval need not account for clock skew because it is only compared within a single authorization server or farm of servers.</value> - internal static TimeSpan MaximumMessageAge { - get { return Configuration.DotNetOpenAuthSection.Messaging.MaximumMessageLifetimeNoSkew; } - } - - /// <summary> - /// Prepares a message for sending based on the rules of this channel binding element. - /// </summary> - /// <param name="message">The message to prepare for sending.</param> - /// <returns> - /// The protections (if any) that this binding element applied to the message. - /// Null if this binding element did not even apply to this binding element. - /// </returns> - /// <remarks> - /// Implementations that provide message protection must honor the - /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. - /// </remarks> - public override MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) { - var response = message as EndUserAuthorizationSuccessAuthCodeResponse; - if (response != null) { - var directResponse = (IDirectResponseProtocolMessage)response; - var request = (EndUserAuthorizationRequest)directResponse.OriginatingRequest; - IAuthorizationCodeCarryingRequest tokenCarryingResponse = response; - tokenCarryingResponse.AuthorizationDescription = new AuthorizationCode(request.ClientIdentifier, request.Callback, response.Scope, response.AuthorizingUsername); - - return MessageProtections.None; - } - - return null; - } - - /// <summary> - /// Performs any transformation on an incoming message that may be necessary and/or - /// validates an incoming message based on the rules of this channel binding element. - /// </summary> - /// <param name="message">The incoming message to process.</param> - /// <returns> - /// The protections (if any) that this binding element applied to the message. - /// Null if this binding element did not even apply to this binding element. - /// </returns> - /// <exception cref="ProtocolException"> - /// Thrown when the binding element rules indicate that this message is invalid and should - /// NOT be processed. - /// </exception> - /// <remarks> - /// Implementations that provide message protection must honor the - /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. - /// </remarks> - public override MessageProtections? ProcessIncomingMessage(IProtocolMessage message) { - var request = message as AccessTokenAuthorizationCodeRequest; - if (request != null) { - IAuthorizationCarryingRequest tokenRequest = request; - ((AuthorizationCode)tokenRequest.AuthorizationDescription).VerifyCallback(request.Callback); - - return MessageProtections.None; - } - - return null; - } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs deleted file mode 100644 index 2fba721..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs +++ /dev/null @@ -1,66 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="EndUserAuthorizationResponseTypeEncoder.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.Messaging.Reflection; - using DotNetOpenAuth.OAuth2.Messages; - - /// <summary> - /// Encodes/decodes the OAuth 2.0 response_type argument. - /// </summary> - internal class EndUserAuthorizationResponseTypeEncoder : IMessagePartEncoder { - /// <summary> - /// Initializes a new instance of the <see cref="EndUserAuthorizationResponseTypeEncoder"/> class. - /// </summary> - public EndUserAuthorizationResponseTypeEncoder() { - } - - #region IMessagePartEncoder Members - - /// <summary> - /// Encodes the specified value. - /// </summary> - /// <param name="value">The value. Guaranteed to never be null.</param> - /// <returns> - /// The <paramref name="value"/> in string form, ready for message transport. - /// </returns> - public string Encode(object value) { - var responseType = (EndUserAuthorizationResponseType)value; - switch (responseType) - { - case EndUserAuthorizationResponseType.AccessToken: - return Protocol.ResponseTypes.Token; - case EndUserAuthorizationResponseType.AuthorizationCode: - return Protocol.ResponseTypes.Code; - default: - throw ErrorUtilities.ThrowFormat(MessagingStrings.UnexpectedMessagePartValue, Protocol.response_type, value); - } - } - - /// <summary> - /// Decodes the specified value. - /// </summary> - /// <param name="value">The string value carried by the transport. Guaranteed to never be null, although it may be empty.</param> - /// <returns> - /// The deserialized form of the given string. - /// </returns> - /// <exception cref="FormatException">Thrown when the string value given cannot be decoded into the required object type.</exception> - public object Decode(string value) { - switch (value) { - case Protocol.ResponseTypes.Token: - return EndUserAuthorizationResponseType.AccessToken; - case Protocol.ResponseTypes.Code: - return EndUserAuthorizationResponseType.AuthorizationCode; - default: - throw ErrorUtilities.ThrowFormat(MessagingStrings.UnexpectedMessagePartValue, Protocol.response_type, value); - } - } - - #endregion - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/GrantTypeEncoder.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/GrantTypeEncoder.cs deleted file mode 100644 index e0e8329..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/GrantTypeEncoder.cs +++ /dev/null @@ -1,78 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="GrantTypeEncoder.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.Messaging.Reflection; - using DotNetOpenAuth.OAuth2.Messages; - - /// <summary> - /// Encodes/decodes the OAuth 2.0 grant_type argument. - /// </summary> - internal class GrantTypeEncoder : IMessagePartEncoder { - /// <summary> - /// Initializes a new instance of the <see cref="GrantTypeEncoder"/> class. - /// </summary> - public GrantTypeEncoder() { - } - - #region IMessagePartEncoder Members - - /// <summary> - /// Encodes the specified value. - /// </summary> - /// <param name="value">The value. Guaranteed to never be null.</param> - /// <returns> - /// The <paramref name="value"/> in string form, ready for message transport. - /// </returns> - public string Encode(object value) { - var responseType = (GrantType)value; - switch (responseType) - { - case GrantType.ClientCredentials: - return Protocol.GrantTypes.ClientCredentials; - case GrantType.AuthorizationCode: - return Protocol.GrantTypes.AuthorizationCode; - case GrantType.RefreshToken: - return Protocol.GrantTypes.RefreshToken; - case GrantType.Password: - return Protocol.GrantTypes.Password; - case GrantType.Assertion: - return Protocol.GrantTypes.Assertion; - default: - throw ErrorUtilities.ThrowFormat(MessagingStrings.UnexpectedMessagePartValue, Protocol.grant_type, value); - } - } - - /// <summary> - /// Decodes the specified value. - /// </summary> - /// <param name="value">The string value carried by the transport. Guaranteed to never be null, although it may be empty.</param> - /// <returns> - /// The deserialized form of the given string. - /// </returns> - /// <exception cref="FormatException">Thrown when the string value given cannot be decoded into the required object type.</exception> - public object Decode(string value) { - switch (value) { - case Protocol.GrantTypes.ClientCredentials: - return GrantType.ClientCredentials; - case Protocol.GrantTypes.Assertion: - return GrantType.Assertion; - case Protocol.GrantTypes.Password: - return GrantType.Password; - case Protocol.GrantTypes.RefreshToken: - return GrantType.RefreshToken; - case Protocol.GrantTypes.AuthorizationCode: - return GrantType.AuthorizationCode; - default: - throw ErrorUtilities.ThrowFormat(MessagingStrings.UnexpectedMessagePartValue, Protocol.grant_type, value); - } - } - - #endregion - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IAuthorizationCodeCarryingRequest.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IAuthorizationCodeCarryingRequest.cs deleted file mode 100644 index 045cb80..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IAuthorizationCodeCarryingRequest.cs +++ /dev/null @@ -1,22 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="IAuthorizationCodeCarryingRequest.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - /// <summary> - /// A message that carries an authorization code between client and authorization server. - /// </summary> - internal interface IAuthorizationCodeCarryingRequest : IAuthorizationCarryingRequest { - /// <summary> - /// Gets or sets the authorization code. - /// </summary> - string Code { get; set; } - - /// <summary> - /// Gets or sets the authorization that the code describes. - /// </summary> - new AuthorizationCode AuthorizationDescription { get; set; } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IOAuth2ChannelWithAuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IOAuth2ChannelWithAuthorizationServer.cs deleted file mode 100644 index 5fc73ce..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IOAuth2ChannelWithAuthorizationServer.cs +++ /dev/null @@ -1,19 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="IOAuth2ChannelWithAuthorizationServer.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - /// <summary> - /// An interface on an OAuth 2 Authorization Server channel - /// to expose the host provided authorization server object. - /// </summary> - internal interface IOAuth2ChannelWithAuthorizationServer { - /// <summary> - /// Gets the authorization server. - /// </summary> - /// <value>The authorization server.</value> - IAuthorizationServer AuthorizationServer { get; } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IRefreshTokenCarryingRequest.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IRefreshTokenCarryingRequest.cs deleted file mode 100644 index ce27538..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IRefreshTokenCarryingRequest.cs +++ /dev/null @@ -1,22 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="IRefreshTokenCarryingRequest.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - /// <summary> - /// A message that carries a refresh token between client and authorization server. - /// </summary> - internal interface IRefreshTokenCarryingRequest : IAuthorizationCarryingRequest { - /// <summary> - /// Gets or sets the refresh token. - /// </summary> - string RefreshToken { get; set; } - - /// <summary> - /// Gets or sets the authorization that the token describes. - /// </summary> - new RefreshToken AuthorizationDescription { get; set; } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs deleted file mode 100644 index 6717717..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs +++ /dev/null @@ -1,109 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OAuth2AuthorizationServerChannel.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using System.Collections.Generic; - using System.Diagnostics.Contracts; - using System.Net.Mime; - using System.Web; - using DotNetOpenAuth.Messaging; - - /// <summary> - /// The channel for the OAuth protocol. - /// </summary> - internal class OAuth2AuthorizationServerChannel : OAuth2ChannelBase, IOAuth2ChannelWithAuthorizationServer { - /// <summary> - /// Initializes a new instance of the <see cref="OAuth2AuthorizationServerChannel"/> class. - /// </summary> - /// <param name="authorizationServer">The authorization server.</param> - protected internal OAuth2AuthorizationServerChannel(IAuthorizationServer authorizationServer) - : base(InitializeBindingElements(authorizationServer)) { - Requires.NotNull(authorizationServer, "authorizationServer"); - this.AuthorizationServer = authorizationServer; - } - - /// <summary> - /// Gets the authorization server. - /// </summary> - /// <value>The authorization server.</value> - public IAuthorizationServer AuthorizationServer { get; private set; } - - /// <summary> - /// Gets the protocol message that may be in the given HTTP response. - /// </summary> - /// <param name="response">The response that is anticipated to contain an protocol message.</param> - /// <returns> - /// The deserialized message parts, if found. Null otherwise. - /// </returns> - /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> - protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { - throw new NotImplementedException(); - } - - /// <summary> - /// Queues a message for sending in the response stream. - /// </summary> - /// <param name="response">The message to send as a response.</param> - /// <returns> - /// The pending user agent redirect based message to be sent as an HttpResponse. - /// </returns> - /// <remarks> - /// This method implements spec OAuth V1.0 section 5.3. - /// </remarks> - protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) { - var webResponse = new OutgoingWebResponse(); - ApplyMessageTemplate(response, webResponse); - string json = this.SerializeAsJson(response); - webResponse.SetResponse(json, new ContentType(JsonEncoded)); - return webResponse; - } - - /// <summary> - /// Gets the protocol message that may be embedded in the given HTTP request. - /// </summary> - /// <param name="request">The request to search for an embedded message.</param> - /// <returns> - /// The deserialized message, if one is found. Null otherwise. - /// </returns> - protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) { - if (!string.IsNullOrEmpty(request.Url.Fragment)) { - var fields = HttpUtility.ParseQueryString(request.Url.Fragment.Substring(1)).ToDictionary(); - - MessageReceivingEndpoint recipient; - try { - recipient = request.GetRecipient(); - } catch (ArgumentException ex) { - Logger.Messaging.WarnFormat("Unrecognized HTTP request: " + ex.ToString()); - return null; - } - - return (IDirectedProtocolMessage)this.Receive(fields, recipient); - } - - return base.ReadFromRequestCore(request); - } - - /// <summary> - /// Initializes the binding elements for the OAuth channel. - /// </summary> - /// <param name="authorizationServer">The authorization server.</param> - /// <returns> - /// An array of binding elements used to initialize the channel. - /// </returns> - private static IChannelBindingElement[] InitializeBindingElements(IAuthorizationServer authorizationServer) { - Requires.NotNull(authorizationServer, "authorizationServer"); - var bindingElements = new List<IChannelBindingElement>(); - - bindingElements.Add(new AuthServerAllFlowsBindingElement()); - bindingElements.Add(new AuthorizationCodeBindingElement()); - bindingElements.Add(new AccessTokenBindingElement()); - bindingElements.Add(new AccessRequestBindingElement()); - - return bindingElements.ToArray(); - } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ChannelBase.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ChannelBase.cs deleted file mode 100644 index 51ac58a..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ChannelBase.cs +++ /dev/null @@ -1,70 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OAuth2ChannelBase.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OAuth2.Messages; - - /// <summary> - /// The base messaging channel used by OAuth 2.0 parties. - /// </summary> - internal abstract class OAuth2ChannelBase : StandardMessageFactoryChannel { - /// <summary> - /// The messages receivable by this channel. - /// </summary> - private static readonly Type[] MessageTypes = new Type[] { - typeof(AccessTokenRefreshRequest), - typeof(AccessTokenAuthorizationCodeRequest), - typeof(AccessTokenResourceOwnerPasswordCredentialsRequest), - typeof(AccessTokenClientCredentialsRequest), - typeof(AccessTokenSuccessResponse), - typeof(AccessTokenFailedResponse), - typeof(EndUserAuthorizationRequest), - typeof(EndUserAuthorizationImplicitRequest), - typeof(EndUserAuthorizationSuccessAuthCodeResponse), - typeof(EndUserAuthorizationSuccessAccessTokenResponse), - typeof(EndUserAuthorizationFailedResponse), - typeof(UnauthorizedResponse), - }; - - /// <summary> - /// The protocol versions supported by this channel. - /// </summary> - private static readonly Version[] Versions = Protocol.AllVersions.Select(v => v.Version).ToArray(); - - /// <summary> - /// Initializes a new instance of the <see cref="OAuth2ChannelBase"/> class. - /// </summary> - /// <param name="channelBindingElements">The channel binding elements.</param> - internal OAuth2ChannelBase(params IChannelBindingElement[] channelBindingElements) - : base(MessageTypes, Versions, channelBindingElements) { - } - - /// <summary> - /// Allows preprocessing and validation of message data before an appropriate message type is - /// selected or deserialized. - /// </summary> - /// <param name="fields">The received message data.</param> - protected override void FilterReceivedFields(IDictionary<string, string> fields) { - base.FilterReceivedFields(fields); - - // Apply the OAuth 2.0 section 2.1 requirement: - // Parameters sent without a value MUST be treated as if they were omitted from the request. - // The authorization server SHOULD ignore unrecognized request parameters. - var emptyKeys = from pair in fields - where string.IsNullOrEmpty(pair.Value) - select pair.Key; - foreach (string emptyKey in emptyKeys.ToList()) { - fields.Remove(emptyKey); - } - } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ClientChannel.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ClientChannel.cs deleted file mode 100644 index c9981d3..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ClientChannel.cs +++ /dev/null @@ -1,122 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OAuth2ClientChannel.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using System.Collections.Generic; - using System.Collections.Specialized; - using System.Diagnostics.Contracts; - using System.Net; - using System.Web; - - using DotNetOpenAuth.Messaging; - - /// <summary> - /// The messaging channel used by OAuth 2.0 Clients. - /// </summary> - internal class OAuth2ClientChannel : OAuth2ChannelBase { - /// <summary> - /// Initializes a new instance of the <see cref="OAuth2ClientChannel"/> class. - /// </summary> - internal OAuth2ClientChannel() { - } - - /// <summary> - /// Prepares an HTTP request that carries a given message. - /// </summary> - /// <param name="request">The message to send.</param> - /// <returns> - /// The <see cref="HttpWebRequest"/> prepared to send the request. - /// </returns> - /// <remarks> - /// This method must be overridden by a derived class, unless the <see cref="Channel.RequestCore"/> method - /// is overridden and does not require this method. - /// </remarks> - protected override HttpWebRequest CreateHttpRequest(IDirectedProtocolMessage request) { - HttpWebRequest httpRequest; - if ((request.HttpMethods & HttpDeliveryMethods.GetRequest) != 0) { - httpRequest = InitializeRequestAsGet(request); - } else if ((request.HttpMethods & HttpDeliveryMethods.PostRequest) != 0) { - httpRequest = InitializeRequestAsPost(request); - } else { - throw new NotSupportedException(); - } - - return httpRequest; - } - - /// <summary> - /// Gets the protocol message that may be in the given HTTP response. - /// </summary> - /// <param name="response">The response that is anticipated to contain an protocol message.</param> - /// <returns> - /// The deserialized message parts, if found. Null otherwise. - /// </returns> - /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> - protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { - // The spec says direct responses should be JSON objects, but Facebook uses HttpFormUrlEncoded instead, calling it text/plain - // Others return text/javascript. Again bad. - string body = response.GetResponseReader().ReadToEnd(); - if (response.ContentType.MediaType == JsonEncoded || response.ContentType.MediaType == JsonTextEncoded) { - return this.DeserializeFromJson(body); - } else if (response.ContentType.MediaType == HttpFormUrlEncoded || response.ContentType.MediaType == PlainTextEncoded) { - return HttpUtility.ParseQueryString(body).ToDictionary(); - } else { - throw ErrorUtilities.ThrowProtocol(OAuthStrings.UnexpectedResponseContentType, response.ContentType.MediaType); - } - } - - /// <summary> - /// Gets the protocol message that may be embedded in the given HTTP request. - /// </summary> - /// <param name="request">The request to search for an embedded message.</param> - /// <returns> - /// The deserialized message, if one is found. Null otherwise. - /// </returns> - protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) { - Logger.Channel.DebugFormat("Incoming HTTP request: {0} {1}", request.HttpMethod, request.GetPublicFacingUrl().AbsoluteUri); - - var fields = request.GetQueryStringBeforeRewriting().ToDictionary(); - - // Also read parameters from the fragment, if it's available. - // Typically the fragment is not available because the browser doesn't send it to a web server - // but this request may have been fabricated by an installed desktop app, in which case - // the fragment is available. - string fragment = request.GetPublicFacingUrl().Fragment; - if (!string.IsNullOrEmpty(fragment)) { - foreach (var pair in HttpUtility.ParseQueryString(fragment.Substring(1)).ToDictionary()) { - fields.Add(pair.Key, pair.Value); - } - } - - MessageReceivingEndpoint recipient; - try { - recipient = request.GetRecipient(); - } catch (ArgumentException ex) { - Logger.Messaging.WarnFormat("Unrecognized HTTP request: ", ex); - return null; - } - - return (IDirectedProtocolMessage)this.Receive(fields, recipient); - } - - /// <summary> - /// Queues a message for sending in the response stream where the fields - /// are sent in the response stream in querystring style. - /// </summary> - /// <param name="response">The message to send as a response.</param> - /// <returns> - /// The pending user agent redirect based message to be sent as an HttpResponse. - /// </returns> - /// <remarks> - /// This method implements spec OAuth V1.0 section 5.3. - /// </remarks> - protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) { - // Clients don't ever send direct responses. - throw new NotImplementedException(); - } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ResourceServerChannel.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ResourceServerChannel.cs deleted file mode 100644 index 947c044..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ResourceServerChannel.cs +++ /dev/null @@ -1,153 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OAuth2ResourceServerChannel.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using System.Collections.Generic; - using System.Diagnostics.Contracts; - using System.Linq; - using System.Net; - using System.Net.Mime; - using System.Text; - using System.Web; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.Messaging.Reflection; - using DotNetOpenAuth.OAuth2.Messages; - - /// <summary> - /// The channel for the OAuth protocol. - /// </summary> - internal class OAuth2ResourceServerChannel : StandardMessageFactoryChannel { - /// <summary> - /// The messages receivable by this channel. - /// </summary> - private static readonly Type[] MessageTypes = new Type[] { - typeof(Messages.AccessProtectedResourceRequest), - }; - - /// <summary> - /// The protocol versions supported by this channel. - /// </summary> - private static readonly Version[] Versions = Protocol.AllVersions.Select(v => v.Version).ToArray(); - - /// <summary> - /// Initializes a new instance of the <see cref="OAuth2ResourceServerChannel"/> class. - /// </summary> - protected internal OAuth2ResourceServerChannel() - : base(MessageTypes, Versions) { - // TODO: add signing (authenticated request) binding element. - } - - /// <summary> - /// Gets the protocol message that may be embedded in the given HTTP request. - /// </summary> - /// <param name="request">The request to search for an embedded message.</param> - /// <returns> - /// The deserialized message, if one is found. Null otherwise. - /// </returns> - protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) { - var fields = new Dictionary<string, string>(); - string accessToken; - if ((accessToken = SearchForBearerAccessTokenInRequest(request)) != null) { - fields["token_type"] = Protocol.AccessTokenTypes.Bearer; - fields["access_token"] = accessToken; - } - - if (fields.Count > 0) { - MessageReceivingEndpoint recipient; - try { - recipient = request.GetRecipient(); - } catch (ArgumentException ex) { - Logger.OAuth.WarnFormat("Unrecognized HTTP request: " + ex.ToString()); - return null; - } - - // Deserialize the message using all the data we've collected. - var message = (IDirectedProtocolMessage)this.Receive(fields, recipient); - return message; - } - - return null; - } - - /// <summary> - /// Gets the protocol message that may be in the given HTTP response. - /// </summary> - /// <param name="response">The response that is anticipated to contain an protocol message.</param> - /// <returns> - /// The deserialized message parts, if found. Null otherwise. - /// </returns> - /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> - protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { - // We never expect resource servers to send out direct requests, - // and therefore won't have direct responses. - throw new NotImplementedException(); - } - - /// <summary> - /// Queues a message for sending in the response stream where the fields - /// are sent in the response stream in querystring style. - /// </summary> - /// <param name="response">The message to send as a response.</param> - /// <returns> - /// The pending user agent redirect based message to be sent as an HttpResponse. - /// </returns> - /// <remarks> - /// This method implements spec OAuth V1.0 section 5.3. - /// </remarks> - protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) { - var webResponse = new OutgoingWebResponse(); - - // The only direct response from a resource server is a 401 Unauthorized error. - var unauthorizedResponse = response as UnauthorizedResponse; - ErrorUtilities.VerifyInternal(unauthorizedResponse != null, "Only unauthorized responses are expected."); - - // First initialize based on the specifics within the message. - ApplyMessageTemplate(response, webResponse); - if (!(response is IHttpDirectResponse)) { - webResponse.Status = HttpStatusCode.Unauthorized; - } - - // Now serialize all the message parts into the WWW-Authenticate header. - var fields = this.MessageDescriptions.GetAccessor(response); - webResponse.Headers[HttpResponseHeader.WwwAuthenticate] = MessagingUtilities.AssembleAuthorizationHeader(Protocol.BearerHttpAuthorizationScheme, fields); - return webResponse; - } - - /// <summary> - /// Searches for a bearer access token in the request. - /// </summary> - /// <param name="request">The request.</param> - /// <returns>The bearer access token, if one exists. Otherwise <c>null</c>.</returns> - private static string SearchForBearerAccessTokenInRequest(HttpRequestBase request) { - Requires.NotNull(request, "request"); - - // First search the authorization header. - string authorizationHeader = request.Headers[HttpRequestHeaders.Authorization]; - if (!string.IsNullOrEmpty(authorizationHeader) && authorizationHeader.StartsWith(Protocol.BearerHttpAuthorizationSchemeWithTrailingSpace, StringComparison.OrdinalIgnoreCase)) { - return authorizationHeader.Substring(Protocol.BearerHttpAuthorizationSchemeWithTrailingSpace.Length); - } - - // Failing that, scan the entity - if (!string.IsNullOrEmpty(request.Headers[HttpRequestHeaders.ContentType])) { - var contentType = new ContentType(request.Headers[HttpRequestHeaders.ContentType]); - if (string.Equals(contentType.MediaType, HttpFormUrlEncoded, StringComparison.Ordinal)) { - if (request.Form[Protocol.BearerTokenEncodedUrlParameterName] != null) { - return request.Form[Protocol.BearerTokenEncodedUrlParameterName]; - } - } - } - - // Finally, check the least desirable location: the query string - var unrewrittenQuery = request.GetQueryStringBeforeRewriting(); - if (!string.IsNullOrEmpty(unrewrittenQuery[Protocol.BearerTokenEncodedUrlParameterName])) { - return unrewrittenQuery[Protocol.BearerTokenEncodedUrlParameterName]; - } - - return null; - } - } -} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/RefreshToken.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/RefreshToken.cs deleted file mode 100644 index 993583c..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/RefreshToken.cs +++ /dev/null @@ -1,56 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="RefreshToken.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth2.ChannelElements { - using System; - using System.Diagnostics.Contracts; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.Messaging.Bindings; - - /// <summary> - /// The refresh token issued to a client by an authorization server that allows the client - /// to periodically obtain new short-lived access tokens. - /// </summary> - internal class RefreshToken : AuthorizationDataBag { - /// <summary> - /// The name of the bucket for symmetric keys used to sign refresh tokens. - /// </summary> - internal const string RefreshTokenKeyBucket = "https://localhost/dnoa/oauth_refresh_token"; - - /// <summary> - /// Initializes a new instance of the <see cref="RefreshToken"/> class. - /// </summary> - public RefreshToken() { - } - - /// <summary> - /// Initializes a new instance of the <see cref="RefreshToken"/> class. - /// </summary> - /// <param name="authorization">The authorization this refresh token should describe.</param> - internal RefreshToken(IAuthorizationDescription authorization) { - Requires.NotNull(authorization, "authorization"); - - this.ClientIdentifier = authorization.ClientIdentifier; - this.UtcCreationDate = authorization.UtcIssued; - this.User = authorization.User; - this.Scope.ResetContents(authorization.Scope); - } - - /// <summary> - /// Creates a formatter capable of serializing/deserializing a refresh token. - /// </summary> - /// <param name="cryptoKeyStore">The crypto key store.</param> - /// <returns> - /// A DataBag formatter. Never null. - /// </returns> - internal static IDataBagFormatter<RefreshToken> CreateFormatter(ICryptoKeyStore cryptoKeyStore) { - Requires.NotNull(cryptoKeyStore, "cryptoKeyStore"); - Contract.Ensures(Contract.Result<IDataBagFormatter<RefreshToken>>() != null); - - return new UriStyleMessageFormatter<RefreshToken>(cryptoKeyStore, RefreshTokenKeyBucket, signed: true, encrypted: true); - } - } -} |