diff options
19 files changed, 262 insertions, 173 deletions
diff --git a/samples/OAuthConsumer/Web.config b/samples/OAuthConsumer/Web.config index 720dd27..a162155 100644 --- a/samples/OAuthConsumer/Web.config +++ b/samples/OAuthConsumer/Web.config @@ -53,8 +53,8 @@ <add key="googleConsumerKey" value="anonymous"/> <add key="googleConsumerSecret" value="anonymous"/> <!-- Facebook sign-up: http://developers.facebook.com/setup/ --> - <add key="facebookAppID" value=""/> - <add key="facebookAppSecret" value=""/> + <add key="facebookAppID" value="367207604173"/> + <add key="facebookAppSecret" value="1df77e64055c4d7d3583cefdf2bc62d7"/> </appSettings> <connectionStrings/> diff --git a/src/DotNetOpenAuth.Test/OAuthWrap/MessageFactoryTests.cs b/src/DotNetOpenAuth.Test/OAuthWrap/MessageFactoryTests.cs index 805e1e3..bf77f7e 100644 --- a/src/DotNetOpenAuth.Test/OAuthWrap/MessageFactoryTests.cs +++ b/src/DotNetOpenAuth.Test/OAuthWrap/MessageFactoryTests.cs @@ -195,7 +195,7 @@ namespace DotNetOpenAuth.Test.OAuthWrap { { Protocol.client_id, "abc" }, { Protocol.redirect_uri, "abc" }, { Protocol.state, "abc" }, - { Protocol.wrap_scope, "abc" }, + { Protocol.scope, "abc" }, }; request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); Assert.IsInstanceOf(typeof(RichAppRequest), request); @@ -291,8 +291,8 @@ namespace DotNetOpenAuth.Test.OAuthWrap { [TestCase] public void AssertionRequest() { var fields = new Dictionary<string, string> { - { Protocol.wrap_assertion_format, "abc" }, - { Protocol.wrap_assertion, "abc" }, + { Protocol.format, "abc" }, + { Protocol.assertion, "abc" }, }; IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); Assert.IsInstanceOf(typeof(AssertionRequest), request); diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj index 3edb13d..31b51c5 100644 --- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj +++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj @@ -309,21 +309,21 @@ http://opensource.org/licenses/ms-pl.html <Compile Include="OAuthWrap\AuthorizationState.cs" /> <Compile Include="OAuthWrap\IClientTokenManager.cs" /> <Compile Include="OAuthWrap\Messages\Assertion\AssertionRequest.cs" /> - <Compile Include="OAuthWrap\Messages\Assertion\AssertionFailedResponse.cs" /> - <Compile Include="OAuthWrap\Messages\ClientCredentials\ClientAccountUsernamePasswordFailedResponse.cs" /> - <Compile Include="OAuthWrap\Messages\ClientCredentials\ClientAccountUsernamePasswordRequest.cs" /> - <Compile Include="OAuthWrap\Messages\ClientCredentials\ClientAccountUsernamePasswordSuccessResponse.cs" /> + <Compile Include="OAuthWrap\Messages\ClientCredentials\ClientCredentialsRequest.cs" /> <Compile Include="OAuthWrap\Messages\Assertion\AssertionSuccessResponse.cs" /> <Compile Include="OAuthWrap\Messages\IMessageWithClientState.cs" /> <Compile Include="OAuthWrap\Messages\RefreshAccessTokenRequest.cs" /> - <Compile Include="OAuthWrap\Messages\UserAgent\RichAppAccessTokenRequest.cs" /> - <Compile Include="OAuthWrap\Messages\UserAgent\RichAppRequest.cs" /> - <Compile Include="OAuthWrap\Messages\UserAgent\RichAppResponse.cs" /> - <Compile Include="OAuthWrap\Messages\UserAgent\RichAppAccessTokenSuccessResponse.cs" /> - <Compile Include="OAuthWrap\Messages\UserAgent\RichAppAccessTokenFailedResponse.cs" /> + <Compile Include="OAuthWrap\Messages\Device\RichAppAccessTokenRequest.cs" /> + <Compile Include="OAuthWrap\Messages\Device\RichAppRequest.cs" /> + <Compile Include="OAuthWrap\Messages\Device\RichAppResponse.cs" /> + <Compile Include="OAuthWrap\Messages\Device\RichAppAccessTokenSuccessResponse.cs" /> + <Compile Include="OAuthWrap\Messages\Device\RichAppAccessTokenFailedResponse.cs" /> <Compile Include="OAuthWrap\Messages\UnauthorizedResponse.cs" /> <Compile Include="OAuthWrap\Messages\AccessTokenFailedResponse.cs" /> <Compile Include="OAuthWrap\Messages\AccessTokenSuccessResponse.cs" /> + <Compile Include="OAuthWrap\Messages\UserAgent\UserAgentFailedResponse.cs" /> + <Compile Include="OAuthWrap\Messages\UserAgent\UserAgentRequest.cs" /> + <Compile Include="OAuthWrap\Messages\UserAgent\UserAgentSuccessResponse.cs" /> <Compile Include="OAuthWrap\Messages\UsernameAndPassword\UserNamePasswordCaptchaResponse.cs" /> <Compile Include="OAuthWrap\Messages\UsernameAndPassword\UserNamePasswordVerificationResponse.cs" /> <Compile Include="OAuthWrap\WrapUtilities.cs" /> @@ -779,19 +779,17 @@ http://opensource.org/licenses/ms-pl.html </ItemGroup> <ItemGroup> <SignDependsOn Include="BuildUnifiedProduct" /> - <DelaySignedAssemblies Include="$(ILMergeOutputAssembly); - $(OutputPath)CodeContracts\$(ProductName).Contracts.dll; - " /> - <Folder Include="OAuthWrap\Messages\Device\" /> + <DelaySignedAssemblies Include="$(ILMergeOutputAssembly);
 $(OutputPath)CodeContracts\$(ProductName).Contracts.dll;
 " /> </ItemGroup> - <PropertyGroup> - <!-- Don't sign the non-unified version of the assembly. --> - <SuppressTargetPathDelaySignedAssembly>true</SuppressTargetPathDelaySignedAssembly> - </PropertyGroup> + <ItemGroup /> + <PropertyGroup> + <!-- Don't sign the non-unified version of the assembly. --> + <SuppressTargetPathDelaySignedAssembly>true</SuppressTargetPathDelaySignedAssembly> + </PropertyGroup> <Target Name="BuildUnifiedProduct" DependsOnTargets="Build" Inputs="@(ILMergeInputAssemblies)" Outputs="$(ILMergeOutputAssembly)"> <MakeDir Directories="$(ILMergeOutputAssemblyDirectory)" /> <ILMerge ExcludeFile="$(ProjectRoot)ILMergeInternalizeExceptions.txt" InputAssemblies="@(ILMergeInputAssemblies)" OutputFile="$(ILMergeOutputAssembly)" KeyFile="$(PublicKeyFile)" DelaySign="true" /> </Target> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" /> -</Project> +</Project>
