diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2010-05-31 23:11:30 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2010-05-31 23:11:30 -0700 |
commit | f00c9430bb49d0dcd54005c852fd2b7d7de2ce7e (patch) | |
tree | d92e72ff24191c3315078b438ea6204af9ab17dc | |
parent | 7f625de00c6daafd1c8e21b27b4b2dce8ce224b0 (diff) | |
download | DotNetOpenAuth-f00c9430bb49d0dcd54005c852fd2b7d7de2ce7e.zip DotNetOpenAuth-f00c9430bb49d0dcd54005c852fd2b7d7de2ce7e.tar.gz DotNetOpenAuth-f00c9430bb49d0dcd54005c852fd2b7d7de2ce7e.tar.bz2 |
Lots of refactoring as we gather the token handling into centralized code.
14 files changed, 202 insertions, 72 deletions
diff --git a/samples/OAuthServiceProvider/Code/OAuth2AuthorizationServer.cs b/samples/OAuthServiceProvider/Code/OAuth2AuthorizationServer.cs index 70474f2..6a36a83 100644 --- a/samples/OAuthServiceProvider/Code/OAuth2AuthorizationServer.cs +++ b/samples/OAuthServiceProvider/Code/OAuth2AuthorizationServer.cs @@ -8,6 +8,7 @@ using DotNetOpenAuth.Messaging.Bindings; using DotNetOpenAuth.OAuth.ChannelElements; using DotNetOpenAuth.OAuthWrap; + using DotNetOpenAuth.OAuthWrap.ChannelElements; internal class OAuth2AuthorizationServer : IAuthorizationServer { private static readonly byte[] secret; @@ -42,5 +43,10 @@ } #endregion + + public bool IsAuthorizationValid(IAuthorizationDescription authorization) { + // We don't support revoking tokens yet. + return true; + } } }
\ No newline at end of file diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj index 5131b7e..f4a02d4 100644 --- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj +++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj @@ -309,6 +309,7 @@ http://opensource.org/licenses/ms-pl.html <Compile Include="Messaging\StandardMessageFactory.cs" /> <Compile Include="OAuthWrap\AuthorizationServerBase.cs" /> <Compile Include="OAuthWrap\AuthorizationState.cs" /> + <Compile Include="OAuthWrap\ChannelElements\AccessRequestBindingElement.cs" /> <Compile Include="OAuthWrap\ChannelElements\AccessToken.cs" /> <Compile Include="OAuthWrap\ChannelElements\AuthorizationDataBag.cs" /> <Compile Include="OAuthWrap\ChannelElements\AuthServerBindingElementBase.cs" /> @@ -316,7 +317,6 @@ http://opensource.org/licenses/ms-pl.html <Compile Include="OAuthWrap\ChannelElements\IAuthorizationDescription.cs" /> <Compile Include="OAuthWrap\ChannelElements\OAuthWrapResourceServerChannel.cs" /> <Compile Include="Messaging\StandardMessageFactoryChannel.cs" /> - <Compile Include="OAuthWrap\ChannelElements\RefreshAccessTokenBindingElement.cs" /> <Compile Include="OAuthWrap\ChannelElements\RefreshToken.cs" /> <Compile Include="OAuthWrap\ChannelElements\DataBag.cs" /> <Compile Include="OAuthWrap\ChannelElements\TimestampEncoder.cs" /> diff --git a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/AccessRequestBindingElement.cs b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/AccessRequestBindingElement.cs new file mode 100644 index 0000000..9aa210f --- /dev/null +++ b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/AccessRequestBindingElement.cs @@ -0,0 +1,84 @@ +namespace DotNetOpenAuth.OAuthWrap.ChannelElements { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.Messaging.Bindings; + + /// <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() { + } + + public override MessageProtections Protection { + get { return MessageProtections.None; } + } + + protected TimeSpan AccessTokenLifetime { + get { return TimeSpan.FromHours(1); } + } + + public override MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) { + var tokenRequest = message as ITokenCarryingRequest; + if (tokenRequest != null) { + var tokenBag = (AuthorizationDataBag)tokenRequest.AuthorizationDescription; + tokenRequest.CodeOrToken = tokenBag.Encode(); + + return MessageProtections.None; + } + + return null; + } + + public override MessageProtections? ProcessIncomingMessage(IProtocolMessage message) { + var tokenRequest = message as ITokenCarryingRequest; + if (tokenRequest != null) { + try { + switch (tokenRequest.CodeOrTokenType) { + case CodeOrTokenType.VerificationCode: + tokenRequest.AuthorizationDescription = VerificationCode.Decode(this.OAuthChannel, tokenRequest.CodeOrToken, message); + break; + case CodeOrTokenType.RefreshToken: + tokenRequest.AuthorizationDescription = RefreshToken.Decode(this.OAuthChannel, tokenRequest.CodeOrToken, message); + break; + case CodeOrTokenType.AccessToken: + tokenRequest.AuthorizationDescription = AccessToken.Decode(this.OAuthChannel, tokenRequest.CodeOrToken, this.AccessTokenLifetime, message); + break; + default: + throw ErrorUtilities.ThrowInternal("Unexpected value for CodeOrTokenType: " + tokenRequest.CodeOrTokenType); + } + } catch (ExpiredMessageException ex) { + throw ErrorUtilities.Wrap(ex, Protocol.authorization_expired); + } + + var accessRequest = message as IAccessTokenRequest; + 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, accessRequest.AuthorizationDescription.ClientIdentifier, StringComparison.Ordinal), Protocol.incorrect_client_credentials); + + // Check that the client secret is correct. + var client = this.AuthorizationServer.GetClientOrThrow(accessRequest.ClientIdentifier); + ErrorUtilities.VerifyProtocol(string.Equals(client.Secret, accessRequest.ClientSecret, StringComparison.Ordinal), Protocol.incorrect_client_credentials); + } + + // 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/OAuthWrap/ChannelElements/AuthServerWebServerFlowBindingElement.cs b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/AuthServerWebServerFlowBindingElement.cs index 2f7b49e..5974414 100644 --- a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/AuthServerWebServerFlowBindingElement.cs +++ b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/AuthServerWebServerFlowBindingElement.cs @@ -69,6 +69,7 @@ namespace DotNetOpenAuth.OAuthWrap.ChannelElements { var client = this.AuthorizationServer.GetClientOrThrow(authorizationRequest.ClientIdentifier); ErrorUtilities.VerifyProtocol(client.Callback == null || client.Callback == authorizationRequest.Callback, OAuthWrapStrings.CallbackMismatch, client.Callback, authorizationRequest.Callback); } + return null; } } diff --git a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/IAccessTokenRequest.cs b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/IAccessTokenRequest.cs index 3579955..426a87f 100644 --- a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/IAccessTokenRequest.cs +++ b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/IAccessTokenRequest.cs @@ -12,11 +12,27 @@ namespace DotNetOpenAuth.OAuthWrap.ChannelElements { using Messages; using Messaging; - internal interface IAccessTokenRequest : IDirectedProtocolMessage { + internal interface ITokenCarryingRequest : IDirectedProtocolMessage { + string CodeOrToken { get; set; } + + CodeOrTokenType CodeOrTokenType { get; } + + IAuthorizationDescription AuthorizationDescription { get; set; } + } + + internal interface IAccessTokenRequest : ITokenCarryingRequest { string ClientIdentifier { get; } - - string Scope { get; } - string SecretType { get; set; } + string ClientSecret { get; } + + string SecretType { get; } + } + + internal enum CodeOrTokenType { + VerificationCode, + + RefreshToken, + + AccessToken, } } diff --git a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapAuthorizationServerChannel.cs b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapAuthorizationServerChannel.cs index 0148b7a..3670ad9 100644 --- a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapAuthorizationServerChannel.cs +++ b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapAuthorizationServerChannel.cs @@ -70,7 +70,7 @@ namespace DotNetOpenAuth.OAuthWrap.ChannelElements { Contract.Requires<ArgumentNullException>(request != null, "request"); var response = new AccessTokenSuccessResponse(request) { - Scope = request.Scope, + Scope = request.AuthorizationDescription.Scope, Lifetime = TimeSpan.FromDays(1), // reasonable default for access token lifetime // TODO: code here to initialize the response AccessToken = "TODO", @@ -178,7 +178,7 @@ namespace DotNetOpenAuth.OAuthWrap.ChannelElements { if (authorizationServer != null) { bindingElements.Add(new AuthServerWebServerFlowBindingElement()); bindingElements.Add(new WebAppVerificationCodeBindingElement()); - bindingElements.Add(new RefreshAccessTokenBindingElement()); + bindingElements.Add(new AccessRequestBindingElement()); } return bindingElements.ToArray(); diff --git a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/RefreshAccessTokenBindingElement.cs b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/RefreshAccessTokenBindingElement.cs deleted file mode 100644 index 24aa1af..0000000 --- a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/RefreshAccessTokenBindingElement.cs +++ /dev/null @@ -1,46 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="RefreshAccessTokenBindingElement.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuthWrap.ChannelElements { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OAuthWrap.Messages; - - internal class RefreshAccessTokenBindingElement : AuthServerBindingElementBase { - /// <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; } - } - - public override MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) { - return null; - } - - public override MessageProtections? ProcessIncomingMessage(IProtocolMessage message) { - var request = message as RefreshAccessTokenRequest; - if (request != null) { - // Decode and validate the refresh token - var refreshToken = RefreshToken.Decode(this.OAuthChannel, request.RefreshToken, message); - - // Fill in the authorized access scope from the refresh token and fill in the property - // on the message so that others can read it later. - request.Scope = refreshToken.Scope; - - return MessageProtections.None; - } - - return null; - } - } -} diff --git a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/WebAppVerificationCodeBindingElement.cs b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/WebAppVerificationCodeBindingElement.cs index faf896a..679ffd1 100644 --- a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/WebAppVerificationCodeBindingElement.cs +++ b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/WebAppVerificationCodeBindingElement.cs @@ -52,9 +52,8 @@ namespace DotNetOpenAuth.OAuthWrap.ChannelElements { if (response != null) { var directResponse = (IDirectResponseProtocolMessage)response; var request = (WebAppRequest)directResponse.OriginatingRequest; - - var code = new VerificationCode(this.OAuthChannel, request.ClientIdentifier, request.Callback, request.Scope, response.AuthorizingUsername); - response.VerificationCode = code.Encode(); + ITokenCarryingRequest tokenCarryingResponse = response; + tokenCarryingResponse.AuthorizationDescription = new VerificationCode(this.OAuthChannel, request.ClientIdentifier, request.Callback, request.Scope, response.AuthorizingUsername); return MessageProtections.None; } @@ -82,14 +81,8 @@ namespace DotNetOpenAuth.OAuthWrap.ChannelElements { public override MessageProtections? ProcessIncomingMessage(IProtocolMessage message) { var request = message as WebAppAccessTokenRequest; if (request != null) { - var client = this.AuthorizationServer.GetClient(request.ClientIdentifier); - ErrorUtilities.VerifyProtocol(string.Equals(client.Secret, request.ClientSecret, StringComparison.Ordinal), Protocol.incorrect_client_credentials); - - var verificationCode = VerificationCode.Decode(this.OAuthChannel, request.VerificationCode, message); - ErrorUtilities.VerifyProtocol(string.Equals(verificationCode.ClientIdentifier, request.ClientIdentifier, StringComparison.Ordinal), Protocol.bad_verification_code); - verificationCode.VerifyCallback(request.Callback); - - request.Scope = verificationCode.Scope; + IAccessTokenRequest accessRequest = request; + ((VerificationCode)accessRequest.AuthorizationDescription).VerifyCallback(request.Callback); return MessageProtections.None; } diff --git a/src/DotNetOpenAuth/OAuthWrap/IAuthorizationServer.cs b/src/DotNetOpenAuth/OAuthWrap/IAuthorizationServer.cs index fccf067..8d5bea4 100644 --- a/src/DotNetOpenAuth/OAuthWrap/IAuthorizationServer.cs +++ b/src/DotNetOpenAuth/OAuthWrap/IAuthorizationServer.cs @@ -13,6 +13,7 @@ namespace DotNetOpenAuth.OAuthWrap { using System.Linq; using System.Text; using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuthWrap.ChannelElements; [ContractClass(typeof(IAuthorizationServerContract))] public interface IAuthorizationServer { @@ -24,6 +25,30 @@ namespace DotNetOpenAuth.OAuthWrap { /// <exception cref="ArgumentException">Thrown when no client with the given identifier is registered with this authorization server.</exception> IConsumerDescription GetClient(string clientIdentifier); + /// <summary> + /// Determines whether a described authorization is (still) valid. + /// </summary> + /// <param name="authorization">The authorization.</param> + /// <returns> + /// <c>true</c> if the original authorization is still valid; otherwise, <c>false</c>. + /// </returns> + /// <remarks> + /// <para>When establishing that an authorization is still valid, + /// it's very important to only match on recorded authorizations that + /// meet these criteria:</para> + /// 1) The client identifier matches. + /// 2) The user account matches. + /// 3) The scope on the recorded authorization must include all scopes in the given authorization. + /// 4) The date the recorded authorization was issued must be <em>no later</em> that the date the given authorization was issued. + /// <para>One possible scenario is where the user authorized a client, later revoked authorization, + /// and even later reinstated authorization. This subsequent recorded authorization + /// would not satisfy requirement #4 in the above list. This is important because the revocation + /// the user went through should invalidate all previously issued tokens as a matter of + /// security in the event the user was revoking access in order to sever authorization on a stolen + /// account or piece of hardware in which the tokens were stored. </para> + /// </remarks> + bool IsAuthorizationValid(IAuthorizationDescription authorization); + byte[] Secret { get; } INonceStore VerificationCodeNonceStore { get; } @@ -53,6 +78,11 @@ namespace DotNetOpenAuth.OAuthWrap { throw new NotImplementedException(); } } + + bool IAuthorizationServer.IsAuthorizationValid(IAuthorizationDescription authorization) { + Contract.Requires<ArgumentNullException>(authorization != null, "authorization"); + throw new NotImplementedException(); + } } } diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/AccessProtectedResourceRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/AccessProtectedResourceRequest.cs index 7b5569a..1f2efaa 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/AccessProtectedResourceRequest.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/AccessProtectedResourceRequest.cs @@ -12,7 +12,7 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { using ChannelElements; using Messaging; - internal class AccessProtectedResourceRequest : MessageBase { + internal class AccessProtectedResourceRequest : MessageBase, ITokenCarryingRequest { /// <summary> /// Initializes a new instance of the <see cref="AccessProtectedResourceRequest"/> class. /// </summary> @@ -22,6 +22,17 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { : base(version, MessageTransport.Direct, recipient) { } + CodeOrTokenType ITokenCarryingRequest.CodeOrTokenType { + get { return CodeOrTokenType.AccessToken; } + } + + string ITokenCarryingRequest.CodeOrToken { + get { return this.AccessToken; } + set { this.AccessToken = value; } + } + + IAuthorizationDescription ITokenCarryingRequest.AuthorizationDescription { get; set; } + [MessagePart("token", IsRequired = true, AllowEmpty = false)] internal string AccessToken { get; set; } diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenRequest.cs index 8ab77ff..9b322f5 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenRequest.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenRequest.cs @@ -30,6 +30,17 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { : base(version, MessageTransport.Direct, tokenEndpoint) { } + CodeOrTokenType ITokenCarryingRequest.CodeOrTokenType { + get { return CodeOrTokenType.RefreshToken; } + } + + string ITokenCarryingRequest.CodeOrToken { + get { return this.RefreshToken; } + set { this.RefreshToken = value; } + } + + IAuthorizationDescription ITokenCarryingRequest.AuthorizationDescription { get; set; } + /// <summary> /// Gets or sets the type of the secret. /// </summary> @@ -47,8 +58,6 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { [MessagePart(Protocol.client_id, IsRequired = true, AllowEmpty = false)] public string ClientIdentifier { get; set; } - public string Scope { get; set; } - /// <summary> /// Gets or sets the client secret. /// </summary> @@ -57,7 +66,7 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// REQUIRED if the client identifier has a matching secret. The client secret as described in Section 3.4 (Client Credentials). /// </remarks> [MessagePart(Protocol.client_secret, IsRequired = false, AllowEmpty = true)] - internal string ClientSecret { get; set; } + public string ClientSecret { get; set; } /// <summary> /// Gets or sets the refresh token. diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppAccessTokenRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppAccessTokenRequest.cs index ff81f14..78cd5e0 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppAccessTokenRequest.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppAccessTokenRequest.cs @@ -50,6 +50,17 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { this.Format = ResponseFormat.Form; } + CodeOrTokenType ITokenCarryingRequest.CodeOrTokenType { + get { return CodeOrTokenType.VerificationCode; } + } + + string ITokenCarryingRequest.CodeOrToken { + get { return this.VerificationCode; } + set { this.VerificationCode = value; } + } + + IAuthorizationDescription ITokenCarryingRequest.AuthorizationDescription { get; set; } + /// <summary> /// Gets or sets the identifier by which this client is known to the Authorization Server. /// </summary> @@ -65,7 +76,7 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// REQUIRED if the client identifier has a matching secret. The client secret as described in Section 3.4 (Client Credentials). /// </remarks> [MessagePart(Protocol.client_secret, IsRequired = false, AllowEmpty = true)] - internal string ClientSecret { get; set; } + public string ClientSecret { get; set; } /// <summary> /// Gets or sets the verification code previously communicated to the Client @@ -94,8 +105,6 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { [MessagePart(Protocol.secret_type, IsRequired = false, AllowEmpty = false)] public string SecretType { get; set; } - public string Scope { get; internal set; } - ResponseFormat IOAuthDirectResponseFormat.Format { get { return this.Format.HasValue ? this.Format.Value : ResponseFormat.Json; } } diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppSuccessResponse.cs index 2cfb017..277653e 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppSuccessResponse.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppSuccessResponse.cs @@ -8,13 +8,14 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { using System; using System.Diagnostics.Contracts; using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuthWrap.ChannelElements; /// <summary> /// The message sent by the Authorization Server to the Client via the user agent /// to indicate that user authorization was granted, and to return the user /// to the Client where they started their experience. /// </summary> - internal class WebAppSuccessResponse : MessageBase, IMessageWithClientState { + internal class WebAppSuccessResponse : MessageBase, IMessageWithClientState, ITokenCarryingRequest { /// <summary> /// Initializes a new instance of the <see cref="WebAppSuccessResponse"/> class. /// </summary> @@ -38,6 +39,17 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { ((IMessageWithClientState)this).ClientState = ((IMessageWithClientState)request).ClientState; } + string ITokenCarryingRequest.CodeOrToken { + get { return this.VerificationCode; } + set { this.VerificationCode = value; } + } + + CodeOrTokenType ITokenCarryingRequest.CodeOrTokenType { + get { return CodeOrTokenType.VerificationCode; } + } + + IAuthorizationDescription ITokenCarryingRequest.AuthorizationDescription { get; set; } + /// <summary> /// Gets or sets some state as provided by the client in the authorization request. /// </summary> diff --git a/src/DotNetOpenAuth/OAuthWrap/Protocol.cs b/src/DotNetOpenAuth/OAuthWrap/Protocol.cs index 4d71ef7..08329b9 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Protocol.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Protocol.cs @@ -59,6 +59,11 @@ namespace DotNetOpenAuth.OAuthWrap { internal const string incorrect_client_credentials = "incorrect_client_credentials"; /// <summary> + /// The "authorization_expired" string. + /// </summary> + internal const string authorization_expired = "authorization_expired"; + + /// <summary> /// The "redirect_uri" string. /// </summary> internal const string redirect_uri = "redirect_uri"; |