\ No newline at end of file diff --git a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapChannel.cs b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapChannel.cs index 0860baa..4cfffbf 100644 --- a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapChannel.cs +++ b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapChannel.cs @@ -104,6 +104,9 @@ namespace DotNetOpenAuth.OAuthWrap.ChannelElements { typeof(Messages.WebAppSuccessResponse), typeof(Messages.WebAppFailedResponse), typeof(Messages.WebAppAccessTokenRequest), + typeof(Messages.UserAgentRequest), + typeof(Messages.UserAgentSuccessResponse), + typeof(Messages.UserAgentFailedResponse), }; // Get all the MessageDescription objects through the standard cache, diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionFailedResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionFailedResponse.cs deleted file mode 100644 index 020192e..0000000 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionFailedResponse.cs +++ /dev/null @@ -1,21 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="AssertionFailedResponse.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuthWrap.Messages { - /// <summary> - /// A response from the Authorization Server to the Client to indicate that a - /// request for an access code failed, probably due to an invalid assertion. - /// </summary> - internal class AssertionFailedResponse : UnauthorizedResponse { - /// <summary> - /// Initializes a new instance of the <see cref="AssertionFailedResponse"/> class. - /// </summary> - /// <param name="request">The request.</param> - internal AssertionFailedResponse(AssertionRequest request) - : base(request) { - } - } -} diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionRequest.cs index ac693e4..1024a3f 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionRequest.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionRequest.cs @@ -16,6 +16,12 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// </summary> internal class AssertionRequest : MessageBase { /// <summary> + /// The type of message. + /// </summary> + [MessagePart(Protocol.type, IsRequired = true)] + private const string Type = "assertion"; + + /// <summary> /// Initializes a new instance of the <see cref="AssertionRequest"/> class. /// </summary> /// <param name="authorizationServer">The authorization server.</param> @@ -29,23 +35,33 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// Gets or sets the format of the assertion as defined by the Authorization Server. /// </summary> /// <value>The assertion format.</value> - [MessagePart(Protocol.wrap_assertion_format, IsRequired = true, AllowEmpty = false)] + [MessagePart(Protocol.format, IsRequired = true, AllowEmpty = false)] internal string AssertionFormat { get; set; } /// <summary> /// Gets or sets the assertion. /// </summary> /// <value>The assertion.</value> - [MessagePart(Protocol.wrap_assertion, IsRequired = true, AllowEmpty = false)] + [MessagePart(Protocol.assertion, IsRequired = true, AllowEmpty = false)] internal string Assertion { get; set; } /// <summary> /// Gets or sets an optional authorization scope as defined by the Authorization Server. /// </summary> - [MessagePart(Protocol.wrap_scope, IsRequired = false, AllowEmpty = true)] + [MessagePart(Protocol.scope, IsRequired = false, AllowEmpty = true)] internal string Scope { get; set; } /// <summary> + /// Gets or sets the type of the secret. + /// </summary> + /// <value>The type of the secret.</value> + /// <remarks> + /// OPTIONAL. The access token secret type as described by Section 5.3 (Cryptographic Tokens Requests). If omitted, the authorization server will issue a bearer token (an access token without a matching secret) as described by Section 5.2 (Bearer Token Requests). + /// </remarks> + [MessagePart(Protocol.secret_type, IsRequired = false, AllowEmpty = false)] + internal string SecretType { get; set; } + + /// <summary> /// Checks the message state for conformity to the protocol specification /// and throws an exception if the message is invalid. /// </summary> diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/ClientCredentials/ClientAccountUsernamePasswordFailedResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/ClientCredentials/ClientAccountUsernamePasswordFailedResponse.cs deleted file mode 100644 index 57ce588..0000000 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/ClientCredentials/ClientAccountUsernamePasswordFailedResponse.cs +++ /dev/null @@ -1,22 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="ClientAccountUsernamePasswordFailedResponse.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuthWrap.Messages { - /// <summary> - /// A response from the Authorization Server to the Client to indicate that a - /// request for an access code failed, probably due to an invalid account - /// name and password. - /// </summary> - internal class ClientAccountUsernamePasswordFailedResponse : UnauthorizedResponse { - /// <summary> - /// Initializes a new instance of the <see cref="ClientAccountUsernamePasswordFailedResponse"/> class. - /// </summary> - /// <param name="request">The request.</param> - internal ClientAccountUsernamePasswordFailedResponse(ClientAccountUsernamePasswordRequest request) - : base(request) { - } - } -} diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/ClientCredentials/ClientAccountUsernamePasswordSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/ClientCredentials/ClientAccountUsernamePasswordSuccessResponse.cs deleted file mode 100644 index 8bd6620..0000000 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/ClientCredentials/ClientAccountUsernamePasswordSuccessResponse.cs +++ /dev/null @@ -1,47 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="ClientAccountUsernamePasswordSuccessResponse.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuthWrap.Messages { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using DotNetOpenAuth.Messaging; - - /// <summary> - /// A response from the Authorization Server to the Client containing an access code. - /// </summary> - internal class ClientAccountUsernamePasswordSuccessResponse : MessageBase { - /// <summary> - /// Initializes a new instance of the <see cref="ClientAccountUsernamePasswordSuccessResponse"/> class. - /// </summary> - /// <param name="request">The request.</param> - internal ClientAccountUsernamePasswordSuccessResponse(ClientAccountUsernamePasswordRequest request) - : base(request) { - } - - /// <summary> - /// Gets or sets the refresh token. - /// </summary> - /// <value>The token.</value> - [MessagePart(Protocol.refresh_token, IsRequired = true, AllowEmpty = false)] - internal string RefreshToken { get; set; } - - /// <summary> - /// Gets or sets the access token. - /// </summary> - /// <value>The access token.</value> - [MessagePart(Protocol.access_token, IsRequired = true, AllowEmpty = false)] - internal string AccessToken { get; set; } - - /// <summary> - /// Gets or sets the lifetime of the access token. - /// </summary> - /// <value>The lifetime.</value> - [MessagePart(Protocol.expires_in, IsRequired = false, Encoder = typeof(TimespanSecondsEncoder))] - internal TimeSpan? Lifetime { get; set; } - } -} diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/ClientCredentials/ClientAccountUsernamePasswordRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/ClientCredentials/ClientCredentialsRequest.cs index 9f47c57..9ebbdd1 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/ClientCredentials/ClientAccountUsernamePasswordRequest.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/ClientCredentials/ClientCredentialsRequest.cs @@ -1,5 +1,5 @@ //----------------------------------------------------------------------- -// <copyright file="ClientAccountUsernamePasswordRequest.cs" company="Andrew Arnott"> +// <copyright file="ClientCredentialsRequest.cs" company="Andrew Arnott"> // Copyright (c) Andrew Arnott. All rights reserved. // </copyright> //----------------------------------------------------------------------- @@ -18,13 +18,13 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// <remarks> /// This is somewhat analogous to 2-legged OAuth. /// </remarks> - internal class ClientAccountUsernamePasswordRequest : MessageBase { + internal class ClientCredentialsRequest : MessageBase { /// <summary> - /// Initializes a new instance of the <see cref="ClientAccountUsernamePasswordRequest"/> class. + /// Initializes a new instance of the <see cref="ClientCredentialsRequest"/> class. /// </summary> /// <param name="authorizationServer">The authorization server.</param> /// <param name="version">The version.</param> - internal ClientAccountUsernamePasswordRequest(Uri authorizationServer, Version version) + internal ClientCredentialsRequest(Uri authorizationServer, Version version) : base(version, MessageTransport.Direct, authorizationServer) { this.HttpMethods = HttpDeliveryMethods.PostRequest; } @@ -46,7 +46,7 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// <summary> /// Gets or sets an optional authorization scope as defined by the Authorization Server. /// </summary> - [MessagePart(Protocol.wrap_scope, IsRequired = false, AllowEmpty = true)] + [MessagePart(Protocol.scope, IsRequired = false, AllowEmpty = true)] internal string Scope { get; set; } /// <summary> diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/RichAppAccessTokenFailedResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/Device/RichAppAccessTokenFailedResponse.cs index be4f001..be4f001 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/RichAppAccessTokenFailedResponse.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/Device/RichAppAccessTokenFailedResponse.cs diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/RichAppAccessTokenRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/Device/RichAppAccessTokenRequest.cs index 015ef54..015ef54 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/RichAppAccessTokenRequest.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/Device/RichAppAccessTokenRequest.cs diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/RichAppAccessTokenSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/Device/RichAppAccessTokenSuccessResponse.cs index 17979e4..17979e4 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/RichAppAccessTokenSuccessResponse.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/Device/RichAppAccessTokenSuccessResponse.cs diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/RichAppRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/Device/RichAppRequest.cs index 49ded9a..b392c52 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/RichAppRequest.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/Device/RichAppRequest.cs @@ -16,13 +16,17 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// authorization to access user Protected Data. /// </summary> internal class RichAppRequest : MessageBase { + [MessagePart(Protocol.type, IsRequired = true)] + private const string MessageType = "device_code"; + /// <summary> /// Initializes a new instance of the <see cref="RichAppRequest"/> class. /// </summary> - /// <param name="authorizationServer">The authorization server.</param> + /// <param name="tokenEndpoint">The authorization server.</param> /// <param name="version">The version.</param> - internal RichAppRequest(Uri authorizationServer, Version version) - : base(version, MessageTransport.Indirect, authorizationServer) { + internal RichAppRequest(Uri tokenEndpoint, Version version) + : base(version, MessageTransport.Direct, tokenEndpoint) { + this.HttpMethods = HttpDeliveryMethods.GetRequest; } /// <summary> @@ -33,36 +37,10 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { internal string ClientIdentifier { get; set; } /// <summary> - /// Gets or sets the callback URL. - /// </summary> - /// <value> - /// An absolute URL to which the Authorization Server will redirect the User back after - /// the user has approved the authorization request. - /// </value> - /// <remarks> - /// Authorization Servers MAY require that the wrap_callback URL match the previously - /// registered value for the Client Identifier. - /// </remarks> - [MessagePart(Protocol.redirect_uri, IsRequired = false, AllowEmpty = false)] - internal Uri Callback { get; set; } - - /// <summary> - /// Gets or sets state of the client that should be sent back with the authorization response. - /// </summary> - /// <value> - /// An opaque value that Clients can use to maintain state associated with this request. - /// </value> - /// <remarks> - /// If this value is present, the Authorization Server MUST return it to the Client's Callback URL. - /// </remarks> - [MessagePart(Protocol.state, IsRequired = false, AllowEmpty = true)] - internal string ClientState { get; set; } - - /// <summary> /// Gets or sets the scope. /// </summary> /// <value>The Authorization Server MAY define authorization scope values for the Client to include.</value> - [MessagePart(Protocol.wrap_scope, IsRequired = false, AllowEmpty = true)] + [MessagePart(Protocol.scope, IsRequired = false, AllowEmpty = true)] internal string Scope { get; set; } } } diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/RichAppResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/Device/RichAppResponse.cs index 48561cf..4a93a45 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/RichAppResponse.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/Device/RichAppResponse.cs @@ -19,10 +19,9 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// <summary> /// Initializes a new instance of the <see cref="RichAppResponse"/> class. /// </summary> - /// <param name="clientCallback">The client callback.</param> - /// <param name="version">The version.</param> - internal RichAppResponse(Uri clientCallback, Version version) - : base(version, MessageTransport.Indirect, clientCallback) { + /// <param name="request">The request.</param> + internal RichAppResponse(RichAppRequest request) + : base(request) { } /// <summary> @@ -36,16 +35,30 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { internal string VerificationCode { get; set; } /// <summary> - /// Gets or sets state of the client that should be sent back with the authorization response. + /// Gets or sets the code the user must enter on the authorization page. /// </summary> - /// <value> - /// An opaque value that Clients can use to maintain state associated with this request. - /// </value> - /// <remarks> - /// This parameter is required if the Client included it in <see cref="RichAppRequest.ClientState"/>. - /// </remarks> - [MessagePart(Protocol.state, IsRequired = false, AllowEmpty = true)] - internal string ClientState { get; set; } + /// <value>The user code.</value> + [MessagePart(Protocol.user_code, IsRequired = true, AllowEmpty = false)] + internal string UserCode { get; set; } + + /// <summary> + /// Gets or sets the user authorization URI on the authorization server. + /// </summary> + [MessagePart(Protocol.user_uri, IsRequired = true)] + internal Uri AuthorizationUri { get; set; } + + /// <summary> + /// Gets or sets the lifetime. + /// </summary> + /// <value>The lifetime.</value> + [MessagePart(Protocol.expires_in, IsRequired = false, Encoder = typeof(TimespanSecondsEncoder))] + internal TimeSpan? Lifetime { get; set; } + + /// <summary> + /// Gets or sets the minimum amount of time that the client SHOULD wait between polling requests to the token endpoint. + /// </summary> + [MessagePart(Protocol.interval, IsRequired = false, Encoder = typeof(TimespanSecondsEncoder))] + internal TimeSpan? PollingInterval { get; set; } /// <summary> /// Gets a value indicating whether the user granted the authorization request. diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/UserAgentRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/UserAgentRequest.cs new file mode 100644 index 0000000..4aa1021 --- /dev/null +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/UserAgentRequest.cs @@ -0,0 +1,91 @@ +//----------------------------------------------------------------------- +// <copyright file="UserAgentRequest.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuthWrap.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using DotNetOpenAuth.Messaging; + + internal class UserAgentRequest : MessageBase { + /// <summary> + /// The type of message. + /// </summary> + [MessagePart(Protocol.type, IsRequired = true)] + private const string Type = "user_agent"; + + /// <summary> + /// Initializes a new instance of the <see cref="UserAgentRequest"/> class. + /// </summary> + /// <param name="authorizationEndpoint">The authorization endpoint.</param> + /// <param name="version">The version.</param> + internal UserAgentRequest(Uri authorizationEndpoint, Version version) + : base(version, MessageTransport.Indirect, authorizationEndpoint) { + } + + /// <summary> + /// Gets or sets state of the client that should be sent back with the authorization response. + /// </summary> + /// <value> + /// An opaque value that Clients can use to maintain state associated with this request. + /// </value> + /// <remarks> + /// REQUIRED. The client identifier as described in Section 3.4 (Client Credentials). + /// </remarks> + [MessagePart(Protocol.state, IsRequired = false, AllowEmpty = true)] + public string ClientState { get; set; } + + /// <summary> + /// Gets or sets the identifier by which this client is known to the Authorization Server. + /// </summary> + [MessagePart(Protocol.client_id, IsRequired = true, AllowEmpty = false)] + internal string ClientIdentifier { get; set; } + + /// <summary> + /// Gets or sets the callback URL. + /// </summary> + /// <value> + /// An absolute URL to which the Authorization Server will redirect the User back after + /// the user has approved the authorization request. + /// </value> + /// <remarks> + /// REQUIRED unless a redirection URI has been established between the client and authorization server via other means. An absolute URI to which the authorization server will redirect the user-agent to when the end-user authorization step is completed. The authorization server MAY require the client to pre-register their redirection URI. The redirection URI MUST NOT include a query component as defined by [RFC3986] (Berners-Lee, T., Fielding, R., and L. Masinter, “Uniform Resource Identifier (URI): Generic Syntax,” January 2005.) section 3 if the state parameter is present. + /// </remarks> + [MessagePart(Protocol.redirect_uri, IsRequired = false, AllowEmpty = false)] + internal Uri Callback { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether the authorization server is + /// required to redirect the browser back to the client immediately. + /// </summary> + /// <remarks> + /// OPTIONAL. The parameter value must be set to true or false. If set to true, the authorization server MUST NOT prompt the end-user to authenticate or approve access. Instead, the authorization server attempts to establish the end-user's identity via other means (e.g. browser cookies) and checks if the end-user has previously approved an identical access request by the same client and if that access grant is still active. If the authorization server does not support an immediate check or if it is unable to establish the end-user's identity or approval status, it MUST deny the request without prompting the end-user. Defaults to false if omitted. + /// </remarks> + [MessagePart(Protocol.immediate, IsRequired = false, AllowEmpty = false)] + internal bool? Immediate { get; set; } + + /// <summary> + /// Gets or sets the scope. + /// </summary> + /// <value>The scope.</value> + /// <remarks> + /// OPTIONAL. The scope of the access request expressed as a list of space-delimited strings. The value of the scope parameter is defined by the authorization server. If the value contains multiple space-delimited strings, their order does not matter, and each string adds additional access range to the requested scope. + /// </remarks> + [MessagePart(Protocol.scope, IsRequired = false, AllowEmpty = true)] + internal string Scope { get; set; } + + /// <summary> + /// Gets or sets the type of the secret. + /// </summary> + /// <value>The type of the secret.</value> + /// <remarks> + /// OPTIONAL. The access token secret type as described by Section 5.3 (Cryptographic Tokens Requests). If omitted, the authorization server will issue a bearer token (an access token without a matching secret) as described by Section 5.2 (Bearer Token Requests). + /// </remarks> + [MessagePart(Protocol.secret_type, IsRequired = false, AllowEmpty = false)] + internal string SecretType { get; set; } + } +} diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/UserAgentSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/UserAgentSuccessResponse.cs new file mode 100644 index 0000000..c8f073f --- /dev/null +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/UserAgent/UserAgentSuccessResponse.cs @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------- +// <copyright file="UserAgentSuccessResponse.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuthWrap.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using DotNetOpenAuth.Messaging; + + internal class UserAgentSuccessResponse : MessageBase { + /// <summary> + /// Initializes a new instance of the <see cref="UserAgentSuccessResponse"/> class. + /// </summary> + /// <param name="clientCallback">The client callback.</param> + /// <param name="version">The version.</param> + internal UserAgentSuccessResponse(Uri clientCallback, Version version) + : base (version, MessageTransport.Indirect, clientCallback) + { + } + + [MessagePart(Protocol.access_token, IsRequired = true, AllowEmpty = false)] + internal string AccessToken { get; set; } + + /// <summary> + /// Gets or sets the lifetime of the access token. + /// </summary> + /// <value>The lifetime.</value> + [MessagePart(Protocol.expires_in, IsRequired = false, Encoder = typeof(TimespanSecondsEncoder))] + internal TimeSpan? Lifetime { get; set; } + + /// <summary> + /// Gets or sets the refresh token. + /// </summary> + /// <value>The refresh token.</value> + /// <remarks> + /// OPTIONAL. The refresh token used to obtain new access tokens using the same end-user access grant as described in Section 6 (Refreshing an Access Token). + /// </remarks> + [MessagePart(Protocol.refresh_token, IsRequired = false, AllowEmpty = false)] + internal string RefreshToken { get; set; } + + /// <summary> + /// Gets or sets the access token secret. + /// </summary> + /// <value>The access token secret.</value> + /// <remarks> + /// REQUIRED if requested by the client. The corresponding access token secret as requested by the client. + /// </remarks> + [MessagePart(Protocol.access_token_secret, IsRequired = false, AllowEmpty = false)] + internal string AccessTokenSecret { get; set; } + + /// <summary> + /// Gets or sets the state. + /// </summary> + /// <value>The state.</value> + /// <remarks> + /// REQUIRED if the state parameter was present in the client authorization request. Set to the exact value received from the client. + /// </remarks> + [MessagePart(Protocol.state, IsRequired = false, AllowEmpty = true)] + internal string ClientState { get; set; } + } +} diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordRequest.cs index 212611a..7ce570a 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordRequest.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordRequest.cs @@ -69,7 +69,7 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// Gets or sets the scope. /// </summary> /// <value>The scope.</value> - [MessagePart(Protocol.wrap_scope, IsRequired = false, AllowEmpty = true)] + [MessagePart(Protocol.scope, IsRequired = false, AllowEmpty = true)] internal string Scope { get; set; } /// <summary> diff --git a/src/DotNetOpenAuth/OAuthWrap/Protocol.cs b/src/DotNetOpenAuth/OAuthWrap/Protocol.cs index 8882aea..9ee7091 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Protocol.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Protocol.cs @@ -54,9 +54,9 @@ namespace DotNetOpenAuth.OAuthWrap { internal const string client_id = "client_id"; /// <summary> - /// The "wrap_scope" string. + /// The "scope" string. /// </summary> - internal const string wrap_scope = "wrap_scope"; + internal const string scope = "scope"; /// <summary> /// The "immediate" string. @@ -74,6 +74,21 @@ namespace DotNetOpenAuth.OAuthWrap { internal const string code = "code"; /// <summary> + /// The "user_code" string. + /// </summary> + internal const string user_code = "user_code"; + + /// <summary> + /// The "user_uri" string. + /// </summary> + internal const string user_uri = "user_uri"; + + /// <summary> + /// The "interval" string. + /// </summary> + internal const string interval = "interval"; + + /// <summary> /// The "wrap_verification_url" string. /// </summary> internal const string wrap_verification_url = "wrap_verification_url"; @@ -124,14 +139,14 @@ namespace DotNetOpenAuth.OAuthWrap { internal const string wrap_name = "wrap_name"; /// <summary> - /// The "wrap_assertion_format" string. + /// The "format" string. /// </summary> - internal const string wrap_assertion_format = "wrap_assertion_format"; + internal const string format = "format"; /// <summary> - /// The "wrap_assertion" string. + /// The "assertion" string. /// </summary> - internal const string wrap_assertion = "wrap_assertion"; + internal const string assertion = "assertion"; /// <summary> /// The "wrap_SAML" string. diff --git a/src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs b/src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs index 83bf48b..1a43d78 100644 --- a/src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs +++ b/src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs @@ -75,8 +75,8 @@ namespace DotNetOpenAuth.OAuthWrap { Contract.Requires<InvalidOperationException>(!string.IsNullOrEmpty(this.ClientIdentifier)); Contract.Requires<InvalidOperationException>(!string.IsNullOrEmpty(this.ClientSecret)); - var response = this.Channel.ReadFromRequest<IMessageWithClientState>(request); - if (response != null) { + IMessageWithClientState response; + if (this.Channel.TryReadFromRequest<IMessageWithClientState>(request, out response)) { IAuthorizationState authorizationState = this.TokenManager.GetAuthorizationState(request.UrlBeforeRewriting, response.ClientState); ErrorUtilities.VerifyProtocol(authorizationState != null, "Unexpected OAuth authorization response received with callback and client state that does not match an expected value."); var success = response as WebAppSuccessResponse; |