diff options
Diffstat (limited to 'src')
88 files changed, 1686 insertions, 978 deletions
diff --git a/src/DotNetOpenAuth.Core/Messaging/Channel.cs b/src/DotNetOpenAuth.Core/Messaging/Channel.cs index 16e39d3..016a2b6 100644 --- a/src/DotNetOpenAuth.Core/Messaging/Channel.cs +++ b/src/DotNetOpenAuth.Core/Messaging/Channel.cs @@ -143,7 +143,10 @@ namespace DotNetOpenAuth.Messaging { /// A class prepared to analyze incoming messages and indicate what concrete /// message types can deserialize from it. /// </param> - /// <param name="bindingElements">The binding elements to use in sending and receiving messages.</param> + /// <param name="bindingElements"> + /// The binding elements to use in sending and receiving messages. + /// The order they are provided is used for outgoing messgaes, and reversed for incoming messages. + /// </param> protected Channel(IMessageFactory messageTypeProvider, params IChannelBindingElement[] bindingElements) { Requires.NotNull(messageTypeProvider, "messageTypeProvider"); diff --git a/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs b/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs index 9d4b93e..746efb1 100644 --- a/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs +++ b/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs @@ -146,6 +146,8 @@ namespace DotNetOpenAuth.Messaging { /// <returns>A non-null, non-empty value.</returns> [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "No apparent problem. False positive?")] public string Serialize(T message) { + Requires.NotNull(message, "message"); + message.UtcCreationDate = DateTime.UtcNow; if (this.decodeOnceOnly != null) { diff --git a/src/DotNetOpenAuth.Core/Messaging/StandardMessageFactoryChannel.cs b/src/DotNetOpenAuth.Core/Messaging/StandardMessageFactoryChannel.cs index 7a1d194..7ca5d45 100644 --- a/src/DotNetOpenAuth.Core/Messaging/StandardMessageFactoryChannel.cs +++ b/src/DotNetOpenAuth.Core/Messaging/StandardMessageFactoryChannel.cs @@ -31,7 +31,10 @@ namespace DotNetOpenAuth.Messaging { /// </summary> /// <param name="messageTypes">The message types that might be encountered.</param> /// <param name="versions">All the possible message versions that might be encountered.</param> - /// <param name="bindingElements">The binding elements to apply to the channel.</param> + /// <param name="bindingElements"> + /// The binding elements to use in sending and receiving messages. + /// The order they are provided is used for outgoing messgaes, and reversed for incoming messages. + /// </param> protected StandardMessageFactoryChannel(ICollection<Type> messageTypes, ICollection<Version> versions, params IChannelBindingElement[] bindingElements) : base(new StandardMessageFactory(), bindingElements) { Requires.NotNull(messageTypes, "messageTypes"); diff --git a/src/DotNetOpenAuth.Core/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.Core/Properties/AssemblyInfo.cs index e57b211..91d27f5 100644 --- a/src/DotNetOpenAuth.Core/Properties/AssemblyInfo.cs +++ b/src/DotNetOpenAuth.Core/Properties/AssemblyInfo.cs @@ -64,6 +64,7 @@ using System.Web.UI; [assembly: InternalsVisibleTo("DotNetOpenAuth.OpenIdOAuth, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.AuthorizationServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ClientAuthorization, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ResourceServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.Client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.Client.UI, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] @@ -88,6 +89,7 @@ using System.Web.UI; [assembly: InternalsVisibleTo("DotNetOpenAuth.OpenIdOAuth")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.AuthorizationServer")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ClientAuthorization")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ResourceServer")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.Client")] [assembly: InternalsVisibleTo("DotNetOpenAuth.AspNet.Test")] diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/DotNetOpenAuth.OAuth2.AuthorizationServer.csproj b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/DotNetOpenAuth.OAuth2.AuthorizationServer.csproj index f6b1a50..9498295 100644 --- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/DotNetOpenAuth.OAuth2.AuthorizationServer.csproj +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/DotNetOpenAuth.OAuth2.AuthorizationServer.csproj @@ -19,6 +19,26 @@ </PropertyGroup> <ItemGroup> <Compile Include="OAuth2\AuthorizationServer.cs" /> + <Compile Include="OAuth2\AuthServerStrings.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>AuthServerStrings.resx</DependentUpon> + </Compile> + <Compile Include="OAuth2\AuthServerUtilities.cs" /> + <Compile Include="OAuth2\ChannelElements\TokenCodeSerializationBindingElement.cs" /> + <Compile Include="OAuth2\ChannelElements\AccessTokenBindingElement.cs" /> + <Compile Include="OAuth2\ChannelElements\AuthorizationCode.cs" /> + <Compile Include="OAuth2\ChannelElements\MessageValidationBindingElement.cs" /> + <Compile Include="OAuth2\ChannelElements\AuthServerBindingElementBase.cs" /> + <Compile Include="OAuth2\ChannelElements\IOAuth2ChannelWithAuthorizationServer.cs" /> + <Compile Include="OAuth2\ChannelElements\OAuth2AuthorizationServerChannel.cs" /> + <Compile Include="OAuth2\ChannelElements\RefreshToken.cs" /> + <Compile Include="OAuth2\ClientDescription.cs" /> + <Compile Include="OAuth2\Messages\AccessTokenAuthorizationCodeRequestAS.cs" /> + <Compile Include="OAuth2\Messages\AccessTokenRefreshRequestAS.cs" /> + <Compile Include="OAuth2\Messages\EndUserAuthorizationSuccessAuthCodeResponseAS.cs" /> + <Compile Include="OAuth2\Messages\IAuthorizationCodeCarryingRequest.cs" /> + <Compile Include="OAuth2\Messages\IRefreshTokenCarryingRequest.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <ItemGroup> @@ -26,11 +46,21 @@ <Project>{60426312-6AE5-4835-8667-37EDEA670222}</Project> <Name>DotNetOpenAuth.Core</Name> </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.OAuth2.ClientAuthorization\DotNetOpenAuth.OAuth2.ClientAuthorization.csproj"> + <Project>{CCF3728A-B3D7-404A-9BC6-75197135F2D7}</Project> + <Name>DotNetOpenAuth.OAuth2.ClientAuthorization</Name> + </ProjectReference> <ProjectReference Include="..\DotNetOpenAuth.OAuth2\DotNetOpenAuth.OAuth2.csproj"> <Project>{56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}</Project> <Name>DotNetOpenAuth.OAuth2</Name> </ProjectReference> </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="OAuth2\AuthServerStrings.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>AuthServerStrings.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" /> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " /> diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerStrings.Designer.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerStrings.Designer.cs new file mode 100644 index 0000000..43a97f3 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerStrings.Designer.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.17611 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace DotNetOpenAuth.OAuth2 { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class AuthServerStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal AuthServerStrings() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DotNetOpenAuth.OAuth2.AuthServerStrings", typeof(AuthServerStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// Looks up a localized string similar to The requested access scope exceeds the grant scope.. + /// </summary> + internal static string AccessScopeExceedsGrantScope { + get { + return ResourceManager.GetString("AccessScopeExceedsGrantScope", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The client secret was incorrect.. + /// </summary> + internal static string ClientSecretMismatch { + get { + return ResourceManager.GetString("ClientSecretMismatch", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Invalid resource owner password credential.. + /// </summary> + internal static string InvalidResourceOwnerPasswordCredential { + get { + return ResourceManager.GetString("InvalidResourceOwnerPasswordCredential", resourceCulture); + } + } + } +} diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerStrings.resx b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerStrings.resx new file mode 100644 index 0000000..82b3e81 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerStrings.resx @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="AccessScopeExceedsGrantScope" xml:space="preserve"> + <value>The requested access scope exceeds the grant scope.</value> + </data> + <data name="ClientSecretMismatch" xml:space="preserve"> + <value>The client secret was incorrect.</value> + </data> + <data name="InvalidResourceOwnerPasswordCredential" xml:space="preserve"> + <value>Invalid resource owner password credential.</value> + </data> +</root>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerUtilities.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerUtilities.cs new file mode 100644 index 0000000..a59eaa7 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerUtilities.cs @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------- +// <copyright file="AuthServerUtilities.cs" company="Outercurve Foundation"> +// Copyright (c) Outercurve Foundation. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2 { + using System; + using System.Collections.Generic; + using System.Diagnostics.Contracts; + using System.Globalization; + using System.Linq; + using System.Text; + using DotNetOpenAuth.Messaging; + + /// <summary> + /// Utility methods for authorization servers. + /// </summary> + internal static class AuthServerUtilities { + /// <summary> + /// Gets information about the client with a given identifier. + /// </summary> + /// <param name="authorizationServer">The authorization server.</param> + /// <param name="clientIdentifier">The client identifier.</param> + /// <returns>The client information. Never null.</returns> + internal static IClientDescription GetClientOrThrow(this IAuthorizationServer authorizationServer, string clientIdentifier) { + Requires.NotNullOrEmpty(clientIdentifier, "clientIdentifier"); + Contract.Ensures(Contract.Result<IClientDescription>() != null); + + try { + var result = authorizationServer.GetClient(clientIdentifier); + ErrorUtilities.VerifyHost(result != null, OAuthStrings.ResultShouldNotBeNull, authorizationServer.GetType().FullName, "GetClient(string)"); + return result; + } catch (KeyNotFoundException ex) { + throw ErrorUtilities.Wrap(ex, OAuthStrings.ClientOrTokenSecretNotFound); + } catch (ArgumentException ex) { + throw ErrorUtilities.Wrap(ex, OAuthStrings.ClientOrTokenSecretNotFound); + } + } + + /// <summary> + /// Verifies a condition is true or throws an exception describing the problem. + /// </summary> + /// <param name="condition">The condition that evaluates to true to avoid an exception.</param> + /// <param name="error">A single error code from <see cref="Protocol.AccessTokenRequestErrorCodes"/>.</param> + /// <param name="unformattedDescription">A human-readable UTF-8 encoded text providing additional information, used to assist the client developer in understanding the error that occurred.</param> + /// <param name="args">The formatting arguments to generate the actual description.</param> + internal static void TokenEndpointVerify(bool condition, string error, string unformattedDescription = null, params object[] args) { + if (!condition) { + string description = unformattedDescription != null ? string.Format(CultureInfo.CurrentCulture, unformattedDescription, args) : null; + throw new TokenEndpointProtocolException(error, description); + } + } + } +} diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs index f555248..88145d2 100644 --- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs @@ -63,7 +63,7 @@ namespace DotNetOpenAuth.OAuth2 { if (message.ResponseType == EndUserAuthorizationResponseType.AuthorizationCode) { // Clients with no secrets can only request implicit grant types. var client = this.AuthorizationServerServices.GetClientOrThrow(message.ClientIdentifier); - ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(client.Secret), Protocol.unauthorized_client); + ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(client.Secret), Protocol.EndUserAuthorizationRequestErrorCodes.UnauthorizedClient); } } @@ -113,10 +113,10 @@ namespace DotNetOpenAuth.OAuth2 { // TODO: refreshToken should be set appropriately based on authorization server policy. responseMessage = this.PrepareAccessTokenResponse(requestMessage); } else { - responseMessage = new AccessTokenFailedResponse() { - Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest, - }; + responseMessage = new AccessTokenFailedResponse() { Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest, }; } + } catch (TokenEndpointProtocolException ex) { + responseMessage = new AccessTokenFailedResponse() { Error = ex.Error, ErrorDescription = ex.Description, ErrorUri = ex.MoreInformation }; } catch (ProtocolException) { responseMessage = new AccessTokenFailedResponse() { Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest, @@ -166,11 +166,17 @@ namespace DotNetOpenAuth.OAuth2 { switch (authorizationRequest.ResponseType) { case EndUserAuthorizationResponseType.AccessToken: var accessTokenResponse = new EndUserAuthorizationSuccessAccessTokenResponse(callback, authorizationRequest); - accessTokenResponse.Lifetime = this.AuthorizationServerServices.GetAccessTokenLifetime((EndUserAuthorizationImplicitRequest)authorizationRequest); response = accessTokenResponse; break; case EndUserAuthorizationResponseType.AuthorizationCode: - response = new EndUserAuthorizationSuccessAuthCodeResponse(callback, authorizationRequest); + var authCodeResponse = new EndUserAuthorizationSuccessAuthCodeResponseAS(callback, authorizationRequest); + IAuthorizationCodeCarryingRequest tokenCarryingResponse = authCodeResponse; + tokenCarryingResponse.AuthorizationDescription = new AuthorizationCode( + authorizationRequest.ClientIdentifier, + authorizationRequest.Callback, + authCodeResponse.Scope, + userName); + response = authCodeResponse; break; default: throw ErrorUtilities.ThrowInternal("Unexpected response type."); @@ -231,8 +237,8 @@ namespace DotNetOpenAuth.OAuth2 { } var tokenRequest = (IAuthorizationCarryingRequest)request; + var accessTokenRequest = (IAccessTokenRequestInternal)request; var response = new AccessTokenSuccessResponse(request) { - Lifetime = this.AuthorizationServerServices.GetAccessTokenLifetime(request), HasRefreshToken = includeRefreshToken, }; response.Scope.ResetContents(tokenRequest.AuthorizationDescription.Scope); diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessTokenBindingElement.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/AccessTokenBindingElement.cs index 4c63f29..9d7e8f2 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessTokenBindingElement.cs +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/AccessTokenBindingElement.cs @@ -7,6 +7,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using System.Security.Cryptography; using System.Text; @@ -44,30 +45,30 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { /// </returns> public override MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) { var directResponse = message as IDirectResponseProtocolMessage; - IAccessTokenRequest request = directResponse != null ? directResponse.OriginatingRequest as IAccessTokenRequest : null; - + var request = directResponse != null ? directResponse.OriginatingRequest as IAccessTokenRequestInternal : null; + var authCarryingRequest = request as IAuthorizationCarryingRequest; + var accessTokenResponse = message as IAccessTokenIssuingResponse; 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; - } + if (request != null) { + request.AccessTokenCreationParameters = this.AuthorizationServer.GetAccessTokenParameters(request); + ErrorUtilities.VerifyHost(request.AccessTokenCreationParameters != null, "IAuthorizationServer.GetAccessTokenParameters must not return null."); - 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 != null) { + accessTokenResponse.Lifetime = request.AccessTokenCreationParameters.AccessTokenLifetime; } + } - if (accessTokenResponse.HasRefreshToken) { - var refreshToken = new RefreshToken(authCarryingRequest.AuthorizationDescription); - var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServer.CryptoKeyStore); - accessTokenResponse.RefreshToken = refreshTokenFormatter.Serialize(refreshToken); - } + if (authCarryingRequest != null) { + ErrorUtilities.VerifyInternal(request != null, MessagingStrings.UnexpectedMessageReceived, typeof(IAccessTokenRequestInternal), request.GetType()); + accessTokenResponse.AuthorizationDescription = new AccessToken(authCarryingRequest.AuthorizationDescription, accessTokenResponse.Lifetime); + } else if (implicitGrantResponse != null) { + IAccessTokenCarryingRequest tokenCarryingResponse = implicitGrantResponse; + accessTokenResponse.AuthorizationDescription = new AccessToken( + request.ClientIdentifier, + implicitGrantResponse.Scope, + implicitGrantResponse.AuthorizingUsername, + implicitGrantResponse.Lifetime); } return null; diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerBindingElementBase.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/AuthServerBindingElementBase.cs index 49f820d..49f820d 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerBindingElementBase.cs +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/AuthServerBindingElementBase.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCode.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/AuthorizationCode.cs index 111c007..f5f25b2 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCode.cs +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/AuthorizationCode.cs @@ -47,6 +47,14 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { } /// <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> /// Gets or sets the hash of the callback URL. /// </summary> [MessagePart("cb")] @@ -70,7 +78,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { signed: true, encrypted: true, compressed: false, - maximumAge: AuthorizationCodeBindingElement.MaximumMessageAge, + maximumAge: MaximumMessageAge, decodeOnceOnly: authorizationServer.VerificationCodeNonceStore); } @@ -86,7 +94,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { [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); + ErrorUtilities.VerifyProtocol(MessagingUtilities.AreEquivalentConstantTime(this.CallbackHash, CalculateCallbackHash(callback)), Protocol.redirect_uri_mismatch); } /// <summary> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IOAuth2ChannelWithAuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/IOAuth2ChannelWithAuthorizationServer.cs index 5fc73ce..5fc73ce 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IOAuth2ChannelWithAuthorizationServer.cs +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/IOAuth2ChannelWithAuthorizationServer.cs diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/MessageValidationBindingElement.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/MessageValidationBindingElement.cs new file mode 100644 index 0000000..43ce243 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/MessageValidationBindingElement.cs @@ -0,0 +1,160 @@ +//----------------------------------------------------------------------- +// <copyright file="MessageValidationBindingElement.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 guard for all messages to or from an Authorization Server to ensure that they are well formed, + /// have valid secrets, callback URIs, etc. + /// </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 MessageValidationBindingElement : 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; } + } + + /// <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 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> + public override MessageProtections? ProcessIncomingMessage(IProtocolMessage message) { + bool applied = false; + + // Check that the client secret is correct for client authenticated messages. + var clientCredentialOnly = message as AccessTokenClientCredentialsRequest; + var authenticatedClientRequest = message as AuthenticatedClientRequestBase; + if (authenticatedClientRequest != null) { + var client = this.AuthorizationServer.GetClientOrThrow(authenticatedClientRequest.ClientIdentifier); + string secret = client.Secret; + AuthServerUtilities.TokenEndpointVerify(!string.IsNullOrEmpty(secret), Protocol.AccessTokenRequestErrorCodes.UnauthorizedClient); // an empty secret is not allowed for client authenticated calls. + AuthServerUtilities.TokenEndpointVerify(MessagingUtilities.EqualsConstantTime(secret, authenticatedClientRequest.ClientSecret), Protocol.AccessTokenRequestErrorCodes.InvalidClient, AuthServerStrings.ClientSecretMismatch); + + if (clientCredentialOnly != null) { + clientCredentialOnly.CredentialsValidated = true; + } + + applied = true; + } + + // Check that any resource owner password credential is correct. + var resourceOwnerPasswordCarrier = message as AccessTokenResourceOwnerPasswordCredentialsRequest; + if (resourceOwnerPasswordCarrier != null) { + try { + if (this.AuthorizationServer.IsResourceOwnerCredentialValid(resourceOwnerPasswordCarrier.UserName, resourceOwnerPasswordCarrier.Password)) { + resourceOwnerPasswordCarrier.CredentialsValidated = true; + } else { + Logger.OAuth.ErrorFormat( + "Resource owner password credential for user \"{0}\" rejected by authorization server host.", + resourceOwnerPasswordCarrier.UserName); + throw new TokenEndpointProtocolException(Protocol.AccessTokenRequestErrorCodes.InvalidGrant, AuthServerStrings.InvalidResourceOwnerPasswordCredential); + } + } catch (NotSupportedException) { + throw new TokenEndpointProtocolException(Protocol.AccessTokenRequestErrorCodes.UnsupportedGrantType); + } catch (NotImplementedException) { + throw new TokenEndpointProtocolException(Protocol.AccessTokenRequestErrorCodes.UnsupportedGrantType); + } + } + + // Check that authorization requests come with an acceptable callback URI. + 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); + applied = true; + } + + // Check that the callback URI in a direct message from the client matches the one in the indirect message received earlier. + var request = message as AccessTokenAuthorizationCodeRequestAS; + if (request != null) { + IAuthorizationCodeCarryingRequest tokenRequest = request; + tokenRequest.AuthorizationDescription.VerifyCallback(request.Callback); + applied = true; + } + + var authCarrier = message as IAuthorizationCarryingRequest; + if (authCarrier != null) { + var accessRequest = authCarrier as AccessTokenRequestBase; + if (accessRequest != null) { + // Make sure the client sending us this token is the client we issued the token to. + AuthServerUtilities.TokenEndpointVerify(string.Equals(accessRequest.ClientIdentifier, authCarrier.AuthorizationDescription.ClientIdentifier, StringComparison.Ordinal), Protocol.AccessTokenRequestErrorCodes.InvalidClient); + + var scopedAccessRequest = accessRequest as ScopedAccessTokenRequest; + if (scopedAccessRequest != null) { + // Make sure the scope the client is requesting does not exceed the scope in the grant. + if (!scopedAccessRequest.Scope.IsSubsetOf(authCarrier.AuthorizationDescription.Scope)) { + Logger.OAuth.ErrorFormat("The requested access scope (\"{0}\") exceeds the grant scope (\"{1}\").", scopedAccessRequest.Scope, authCarrier.AuthorizationDescription.Scope); + throw new TokenEndpointProtocolException(Protocol.AccessTokenRequestErrorCodes.InvalidScope, AuthServerStrings.AccessScopeExceedsGrantScope); + } + } + } + + // Make sure the authorization this token represents hasn't already been revoked. + if (!this.AuthorizationServer.IsAuthorizationValid(authCarrier.AuthorizationDescription)) { + Logger.OAuth.Error("Rejecting access token request because the IAuthorizationServer.IsAuthorizationValid method returned false."); + throw new TokenEndpointProtocolException(Protocol.AccessTokenRequestErrorCodes.InvalidGrant); + } + + applied = true; + } + + return applied ? (MessageProtections?)MessageProtections.None : null; + } + } +} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs index 6717717..09d35ee 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs @@ -11,17 +11,32 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { using System.Net.Mime; using System.Web; using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth2.AuthServer.Messages; + using DotNetOpenAuth.OAuth2.Messages; /// <summary> /// The channel for the OAuth protocol. /// </summary> internal class OAuth2AuthorizationServerChannel : OAuth2ChannelBase, IOAuth2ChannelWithAuthorizationServer { /// <summary> + /// The messages receivable by this channel. + /// </summary> + private static readonly Type[] MessageTypes = new Type[] { + typeof(AccessTokenRefreshRequestAS), + typeof(AccessTokenAuthorizationCodeRequestAS), + typeof(AccessTokenResourceOwnerPasswordCredentialsRequest), + typeof(AccessTokenClientCredentialsRequest), + typeof(EndUserAuthorizationRequest), + typeof(EndUserAuthorizationImplicitRequest), + typeof(EndUserAuthorizationFailedResponse), + }; + + /// <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)) { + : base(MessageTypes, InitializeBindingElements(authorizationServer)) { Requires.NotNull(authorizationServer, "authorizationServer"); this.AuthorizationServer = authorizationServer; } @@ -98,10 +113,10 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { Requires.NotNull(authorizationServer, "authorizationServer"); var bindingElements = new List<IChannelBindingElement>(); - bindingElements.Add(new AuthServerAllFlowsBindingElement()); - bindingElements.Add(new AuthorizationCodeBindingElement()); + // The order they are provided is used for outgoing messgaes, and reversed for incoming messages. + bindingElements.Add(new MessageValidationBindingElement()); bindingElements.Add(new AccessTokenBindingElement()); - bindingElements.Add(new AccessRequestBindingElement()); + bindingElements.Add(new TokenCodeSerializationBindingElement()); return bindingElements.ToArray(); } diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/RefreshToken.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/RefreshToken.cs index 993583c..993583c 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/RefreshToken.cs +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/RefreshToken.cs diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/TokenCodeSerializationBindingElement.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/TokenCodeSerializationBindingElement.cs new file mode 100644 index 0000000..b14f366 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/TokenCodeSerializationBindingElement.cs @@ -0,0 +1,120 @@ +//----------------------------------------------------------------------- +// <copyright file="TokenCodeSerializationBindingElement.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.AuthServer.ChannelElements; + using DotNetOpenAuth.OAuth2.Messages; + + /// <summary> + /// Serializes and deserializes authorization codes, refresh tokens and access tokens + /// on incoming and outgoing messages. + /// </summary> + internal class TokenCodeSerializationBindingElement : AuthServerBindingElementBase { + /// <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 directResponse = message as IDirectResponseProtocolMessage; + var request = directResponse != null ? directResponse.OriginatingRequest as IAccessTokenRequestInternal : null; + + // Serialize the authorization code, if there is one. + 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; + } + + // Serialize the refresh token, if applicable. + var refreshTokenResponse = message as AccessTokenSuccessResponse; + if (refreshTokenResponse != null && refreshTokenResponse.HasRefreshToken) { + var refreshTokenCarrier = (IAuthorizationCarryingRequest)message; + var refreshToken = new RefreshToken(refreshTokenCarrier.AuthorizationDescription); + var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServer.CryptoKeyStore); + refreshTokenResponse.RefreshToken = refreshTokenFormatter.Serialize(refreshToken); + } + + // Serialize the access token, if applicable. + var accessTokenResponse = message as IAccessTokenIssuingResponse; + if (accessTokenResponse != null && accessTokenResponse.AuthorizationDescription != null) { + ErrorUtilities.VerifyInternal(request != null, "We should always have a direct request message for this case."); + var accessTokenFormatter = AccessToken.CreateFormatter(this.AuthorizationServer.AccessTokenSigningKey, request.AccessTokenCreationParameters.ResourceServerEncryptionKey); + accessTokenResponse.AccessToken = accessTokenFormatter.Serialize(accessTokenResponse.AuthorizationDescription); + } + + 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 authCodeCarrier = message as IAuthorizationCodeCarryingRequest; + if (authCodeCarrier != null) { + var authorizationCodeFormatter = AuthorizationCode.CreateFormatter(this.AuthorizationServer); + var authorizationCode = authorizationCodeFormatter.Deserialize(message, authCodeCarrier.Code, Protocol.code); + authCodeCarrier.AuthorizationDescription = authorizationCode; + } + + var refreshTokenCarrier = message as IRefreshTokenCarryingRequest; + if (refreshTokenCarrier != null) { + var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServer.CryptoKeyStore); + var refreshToken = refreshTokenFormatter.Deserialize(message, refreshTokenCarrier.RefreshToken, Protocol.refresh_token); + refreshTokenCarrier.AuthorizationDescription = refreshToken; + } + + return null; + } + } +} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ClientDescription.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ClientDescription.cs index 76c3ea6..76c3ea6 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ClientDescription.cs +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ClientDescription.cs diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/AccessTokenAuthorizationCodeRequestAS.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/AccessTokenAuthorizationCodeRequestAS.cs new file mode 100644 index 0000000..ca14d0e --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/AccessTokenAuthorizationCodeRequestAS.cs @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------- +// <copyright file="AccessTokenAuthorizationCodeRequestAS.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using DotNetOpenAuth.OAuth2.ChannelElements; + + /// <summary> + /// A request from a Client to an Authorization Server to exchange an authorization code for an access token, + /// and (at the authorization server's option) a refresh token. + /// </summary> + internal class AccessTokenAuthorizationCodeRequestAS : AccessTokenAuthorizationCodeRequest, IAuthorizationCodeCarryingRequest { + /// <summary> + /// Initializes a new instance of the <see cref="AccessTokenAuthorizationCodeRequestAS"/> class. + /// </summary> + /// <param name="tokenEndpoint">The Authorization Server's access token endpoint URL.</param> + /// <param name="version">The version.</param> + internal AccessTokenAuthorizationCodeRequestAS(Uri tokenEndpoint, Version version) + : base(tokenEndpoint, version) { + } + + #region IAuthorizationCodeCarryingRequest Members + + /// <summary> + /// Gets or sets the verification code or refresh/access token. + /// </summary> + /// <value>The code or token.</value> + string IAuthorizationCodeCarryingRequest.Code { + get { return this.AuthorizationCode; } + set { this.AuthorizationCode = value; } + } + + /// <summary> + /// Gets or sets the authorization that the token describes. + /// </summary> + AuthorizationCode IAuthorizationCodeCarryingRequest.AuthorizationDescription { get; set; } + + /// <summary> + /// Gets the authorization that the code describes. + /// </summary> + IAuthorizationDescription IAuthorizationCarryingRequest.AuthorizationDescription { + get { return ((IAuthorizationCodeCarryingRequest)this).AuthorizationDescription; } + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/AccessTokenRefreshRequestAS.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/AccessTokenRefreshRequestAS.cs new file mode 100644 index 0000000..d9ca4c8 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/AccessTokenRefreshRequestAS.cs @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------- +// <copyright file="AccessTokenRefreshRequestAS.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2.AuthServer.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using DotNetOpenAuth.OAuth2.AuthServer.ChannelElements; + using DotNetOpenAuth.OAuth2.ChannelElements; + using DotNetOpenAuth.OAuth2.Messages; + + /// <summary> + /// A request from the client to the token endpoint for a new access token + /// in exchange for a refresh token that the client has previously obtained. + /// </summary> + internal class AccessTokenRefreshRequestAS : AccessTokenRefreshRequest, IRefreshTokenCarryingRequest { + /// <summary> + /// Initializes a new instance of the <see cref="AccessTokenRefreshRequestAS"/> class. + /// </summary> + /// <param name="tokenEndpoint">The token endpoint.</param> + /// <param name="version">The version.</param> + internal AccessTokenRefreshRequestAS(Uri tokenEndpoint, Version version) + : base(tokenEndpoint, version) { + } + + #region IRefreshTokenCarryingRequest members + + /// <summary> + /// Gets or sets the verification code or refresh/access token. + /// </summary> + /// <value>The code or token.</value> + string IRefreshTokenCarryingRequest.RefreshToken { + get { return this.RefreshToken; } + set { this.RefreshToken = value; } + } + + /// <summary> + /// Gets or sets the authorization that the token describes. + /// </summary> + RefreshToken IRefreshTokenCarryingRequest.AuthorizationDescription { get; set; } + + /// <summary> + /// Gets the authorization that the token describes. + /// </summary> + IAuthorizationDescription IAuthorizationCarryingRequest.AuthorizationDescription { + get { return ((IRefreshTokenCarryingRequest)this).AuthorizationDescription; } + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/EndUserAuthorizationSuccessAuthCodeResponseAS.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/EndUserAuthorizationSuccessAuthCodeResponseAS.cs new file mode 100644 index 0000000..25f5dc8 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/EndUserAuthorizationSuccessAuthCodeResponseAS.cs @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------- +// <copyright file="EndUserAuthorizationSuccessAuthCodeResponseAS.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using DotNetOpenAuth.OAuth2.ChannelElements; + + /// <summary> + /// The message sent by the Authorization Server to the Client via the user agent + /// to indicate that user authorization was granted, carrying an authorization code and possibly an access token, + /// and to return the user to the Client where they started their experience. + /// </summary> + internal class EndUserAuthorizationSuccessAuthCodeResponseAS : EndUserAuthorizationSuccessAuthCodeResponse, IAuthorizationCodeCarryingRequest { + /// <summary> + /// Initializes a new instance of the <see cref="EndUserAuthorizationSuccessAuthCodeResponseAS"/> class. + /// </summary> + /// <param name="clientCallback">The URL to redirect to so the client receives the message. This may not be built into the request message if the client pre-registered the URL with the authorization server.</param> + /// <param name="version">The protocol version.</param> + internal EndUserAuthorizationSuccessAuthCodeResponseAS(Uri clientCallback, Version version) + : base(clientCallback, version) { + Requires.NotNull(version, "version"); + Requires.NotNull(clientCallback, "clientCallback"); + } + + /// <summary> + /// Initializes a new instance of the <see cref="EndUserAuthorizationSuccessAuthCodeResponseAS"/> class. + /// </summary> + /// <param name="clientCallback">The URL to redirect to so the client receives the message. This may not be built into the request message if the client pre-registered the URL with the authorization server.</param> + /// <param name="request">The authorization request from the user agent on behalf of the client.</param> + internal EndUserAuthorizationSuccessAuthCodeResponseAS(Uri clientCallback, EndUserAuthorizationRequest request) + : base(clientCallback, request) { + Requires.NotNull(clientCallback, "clientCallback"); + Requires.NotNull(request, "request"); + ((IMessageWithClientState)this).ClientState = request.ClientState; + } + + #region IAuthorizationCodeCarryingRequest Members + + /// <summary> + /// Gets or sets the authorization code. + /// </summary> + string IAuthorizationCodeCarryingRequest.Code { + get { return this.AuthorizationCode; } + set { this.AuthorizationCode = value; } + } + + /// <summary> + /// Gets or sets the authorization that the token describes. + /// </summary> + AuthorizationCode IAuthorizationCodeCarryingRequest.AuthorizationDescription { get; set; } + + /// <summary> + /// Gets the authorization that the code describes. + /// </summary> + IAuthorizationDescription IAuthorizationCarryingRequest.AuthorizationDescription { + get { return ((IAuthorizationCodeCarryingRequest)this).AuthorizationDescription; } + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IAuthorizationCodeCarryingRequest.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/IAuthorizationCodeCarryingRequest.cs index 045cb80..045cb80 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IAuthorizationCodeCarryingRequest.cs +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/IAuthorizationCodeCarryingRequest.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IRefreshTokenCarryingRequest.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/IRefreshTokenCarryingRequest.cs index ce27538..9e6fc3c 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IRefreshTokenCarryingRequest.cs +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/Messages/IRefreshTokenCarryingRequest.cs @@ -4,7 +4,9 @@ // </copyright> //----------------------------------------------------------------------- -namespace DotNetOpenAuth.OAuth2.ChannelElements { +namespace DotNetOpenAuth.OAuth2.AuthServer.ChannelElements { + using DotNetOpenAuth.OAuth2.ChannelElements; + /// <summary> /// A message that carries a refresh token between client and authorization server. /// </summary> diff --git a/src/DotNetOpenAuth.OAuth2.Client/DotNetOpenAuth.OAuth2.Client.csproj b/src/DotNetOpenAuth.OAuth2.Client/DotNetOpenAuth.OAuth2.Client.csproj index 3d2683f..3dfc63b 100644 --- a/src/DotNetOpenAuth.OAuth2.Client/DotNetOpenAuth.OAuth2.Client.csproj +++ b/src/DotNetOpenAuth.OAuth2.Client/DotNetOpenAuth.OAuth2.Client.csproj @@ -18,6 +18,15 @@ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> </PropertyGroup> <ItemGroup> + <Compile Include="OAuth2\AuthorizationServerDescription.cs" /> + <Compile Include="OAuth2\AuthorizationState.cs" /> + <Compile Include="OAuth2\ChannelElements\OAuth2ClientChannel.cs" /> + <Compile Include="OAuth2\IAuthorizationState.cs" /> + <Compile Include="OAuth2\IClientAuthorizationTracker.cs" /> + <Compile Include="OAuth2\Messages\AccessTokenAuthorizationCodeRequestC.cs" /> + <Compile Include="OAuth2\Messages\AccessTokenRefreshRequestC.cs" /> + <Compile Include="OAuth2\Messages\EndUserAuthorizationImplicitRequestC.cs" /> + <Compile Include="OAuth2\Messages\EndUserAuthorizationRequestC.cs" /> <Compile Include="OAuth2\OAuth2Strings.Designer.cs"> <AutoGen>True</AutoGen> <DesignTime>True</DesignTime> @@ -33,6 +42,10 @@ <Project>{60426312-6AE5-4835-8667-37EDEA670222}</Project> <Name>DotNetOpenAuth.Core</Name> </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.OAuth2.ClientAuthorization\DotNetOpenAuth.OAuth2.ClientAuthorization.csproj"> + <Project>{CCF3728A-B3D7-404A-9BC6-75197135F2D7}</Project> + <Name>DotNetOpenAuth.OAuth2.ClientAuthorization</Name> + </ProjectReference> <ProjectReference Include="..\DotNetOpenAuth.OAuth2\DotNetOpenAuth.OAuth2.csproj"> <Project>{56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}</Project> <Name>DotNetOpenAuth.OAuth2</Name> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/AuthorizationServerDescription.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/AuthorizationServerDescription.cs index 38a9ff9..38a9ff9 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/AuthorizationServerDescription.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/AuthorizationServerDescription.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/AuthorizationState.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/AuthorizationState.cs index 4117b3c..4117b3c 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/AuthorizationState.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/AuthorizationState.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ClientChannel.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs index c9981d3..95ec983 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ClientChannel.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs @@ -13,15 +13,28 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { using System.Web; using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth2.Messages; /// <summary> /// The messaging channel used by OAuth 2.0 Clients. /// </summary> internal class OAuth2ClientChannel : OAuth2ChannelBase { /// <summary> + /// The messages receivable by this channel. + /// </summary> + private static readonly Type[] MessageTypes = new Type[] { + typeof(AccessTokenSuccessResponse), + typeof(AccessTokenFailedResponse), + typeof(EndUserAuthorizationSuccessAuthCodeResponse), + typeof(EndUserAuthorizationSuccessAccessTokenResponse), + typeof(EndUserAuthorizationFailedResponse), + typeof(UnauthorizedResponse), + }; + + /// <summary> /// Initializes a new instance of the <see cref="OAuth2ClientChannel"/> class. /// </summary> - internal OAuth2ClientChannel() { + internal OAuth2ClientChannel() : base(MessageTypes) { } /// <summary> diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs index 7697244..1bda5e0 100644 --- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs @@ -116,7 +116,7 @@ namespace DotNetOpenAuth.OAuth2 { } } - var request = new AccessTokenRefreshRequest(this.AuthorizationServer) { + var request = new AccessTokenRefreshRequestC(this.AuthorizationServer) { ClientIdentifier = this.ClientIdentifier, ClientSecret = this.ClientSecret, RefreshToken = authorization.RefreshToken, @@ -143,7 +143,7 @@ namespace DotNetOpenAuth.OAuth2 { Requires.NotNull(scope, "scope"); Contract.Ensures(Contract.Result<IAuthorizationState>() != null); - var request = new AccessTokenRefreshRequest(this.AuthorizationServer) { + var request = new AccessTokenRefreshRequestC(this.AuthorizationServer) { ClientIdentifier = this.ClientIdentifier, ClientSecret = this.ClientSecret, RefreshToken = refreshToken, @@ -248,7 +248,7 @@ namespace DotNetOpenAuth.OAuth2 { Requires.NotNull(authorizationState, "authorizationState"); Requires.NotNull(authorizationSuccess, "authorizationSuccess"); - var accessTokenRequest = new AccessTokenAuthorizationCodeRequest(this.AuthorizationServer) { + var accessTokenRequest = new AccessTokenAuthorizationCodeRequestC(this.AuthorizationServer) { ClientIdentifier = this.ClientIdentifier, ClientSecret = this.ClientSecret, Callback = authorizationState.Callback, diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationState.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/IAuthorizationState.cs index f38df9a..f38df9a 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationState.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/IAuthorizationState.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/IClientAuthorizationTracker.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/IClientAuthorizationTracker.cs index 73b7a44..73b7a44 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/IClientAuthorizationTracker.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/IClientAuthorizationTracker.cs diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/AccessTokenAuthorizationCodeRequestC.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/AccessTokenAuthorizationCodeRequestC.cs new file mode 100644 index 0000000..ebfb2e8 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/AccessTokenAuthorizationCodeRequestC.cs @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------- +// <copyright file="AccessTokenAuthorizationCodeRequestC.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + /// <summary> + /// A request from a Client to an Authorization Server to exchange an authorization code for an access token, + /// and (at the authorization server's option) a refresh token. + /// </summary> + internal class AccessTokenAuthorizationCodeRequestC : AccessTokenAuthorizationCodeRequest { + /// <summary> + /// Initializes a new instance of the <see cref="AccessTokenAuthorizationCodeRequestC"/> class. + /// </summary> + /// <param name="authorizationServer">The authorization server.</param> + internal AccessTokenAuthorizationCodeRequestC(AuthorizationServerDescription authorizationServer) + : base(authorizationServer.TokenEndpoint, authorizationServer.Version) { + Requires.NotNull(authorizationServer, "authorizationServer"); + } + } +} diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/AccessTokenRefreshRequestC.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/AccessTokenRefreshRequestC.cs new file mode 100644 index 0000000..25da3dc --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/AccessTokenRefreshRequestC.cs @@ -0,0 +1,26 @@ +//----------------------------------------------------------------------- +// <copyright file="AccessTokenRefreshRequestC.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + /// <summary> + /// A request from the client to the token endpoint for a new access token + /// in exchange for a refresh token that the client has previously obtained. + /// </summary> + internal class AccessTokenRefreshRequestC : AccessTokenRefreshRequest { + /// <summary> + /// Initializes a new instance of the <see cref="AccessTokenRefreshRequestC"/> class. + /// </summary> + /// <param name="authorizationServer">The authorization server.</param> + internal AccessTokenRefreshRequestC(AuthorizationServerDescription authorizationServer) + : base(authorizationServer.TokenEndpoint, authorizationServer.Version) { + } + } +} diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/EndUserAuthorizationImplicitRequestC.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/EndUserAuthorizationImplicitRequestC.cs new file mode 100644 index 0000000..78bf48e --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/EndUserAuthorizationImplicitRequestC.cs @@ -0,0 +1,28 @@ +//----------------------------------------------------------------------- +// <copyright file="EndUserAuthorizationImplicitRequestC.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + /// <summary> + /// A message sent by a web application Client to the AuthorizationServer + /// via the user agent to obtain authorization from the user and prepare + /// to issue an access token to the client if permission is granted. + /// </summary> + [Serializable] + internal class EndUserAuthorizationImplicitRequestC : EndUserAuthorizationImplicitRequest { + /// <summary> + /// Initializes a new instance of the <see cref="EndUserAuthorizationImplicitRequestC"/> class. + /// </summary> + /// <param name="authorizationServer">The authorization server.</param> + internal EndUserAuthorizationImplicitRequestC(AuthorizationServerDescription authorizationServer) + : base(authorizationServer.AuthorizationEndpoint, authorizationServer.Version) { + } + } +} diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/EndUserAuthorizationRequestC.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/EndUserAuthorizationRequestC.cs new file mode 100644 index 0000000..7c06897 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/Messages/EndUserAuthorizationRequestC.cs @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------- +// <copyright file="EndUserAuthorizationRequestC.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + /// <summary> + /// A message sent by a web application Client to the AuthorizationServer + /// via the user agent to obtain authorization from the user and prepare + /// to issue an access token to the client if permission is granted. + /// </summary> + [Serializable] + internal class EndUserAuthorizationRequestC : EndUserAuthorizationRequest { + /// <summary> + /// Initializes a new instance of the <see cref="EndUserAuthorizationRequestC"/> class. + /// </summary> + /// <param name="authorizationServer">The authorization server.</param> + internal EndUserAuthorizationRequestC(AuthorizationServerDescription authorizationServer) + : base(authorizationServer.AuthorizationEndpoint, authorizationServer.Version) { + Requires.NotNull(authorizationServer, "authorizationServer"); + Requires.True(authorizationServer.Version != null, "authorizationServer"); + Requires.True(authorizationServer.AuthorizationEndpoint != null, "authorizationServer"); + } + } +} diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/UserAgentClient.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/UserAgentClient.cs index c29d167..9834985 100644 --- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/UserAgentClient.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/UserAgentClient.cs @@ -151,7 +151,7 @@ namespace DotNetOpenAuth.OAuth2 { authorization.Callback = new Uri("http://localhost/"); } - var request = implicitResponseType ? new EndUserAuthorizationImplicitRequest(this.AuthorizationServer) : new EndUserAuthorizationRequest(this.AuthorizationServer); + var request = implicitResponseType ? (EndUserAuthorizationRequest)new EndUserAuthorizationImplicitRequestC(this.AuthorizationServer) : new EndUserAuthorizationRequestC(this.AuthorizationServer); request.ClientIdentifier = this.ClientIdentifier; request.Callback = authorization.Callback; request.ClientState = state; diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs index 671214f..016c491 100644 --- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs @@ -78,7 +78,7 @@ namespace DotNetOpenAuth.OAuth2 { authorization.SaveChanges(); } - var request = new EndUserAuthorizationRequest(this.AuthorizationServer) { + var request = new EndUserAuthorizationRequestC(this.AuthorizationServer) { ClientIdentifier = this.ClientIdentifier, Callback = authorization.Callback, }; diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/DotNetOpenAuth.OAuth2.ClientAuthorization.csproj b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/DotNetOpenAuth.OAuth2.ClientAuthorization.csproj new file mode 100644 index 0000000..53ab1d0 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/DotNetOpenAuth.OAuth2.ClientAuthorization.csproj @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))\EnlistmentInfo.props" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))' != '' " /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + </PropertyGroup> + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.props" /> + <PropertyGroup> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{CCF3728A-B3D7-404A-9BC6-75197135F2D7}</ProjectGuid> + <AppDesignerFolder>Properties</AppDesignerFolder> + <AssemblyName>DotNetOpenAuth.OAuth2.ClientAuthorization</AssemblyName> + </PropertyGroup> + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.Product.props" /> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + </PropertyGroup> + <ItemGroup> + <Compile Include="OAuth2\AccessTokenParameters.cs" /> + <Compile Include="OAuth2\ChannelElements\EndUserAuthorizationResponseTypeEncoder.cs" /> + <Compile Include="OAuth2\ChannelElements\GrantTypeEncoder.cs" /> + <Compile Include="OAuth2\ChannelElements\OAuth2ChannelBase.cs" /> + <Compile Include="OAuth2\ClientAuthorizationStrings.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>ClientAuthorizationStrings.resx</DependentUpon> + </Compile> + <Compile Include="OAuth2\ClientType.cs" /> + <Compile Include="OAuth2\IAuthorizationServer.cs" /> + <Compile Include="OAuth2\IClientDescription.cs" /> + <Compile Include="OAuth2\Messages\AccessTokenAuthorizationCodeRequest.cs" /> + <Compile Include="OAuth2\Messages\AccessTokenClientCredentialsRequest.cs" /> + <Compile Include="OAuth2\Messages\AccessTokenFailedResponse.cs" /> + <Compile Include="OAuth2\Messages\AccessTokenRefreshRequest.cs" /> + <Compile Include="OAuth2\Messages\AccessTokenRequestBase.cs" /> + <Compile Include="OAuth2\Messages\AccessTokenResourceOwnerPasswordCredentialsRequest.cs" /> + <Compile Include="OAuth2\Messages\AccessTokenSuccessResponse.cs" /> + <Compile Include="OAuth2\Messages\AuthenticatedClientRequestBase.cs" /> + <Compile Include="OAuth2\Messages\EndUserAuthorizationFailedResponse.cs" /> + <Compile Include="OAuth2\Messages\EndUserAuthorizationImplicitRequest.cs" /> + <Compile Include="OAuth2\Messages\EndUserAuthorizationRequest.cs" /> + <Compile Include="OAuth2\Messages\EndUserAuthorizationResponseType.cs" /> + <Compile Include="OAuth2\Messages\EndUserAuthorizationSuccessAccessTokenResponse.cs" /> + <Compile Include="OAuth2\Messages\EndUserAuthorizationSuccessAuthCodeResponse.cs" /> + <Compile Include="OAuth2\Messages\EndUserAuthorizationSuccessResponseBase.cs" /> + <Compile Include="OAuth2\Messages\GrantType.cs" /> + <Compile Include="OAuth2\Messages\IAccessTokenIssuingResponse.cs" /> + <Compile Include="OAuth2\Messages\IAccessTokenRequest.cs" /> + <Compile Include="OAuth2\Messages\IAccessTokenRequestInternal.cs" /> + <Compile Include="OAuth2\Messages\IMessageWithClientState.cs" /> + <Compile Include="OAuth2\Messages\ScopedAccessTokenRequest.cs" /> + <Compile Include="OAuth2\TokenEndpointProtocolException.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\DotNetOpenAuth.Core\DotNetOpenAuth.Core.csproj"> + <Project>{60426312-6AE5-4835-8667-37EDEA670222}</Project> + <Name>DotNetOpenAuth.Core</Name> + </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.OAuth2\DotNetOpenAuth.OAuth2.csproj"> + <Project>{56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}</Project> + <Name>DotNetOpenAuth.OAuth2</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="OAuth2\ClientAuthorizationStrings.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>ClientAuthorizationStrings.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" /> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " /> +</Project>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/AccessTokenParameters.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/AccessTokenParameters.cs new file mode 100644 index 0000000..a214f20 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/AccessTokenParameters.cs @@ -0,0 +1,80 @@ +//----------------------------------------------------------------------- +// <copyright file="AccessTokenParameters.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2 { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Security.Cryptography; + using System.Text; + + /// <summary> + /// Describes the parameters to be fed into creating a response to an access token request. + /// </summary> + public class AccessTokenParameters : IDisposable { + /// <summary> + /// Initializes a new instance of the <see cref="AccessTokenParameters"/> class. + /// </summary> + public AccessTokenParameters() { + this.IncludeRefreshToken = true; + this.AccessTokenLifetime = TimeSpan.FromHours(1); + } + + /// <summary> + /// Gets or sets the access token lifetime. + /// </summary> + /// <value> + /// A positive timespan. + /// </value> + /// <remarks> + /// Note that within this lifetime, authorization <i>may</i> not be revokable. + /// Short lifetimes are recommended (e.g. one hour), particularly when the client is not authenticated or + /// the resources to which access is being granted are sensitive. + /// </remarks> + public TimeSpan AccessTokenLifetime { get; set; } + + /// <summary> + /// Gets or sets the key to encrypt the access token. + /// </summary> + public RSACryptoServiceProvider ResourceServerEncryptionKey { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether to provide the client with a refresh token, when applicable. + /// </summary> + /// <value>The default value is <c>true</c>.</value> + /// <remarks>> + /// The refresh token will never be provided when this value is false. + /// The refresh token <em>may</em> be provided when this value is true. + /// </remarks> + public bool IncludeRefreshToken { get; set; } + + #region Implementation of IDisposable + + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + /// <filterpriority>2</filterpriority> + public void Dispose() { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + /// <summary> + /// Releases unmanaged and - optionally - managed resources + /// </summary> + /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> + protected virtual void Dispose(bool disposing) { + if (disposing) { + if (this.ResourceServerEncryptionKey != null) { + IDisposable value = this.ResourceServerEncryptionKey; + value.Dispose(); + } + } + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs index 2fba721..2fba721 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/GrantTypeEncoder.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ChannelElements/GrantTypeEncoder.cs index e0e8329..e0e8329 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/GrantTypeEncoder.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ChannelElements/GrantTypeEncoder.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ChannelBase.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ChannelElements/OAuth2ChannelBase.cs index 51ac58a..f2f674e 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ChannelBase.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ChannelElements/OAuth2ChannelBase.cs @@ -18,24 +18,6 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { /// </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(); @@ -43,9 +25,13 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { /// <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) { + /// <param name="messageTypes">The message types that are received by this channel.</param> + /// <param name="channelBindingElements"> + /// The binding elements to use in sending and receiving messages. + /// The order they are provided is used for outgoing messgaes, and reversed for incoming messages. + /// </param> + internal OAuth2ChannelBase(Type[] messageTypes, params IChannelBindingElement[] channelBindingElements) + : base(Requires.NotNull(messageTypes, "messageTypes"), Versions, channelBindingElements) { } /// <summary> diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ClientAuthorizationStrings.Designer.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ClientAuthorizationStrings.Designer.cs new file mode 100644 index 0000000..7d33d3e --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ClientAuthorizationStrings.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.17611 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace DotNetOpenAuth.OAuth2 { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class ClientAuthorizationStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ClientAuthorizationStrings() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DotNetOpenAuth.OAuth2.ClientAuthorizationStrings", typeof(ClientAuthorizationStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// Looks up a localized string similar to The Authorization Server's token endpoint generated error {0}: '{1}'. + /// </summary> + internal static string TokenEndpointErrorFormat { + get { + return ResourceManager.GetString("TokenEndpointErrorFormat", resourceCulture); + } + } + } +} diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ClientAuthorizationStrings.resx b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ClientAuthorizationStrings.resx new file mode 100644 index 0000000..5ae922f --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ClientAuthorizationStrings.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="TokenEndpointErrorFormat" xml:space="preserve"> + <value>The Authorization Server's token endpoint generated error {0}: '{1}'</value> + </data> +</root>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ClientType.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ClientType.cs index 9e8ed2a..9e8ed2a 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ClientType.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/ClientType.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/IAuthorizationServer.cs index a0a2ad9..03ef781 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/IAuthorizationServer.cs @@ -49,38 +49,14 @@ namespace DotNetOpenAuth.OAuth2 { RSACryptoServiceProvider AccessTokenSigningKey { get; } /// <summary> - /// Obtains the lifetime for a new access token. + /// Obtains parameters to go into the formulation of an access token. /// </summary> - /// <param name="accessTokenRequestMessage"> - /// Details regarding the resources that the access token will grant access to, and the identity of the client - /// that will receive that access. - /// Based on this information the receiving resource server can be determined and the lifetime of the access - /// token can be set based on the sensitivity of the resources. - /// </param> - /// <returns> - /// Receives the lifetime for this access token. Note that within this lifetime, authorization <i>may</i> not be revokable. - /// Short lifetimes are recommended (i.e. one hour), particularly when the client is not authenticated or - /// the resources to which access is being granted are sensitive. - /// </returns> - TimeSpan GetAccessTokenLifetime(IAccessTokenRequest accessTokenRequestMessage); - - /// <summary> - /// Obtains the encryption key for an access token being created. - /// </summary> - /// <param name="accessTokenRequestMessage"> - /// Details regarding the resources that the access token will grant access to, and the identity of the client + /// <param name="accessTokenRequestMessage">Details regarding the resources that the access token will grant access to, and the identity of the client /// that will receive that access. /// Based on this information the receiving resource server can be determined and the lifetime of the access - /// token can be set based on the sensitivity of the resources. - /// </param> - /// <returns> - /// The crypto service provider with the asymmetric public key to use for encrypting access tokens for a specific resource server. - /// The caller is responsible to dispose of this value. - /// </returns> - /// <remarks> - /// The caller is responsible to dispose of the returned value. - /// </remarks> - RSACryptoServiceProvider GetResourceServerEncryptionKey(IAccessTokenRequest accessTokenRequestMessage); + /// token can be set based on the sensitivity of the resources.</param> + /// <returns>A non-null parameters instance that DotNetOpenAuth will dispose after it has been used.</returns> + AccessTokenParameters GetAccessTokenParameters(IAccessTokenRequest accessTokenRequestMessage); /// <summary> /// Gets the client with a given identifier. @@ -174,40 +150,6 @@ namespace DotNetOpenAuth.OAuth2 { } /// <summary> - /// Obtains the lifetime for a new access token. - /// </summary> - /// <param name="accessTokenRequestMessage">Details regarding the resources that the access token will grant access to, and the identity of the client - /// that will receive that access. - /// Based on this information the receiving resource server can be determined and the lifetime of the access - /// token can be set based on the sensitivity of the resources.</param> - /// <returns> - /// Receives the lifetime for this access token. Note that within this lifetime, authorization <i>may</i> not be revokable. - /// Short lifetimes are recommended (i.e. one hour), particularly when the client is not authenticated or - /// the resources to which access is being granted are sensitive. - /// </returns> - TimeSpan IAuthorizationServer.GetAccessTokenLifetime(IAccessTokenRequest accessTokenRequestMessage) { - Requires.NotNull(accessTokenRequestMessage, "accessTokenRequestMessage"); - throw new NotImplementedException(); - } - - /// <summary> - /// Obtains the encryption key for an access token being created. - /// </summary> - /// <param name="accessTokenRequestMessage">Details regarding the resources that the access token will grant access to, and the identity of the client - /// that will receive that access. - /// Based on this information the receiving resource server can be determined and the lifetime of the access - /// token can be set based on the sensitivity of the resources.</param> - /// <returns> - /// The crypto service provider with the asymmetric public key to use for encrypting access tokens for a specific resource server. - /// The caller is responsible to dispose of this value. - /// </returns> - RSACryptoServiceProvider IAuthorizationServer.GetResourceServerEncryptionKey(IAccessTokenRequest accessTokenRequestMessage) { - Requires.NotNull(accessTokenRequestMessage, "accessTokenRequestMessage"); - Contract.Ensures(Contract.Result<RSACryptoServiceProvider>() != null); - throw new NotImplementedException(); - } - - /// <summary> /// Gets the client with a given identifier. /// </summary> /// <param name="clientIdentifier">The client identifier.</param> @@ -260,5 +202,21 @@ namespace DotNetOpenAuth.OAuth2 { Contract.Requires(password != null); throw new NotImplementedException(); } + + /// <summary> + /// Obtains parameters to go into the formulation of an access token. + /// </summary> + /// <param name="accessTokenRequestMessage">Details regarding the resources that the access token will grant access to, and the identity of the client + /// that will receive that access. + /// Based on this information the receiving resource server can be determined and the lifetime of the access + /// token can be set based on the sensitivity of the resources.</param> + /// <returns> + /// A non-null parameters instance that DotNetOpenAuth will dispose after it has been used. + /// </returns> + AccessTokenParameters IAuthorizationServer.GetAccessTokenParameters(IAccessTokenRequest accessTokenRequestMessage) { + Contract.Requires(accessTokenRequestMessage != null); + Contract.Ensures(Contract.Result<AccessTokenParameters>() != null); + throw new NotImplementedException(); + } } } diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/IClientDescription.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/IClientDescription.cs index d30151b..d30151b 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/IClientDescription.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/IClientDescription.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenAuthorizationCodeRequest.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenAuthorizationCodeRequest.cs index 1f244f9..b8c9ede 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenAuthorizationCodeRequest.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenAuthorizationCodeRequest.cs @@ -18,51 +18,17 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// A request from a Client to an Authorization Server to exchange an authorization code for an access token, /// and (at the authorization server's option) a refresh token. /// </summary> - internal class AccessTokenAuthorizationCodeRequest : AccessTokenRequestBase, IAuthorizationCodeCarryingRequest { + internal class AccessTokenAuthorizationCodeRequest : AccessTokenRequestBase { /// <summary> /// Initializes a new instance of the <see cref="AccessTokenAuthorizationCodeRequest"/> class. /// </summary> /// <param name="tokenEndpoint">The Authorization Server's access token endpoint URL.</param> /// <param name="version">The version.</param> - internal AccessTokenAuthorizationCodeRequest(Uri tokenEndpoint, Version version) + protected AccessTokenAuthorizationCodeRequest(Uri tokenEndpoint, Version version) : base(tokenEndpoint, version) { } /// <summary> - /// Initializes a new instance of the <see cref="AccessTokenAuthorizationCodeRequest"/> class. - /// </summary> - /// <param name="authorizationServer">The authorization server.</param> - internal AccessTokenAuthorizationCodeRequest(AuthorizationServerDescription authorizationServer) - : this(authorizationServer.TokenEndpoint, authorizationServer.Version) { - Requires.NotNull(authorizationServer, "authorizationServer"); - } - - #region IAuthorizationCodeCarryingRequest Members - - /// <summary> - /// Gets or sets the verification code or refresh/access token. - /// </summary> - /// <value>The code or token.</value> - string IAuthorizationCodeCarryingRequest.Code { - get { return this.AuthorizationCode; } - set { this.AuthorizationCode = value; } - } - - /// <summary> - /// Gets or sets the authorization that the token describes. - /// </summary> - AuthorizationCode IAuthorizationCodeCarryingRequest.AuthorizationDescription { get; set; } - - /// <summary> - /// Gets the authorization that the code describes. - /// </summary> - IAuthorizationDescription IAuthorizationCarryingRequest.AuthorizationDescription { - get { return ((IAuthorizationCodeCarryingRequest)this).AuthorizationDescription; } - } - - #endregion - - /// <summary> /// Gets the type of the grant. /// </summary> /// <value>The type of the grant.</value> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenClientCredentialsRequest.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenClientCredentialsRequest.cs index 48419eb..48419eb 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenClientCredentialsRequest.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenClientCredentialsRequest.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenFailedResponse.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenFailedResponse.cs index 8c4b1c3..8c4b1c3 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenFailedResponse.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenFailedResponse.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenRefreshRequest.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenRefreshRequest.cs index 2c3ab25..685f697 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenRefreshRequest.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenRefreshRequest.cs @@ -14,50 +14,17 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// A request from the client to the token endpoint for a new access token /// in exchange for a refresh token that the client has previously obtained. /// </summary> - internal class AccessTokenRefreshRequest : ScopedAccessTokenRequest, IRefreshTokenCarryingRequest { + internal class AccessTokenRefreshRequest : ScopedAccessTokenRequest { /// <summary> /// Initializes a new instance of the <see cref="AccessTokenRefreshRequest"/> class. /// </summary> /// <param name="tokenEndpoint">The token endpoint.</param> /// <param name="version">The version.</param> - internal AccessTokenRefreshRequest(Uri tokenEndpoint, Version version) + protected AccessTokenRefreshRequest(Uri tokenEndpoint, Version version) : base(tokenEndpoint, version) { } /// <summary> - /// Initializes a new instance of the <see cref="AccessTokenRefreshRequest"/> class. - /// </summary> - /// <param name="authorizationServer">The authorization server.</param> - internal AccessTokenRefreshRequest(AuthorizationServerDescription authorizationServer) - : this(authorizationServer.TokenEndpoint, authorizationServer.Version) { - } - - #region IRefreshTokenCarryingRequest members - - /// <summary> - /// Gets or sets the verification code or refresh/access token. - /// </summary> - /// <value>The code or token.</value> - string IRefreshTokenCarryingRequest.RefreshToken { - get { return this.RefreshToken; } - set { this.RefreshToken = value; } - } - - /// <summary> - /// Gets or sets the authorization that the token describes. - /// </summary> - RefreshToken IRefreshTokenCarryingRequest.AuthorizationDescription { get; set; } - - /// <summary> - /// Gets the authorization that the token describes. - /// </summary> - IAuthorizationDescription IAuthorizationCarryingRequest.AuthorizationDescription { - get { return ((IRefreshTokenCarryingRequest)this).AuthorizationDescription; } - } - - #endregion - - /// <summary> /// Gets or sets the refresh token. /// </summary> /// <value>The refresh token.</value> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenRequestBase.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenRequestBase.cs index 7e41fcd..b9f4c56 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenRequestBase.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenRequestBase.cs @@ -16,7 +16,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// <summary> /// A message sent from the client to the authorization server to exchange a previously obtained grant for an access token. /// </summary> - public abstract class AccessTokenRequestBase : AuthenticatedClientRequestBase, IAccessTokenRequest { + public abstract class AccessTokenRequestBase : AuthenticatedClientRequestBase, IAccessTokenRequestInternal, IDisposable { /// <summary> /// Initializes a new instance of the <see cref="AccessTokenRequestBase"/> class. /// </summary> @@ -45,6 +45,14 @@ namespace DotNetOpenAuth.OAuth2.Messages { } /// <summary> + /// Gets or sets the access token creation parameters. + /// </summary> + /// <remarks> + /// This property's value is set by a binding element in the OAuth 2 channel. + /// </remarks> + AccessTokenParameters IAccessTokenRequestInternal.AccessTokenCreationParameters { get; set; } + + /// <summary> /// Gets the type of the grant. /// </summary> /// <value>The type of the grant.</value> @@ -57,6 +65,25 @@ namespace DotNetOpenAuth.OAuth2.Messages { protected abstract HashSet<string> RequestedScope { get; } /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + public void Dispose() { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + /// <summary> + /// Releases unmanaged and - optionally - managed resources + /// </summary> + /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> + protected virtual void Dispose(bool disposing) { + IAccessTokenRequestInternal self = this; + if (self.AccessTokenCreationParameters != null) { + self.AccessTokenCreationParameters.Dispose(); + } + } + + /// <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.OAuth2/OAuth2/Messages/AccessTokenResourceOwnerPasswordCredentialsRequest.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenResourceOwnerPasswordCredentialsRequest.cs index 52e65be..52e65be 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenResourceOwnerPasswordCredentialsRequest.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenResourceOwnerPasswordCredentialsRequest.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenSuccessResponse.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenSuccessResponse.cs index 6d278c4..5dc3271 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenSuccessResponse.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenSuccessResponse.cs @@ -18,7 +18,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// <remarks> /// This message type is shared by the Web App, Rich App, and Username/Password profiles. /// </remarks> - internal class AccessTokenSuccessResponse : MessageBase, IHttpDirectResponse { + internal class AccessTokenSuccessResponse : MessageBase, IHttpDirectResponse, IAccessTokenIssuingResponse { /// <summary> /// Initializes a new instance of the <see cref="AccessTokenSuccessResponse"/> class. /// </summary> @@ -92,6 +92,50 @@ namespace DotNetOpenAuth.OAuth2.Messages { [MessagePart(Protocol.scope, IsRequired = false, Encoder = typeof(ScopeEncoder))] public HashSet<string> Scope { get; private set; } + #region IAccessTokenIssuingResponse Members + + /// <summary> + /// Gets or sets the lifetime of the access token. + /// </summary> + /// <value> + /// The lifetime. + /// </value> + TimeSpan? IAccessTokenIssuingResponse.Lifetime { + get { return this.Lifetime; } + set { this.Lifetime = value; } + } + + #endregion + + #region IAuthorizationCarryingRequest + + /// <summary> + /// Gets the authorization that the token describes. + /// </summary> + IAuthorizationDescription IAuthorizationCarryingRequest.AuthorizationDescription { + get { return ((IAccessTokenCarryingRequest)this).AuthorizationDescription; } + } + + #endregion + + #region IAccessTokenCarryingRequest Members + + /// <summary> + /// Gets or sets the authorization that the token describes. + /// </summary> + /// <value></value> + AccessToken IAccessTokenCarryingRequest.AuthorizationDescription { get; set; } + + /// <summary> + /// Gets or sets the access token. + /// </summary> + string IAccessTokenCarryingRequest.AccessToken { + get { return this.AccessToken; } + set { this.AccessToken = value; } + } + + #endregion + /// <summary> /// Gets or sets a value indicating whether a refresh token is or should be included in the response. /// </summary> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AuthenticatedClientRequestBase.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AuthenticatedClientRequestBase.cs index bc4d0ca..bc4d0ca 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AuthenticatedClientRequestBase.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AuthenticatedClientRequestBase.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs index 7cc8e82..7cc8e82 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationImplicitRequest.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationImplicitRequest.cs index f5a5d67..661e2ae 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationImplicitRequest.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationImplicitRequest.cs @@ -18,7 +18,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// to issue an access token to the client if permission is granted. /// </summary> [Serializable] - public class EndUserAuthorizationImplicitRequest : EndUserAuthorizationRequest, IAccessTokenRequest { + public class EndUserAuthorizationImplicitRequest : EndUserAuthorizationRequest, IAccessTokenRequestInternal { /// <summary> /// Gets or sets the grant type that the client expects of the authorization server. /// </summary> @@ -31,19 +31,11 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// </summary> /// <param name="authorizationEndpoint">The Authorization Server's user authorization URL to direct the user to.</param> /// <param name="version">The protocol version.</param> - internal EndUserAuthorizationImplicitRequest(Uri authorizationEndpoint, Version version) + protected EndUserAuthorizationImplicitRequest(Uri authorizationEndpoint, Version version) : base(authorizationEndpoint, version) { } /// <summary> - /// Initializes a new instance of the <see cref="EndUserAuthorizationImplicitRequest"/> class. - /// </summary> - /// <param name="authorizationServer">The authorization server.</param> - internal EndUserAuthorizationImplicitRequest(AuthorizationServerDescription authorizationServer) - : this(authorizationServer.AuthorizationEndpoint, authorizationServer.Version) { - } - - /// <summary> /// Gets the grant type that the client expects of the authorization server. /// </summary> public override EndUserAuthorizationResponseType ResponseType { @@ -51,6 +43,14 @@ namespace DotNetOpenAuth.OAuth2.Messages { } /// <summary> + /// Gets or sets the access token creation parameters. + /// </summary> + /// <remarks> + /// This property's value is set by a binding element in the OAuth 2 channel. + /// </remarks> + AccessTokenParameters IAccessTokenRequestInternal.AccessTokenCreationParameters { get; set; } + + /// <summary> /// Gets a value indicating whether the client requesting the access token has authenticated itself. /// </summary> /// <value> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationRequest.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationRequest.cs index 45fa049..f229cf9 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationRequest.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationRequest.cs @@ -32,7 +32,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// </summary> /// <param name="authorizationEndpoint">The Authorization Server's user authorization URL to direct the user to.</param> /// <param name="version">The protocol version.</param> - internal EndUserAuthorizationRequest(Uri authorizationEndpoint, Version version) + protected EndUserAuthorizationRequest(Uri authorizationEndpoint, Version version) : base(version, MessageTransport.Indirect, authorizationEndpoint) { Requires.NotNull(authorizationEndpoint, "authorizationEndpoint"); Requires.NotNull(version, "version"); @@ -41,17 +41,6 @@ namespace DotNetOpenAuth.OAuth2.Messages { } /// <summary> - /// Initializes a new instance of the <see cref="EndUserAuthorizationRequest"/> class. - /// </summary> - /// <param name="authorizationServer">The authorization server.</param> - internal EndUserAuthorizationRequest(AuthorizationServerDescription authorizationServer) - : this(authorizationServer.AuthorizationEndpoint, authorizationServer.Version) { - Requires.NotNull(authorizationServer, "authorizationServer"); - Requires.True(authorizationServer.Version != null, "authorizationServer"); - Requires.True(authorizationServer.AuthorizationEndpoint != null, "authorizationServer"); - } - - /// <summary> /// Gets the grant type that the client expects of the authorization server. /// </summary> public virtual EndUserAuthorizationResponseType ResponseType { diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationResponseType.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationResponseType.cs index 75ece0f..75ece0f 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationResponseType.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationResponseType.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationSuccessAccessTokenResponse.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationSuccessAccessTokenResponse.cs index 5c03e7a..7a79e46 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationSuccessAccessTokenResponse.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationSuccessAccessTokenResponse.cs @@ -19,7 +19,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// to indicate that user authorization was granted, carrying only an access token, /// and to return the user to the Client where they started their experience. /// </summary> - internal class EndUserAuthorizationSuccessAccessTokenResponse : EndUserAuthorizationSuccessResponseBase, IAccessTokenCarryingRequest, IHttpIndirectResponse { + internal class EndUserAuthorizationSuccessAccessTokenResponse : EndUserAuthorizationSuccessResponseBase, IAccessTokenIssuingResponse, IHttpIndirectResponse { /// <summary> /// Initializes a new instance of the <see cref="EndUserAuthorizationSuccessAccessTokenResponse"/> class. /// </summary> @@ -75,6 +75,17 @@ namespace DotNetOpenAuth.OAuth2.Messages { #endregion /// <summary> + /// Gets or sets the lifetime of the access token. + /// </summary> + /// <value> + /// The lifetime. + /// </value> + TimeSpan? IAccessTokenIssuingResponse.Lifetime { + get { return this.Lifetime; } + set { this.Lifetime = value; } + } + + /// <summary> /// Gets or sets the token type. /// </summary> /// <value>Usually "bearer".</value> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationSuccessAuthCodeResponse.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationSuccessAuthCodeResponse.cs index dcacc14..9d6b015 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationSuccessAuthCodeResponse.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationSuccessAuthCodeResponse.cs @@ -16,7 +16,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// to indicate that user authorization was granted, carrying an authorization code and possibly an access token, /// and to return the user to the Client where they started their experience. /// </summary> - internal class EndUserAuthorizationSuccessAuthCodeResponse : EndUserAuthorizationSuccessResponseBase, IAuthorizationCodeCarryingRequest { + internal class EndUserAuthorizationSuccessAuthCodeResponse : EndUserAuthorizationSuccessResponseBase { /// <summary> /// Initializes a new instance of the <see cref="EndUserAuthorizationSuccessAuthCodeResponse"/> class. /// </summary> @@ -40,30 +40,6 @@ namespace DotNetOpenAuth.OAuth2.Messages { ((IMessageWithClientState)this).ClientState = request.ClientState; } - #region IAuthorizationCodeCarryingRequest Members - - /// <summary> - /// Gets or sets the authorization code. - /// </summary> - string IAuthorizationCodeCarryingRequest.Code { - get { return this.AuthorizationCode; } - set { this.AuthorizationCode = value; } - } - - /// <summary> - /// Gets or sets the authorization that the token describes. - /// </summary> - AuthorizationCode IAuthorizationCodeCarryingRequest.AuthorizationDescription { get; set; } - - /// <summary> - /// Gets the authorization that the code describes. - /// </summary> - IAuthorizationDescription IAuthorizationCarryingRequest.AuthorizationDescription { - get { return ((IAuthorizationCodeCarryingRequest)this).AuthorizationDescription; } - } - - #endregion - /// <summary> /// Gets or sets the authorization code. /// </summary> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs index ef0010e..ef0010e 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/GrantType.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/GrantType.cs index a26d405..a26d405 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/GrantType.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/GrantType.cs diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenIssuingResponse.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenIssuingResponse.cs new file mode 100644 index 0000000..1a54aca --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenIssuingResponse.cs @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------- +// <copyright file="IAccessTokenIssuingResponse.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using DotNetOpenAuth.OAuth2.ChannelElements; + + /// <summary> + /// A message sent from the Authorization Server to the client carrying an access token. + /// </summary> + internal interface IAccessTokenIssuingResponse : IAccessTokenCarryingRequest { + /// <summary> + /// Gets or sets the lifetime of the access token. + /// </summary> + /// <value>The lifetime.</value> + TimeSpan? Lifetime { get; set; } + } +} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/IAccessTokenRequest.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenRequest.cs index 65378f9..65378f9 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/IAccessTokenRequest.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenRequest.cs diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenRequestInternal.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenRequestInternal.cs new file mode 100644 index 0000000..e218462 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenRequestInternal.cs @@ -0,0 +1,25 @@ +//----------------------------------------------------------------------- +// <copyright file="IAccessTokenRequestInternal.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + /// <summary> + /// Implemented by all message types whose response may contain an access token. + /// </summary> + public interface IAccessTokenRequestInternal : IAccessTokenRequest { + /// <summary> + /// Gets or sets the access token creation parameters. + /// </summary> + /// <remarks> + /// This property's value is set by a binding element in the OAuth 2 channel. + /// </remarks> + AccessTokenParameters AccessTokenCreationParameters { get; set; } + } +} diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/IMessageWithClientState.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IMessageWithClientState.cs index 71476f2..71476f2 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/IMessageWithClientState.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IMessageWithClientState.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/ScopedAccessTokenRequest.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/ScopedAccessTokenRequest.cs index 0ea6efb..0ea6efb 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/ScopedAccessTokenRequest.cs +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/ScopedAccessTokenRequest.cs diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/TokenEndpointProtocolException.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/TokenEndpointProtocolException.cs new file mode 100644 index 0000000..308bfe2 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/TokenEndpointProtocolException.cs @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------- +// <copyright file="TokenEndpointProtocolException.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth2 { + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Text; + + using DotNetOpenAuth.Messaging; + + /// <summary> + /// Describes an error generated by an Authorization Server's token endpoint. + /// </summary> + public class TokenEndpointProtocolException : ProtocolException { + /// <summary> + /// Initializes a new instance of the <see cref="TokenEndpointProtocolException"/> class. + /// </summary> + /// <param name="error">A single error code from <see cref="Protocol.AccessTokenRequestErrorCodes"/>.</param> + /// <param name="description">A human-readable UTF-8 encoded text providing additional information, used to assist the client developer in understanding the error that occurred.</param> + /// <param name="moreInformation">A URI identifying a human-readable web page with information about the error, used to provide the client developer with additional information about the error.</param> + public TokenEndpointProtocolException(string error, string description = null, Uri moreInformation = null) + : base(string.Format(CultureInfo.CurrentCulture, ClientAuthorizationStrings.TokenEndpointErrorFormat, error, description)) { + Requires.NotNullOrEmpty(error, "error"); + + this.Error = error; + this.Description = description; + this.MoreInformation = moreInformation; + } + + /// <summary> + /// Initializes a new instance of the <see cref="TokenEndpointProtocolException"/> class. + /// </summary> + /// <param name="innerException">The inner exception.</param> + public TokenEndpointProtocolException(Exception innerException) + : base(Protocol.AccessTokenRequestErrorCodes.InvalidRequest, innerException) { + this.Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest; + } + + /// <summary> + /// Gets a single error code from <see cref="Protocol.AccessTokenRequestErrorCodes"/>. + /// </summary> + public string Error { get; private set; } + + /// <summary> + /// Gets a human-readable UTF-8 encoded text providing additional information, used to assist the client developer in understanding the error that occurred. + /// </summary> + public string Description { get; private set; } + + /// <summary> + /// Gets a URI identifying a human-readable web page with information about the error, used to provide the client developer with additional information about the error. + /// </summary> + public Uri MoreInformation { get; private set; } + } +} diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d536886 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/Properties/AssemblyInfo.cs @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------- +// <copyright file="AssemblyInfo.cs" company="Outercurve Foundation"> +// Copyright (c) Outercurve Foundation. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +// We DON'T put an AssemblyVersionAttribute in here because it is generated in the build. + +using System; +using System.Diagnostics.Contracts; +using System.Net; +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Security.Permissions; +using System.Web.UI; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DotNetOpenAuth OAuth 2.0")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DotNetOpenAuth")] +[assembly: AssemblyCopyright("Copyright © 2011 Outercurve Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("en-US")] +[assembly: CLSCompliant(true)] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7d73990c-47c0-4256-9f20-a893add9e289")] + +[assembly: ContractVerification(true)] + +#if StrongNameSigned +// See comment at top of this file. We need this so that strong-naming doesn't +// keep this assembly from being useful to shared host (medium trust) web sites. +[assembly: AllowPartiallyTrustedCallers] + +[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.Client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.AuthorizationServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] +#else +[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.Client")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.AuthorizationServer")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.Test")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] +#endif diff --git a/src/DotNetOpenAuth.OAuth2.ResourceServer/DotNetOpenAuth.OAuth2.ResourceServer.csproj b/src/DotNetOpenAuth.OAuth2.ResourceServer/DotNetOpenAuth.OAuth2.ResourceServer.csproj index f4ac48c..154890c 100644 --- a/src/DotNetOpenAuth.OAuth2.ResourceServer/DotNetOpenAuth.OAuth2.ResourceServer.csproj +++ b/src/DotNetOpenAuth.OAuth2.ResourceServer/DotNetOpenAuth.OAuth2.ResourceServer.csproj @@ -18,12 +18,15 @@ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> </PropertyGroup> <ItemGroup> + <Compile Include="OAuth2\ChannelElements\OAuth2ResourceServerChannel.cs" /> + <Compile Include="OAuth2\IAccessTokenAnalyzer.cs" /> <Compile Include="OAuth2\OAuth2Strings.Designer.cs"> <AutoGen>True</AutoGen> <DesignTime>True</DesignTime> <DependentUpon>OAuth2Strings.resx</DependentUpon> </Compile> <Compile Include="OAuth2\ResourceServer.cs" /> + <Compile Include="OAuth2\StandardAccessTokenAnalyzer.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <ItemGroup> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ResourceServerChannel.cs b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/ChannelElements/OAuth2ResourceServerChannel.cs index 947c044..22514b4 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ResourceServerChannel.cs +++ b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/ChannelElements/OAuth2ResourceServerChannel.cs @@ -52,8 +52,8 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { var fields = new Dictionary<string, string>(); string accessToken; if ((accessToken = SearchForBearerAccessTokenInRequest(request)) != null) { - fields["token_type"] = Protocol.AccessTokenTypes.Bearer; - fields["access_token"] = accessToken; + fields[Protocol.token_type] = Protocol.AccessTokenTypes.Bearer; + fields[Protocol.access_token] = accessToken; } if (fields.Count > 0) { diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/IAccessTokenAnalyzer.cs b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/IAccessTokenAnalyzer.cs index 5aa1bb6..5aa1bb6 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/IAccessTokenAnalyzer.cs +++ b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/IAccessTokenAnalyzer.cs diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/StandardAccessTokenAnalyzer.cs b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/StandardAccessTokenAnalyzer.cs index 636f490..636f490 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/StandardAccessTokenAnalyzer.cs +++ b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/StandardAccessTokenAnalyzer.cs diff --git a/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj b/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj index 438a21d..1b410ac 100644 --- a/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj +++ b/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj @@ -19,71 +19,25 @@ </PropertyGroup> <ItemGroup> <Compile Include="GlobalSuppressions.cs" /> - <Compile Include="OAuth2\AuthorizationState.cs" /> - <Compile Include="OAuth2\ChannelElements\AccessRequestBindingElement.cs" /> <Compile Include="OAuth2\ChannelElements\AccessToken.cs" /> - <Compile Include="OAuth2\ChannelElements\AccessTokenBindingElement.cs" /> <Compile Include="OAuth2\ChannelElements\AuthorizationDataBag.cs" /> - <Compile Include="OAuth2\ChannelElements\AuthServerBindingElementBase.cs" /> - <Compile Include="OAuth2\ChannelElements\GrantTypeEncoder.cs" /> - <Compile Include="OAuth2\ChannelElements\EndUserAuthorizationResponseTypeEncoder.cs" /> <Compile Include="OAuth2\ChannelElements\IAccessTokenCarryingRequest.cs" /> - <Compile Include="OAuth2\ChannelElements\IAuthorizationCodeCarryingRequest.cs" /> - <Compile Include="OAuth2\ChannelElements\IOAuth2ChannelWithAuthorizationServer.cs" /> - <Compile Include="OAuth2\ChannelElements\IRefreshTokenCarryingRequest.cs" /> - <Compile Include="OAuth2\ChannelElements\OAuth2ChannelBase.cs" /> - <Compile Include="OAuth2\ChannelElements\OAuth2ClientChannel.cs" /> <Compile Include="OAuth2\ChannelElements\ScopeEncoder.cs" /> <Compile Include="OAuth2\ChannelElements\IAuthorizationDescription.cs" /> <Compile Include="OAuth2\ChannelElements\IAuthorizationCarryingRequest.cs" /> - <Compile Include="OAuth2\ChannelElements\OAuth2ResourceServerChannel.cs" /> - <Compile Include="OAuth2\ChannelElements\RefreshToken.cs" /> - <Compile Include="OAuth2\ChannelElements\AuthorizationCode.cs" /> - <Compile Include="OAuth2\ChannelElements\AuthorizationCodeBindingElement.cs" /> - <Compile Include="OAuth2\ChannelElements\AuthServerAllFlowsBindingElement.cs" /> - <Compile Include="OAuth2\ClientDescription.cs" /> - <Compile Include="OAuth2\ClientType.cs" /> - <Compile Include="OAuth2\IAccessTokenAnalyzer.cs" /> - <Compile Include="OAuth2\IAuthorizationServer.cs" /> - <Compile Include="OAuth2\IAuthorizationState.cs" /> - <Compile Include="OAuth2\IClientAuthorizationTracker.cs" /> - <Compile Include="OAuth2\IClientDescription.cs" /> <Compile Include="OAuth2\Messages\AccessProtectedResourceRequest.cs" /> - <Compile Include="OAuth2\Messages\AccessTokenAuthorizationCodeRequest.cs" /> - <Compile Include="OAuth2\Messages\AccessTokenResourceOwnerPasswordCredentialsRequest.cs" /> - <Compile Include="OAuth2\Messages\AccessTokenRequestBase.cs" /> - <Compile Include="OAuth2\Messages\AccessTokenClientCredentialsRequest.cs" /> - <Compile Include="OAuth2\Messages\AuthenticatedClientRequestBase.cs" /> - <Compile Include="OAuth2\Messages\EndUserAuthorizationImplicitRequest.cs" /> - <Compile Include="OAuth2\Messages\EndUserAuthorizationSuccessAccessTokenResponse.cs" /> - <Compile Include="OAuth2\Messages\EndUserAuthorizationFailedResponse.cs" /> - <Compile Include="OAuth2\Messages\EndUserAuthorizationSuccessAuthCodeResponse.cs" /> - <Compile Include="OAuth2\Messages\GrantType.cs" /> - <Compile Include="OAuth2\Messages\AccessTokenRefreshRequest.cs" /> - <Compile Include="OAuth2\Messages\EndUserAuthorizationResponseType.cs" /> - <Compile Include="OAuth2\Messages\IAccessTokenRequest.cs" /> - <Compile Include="OAuth2\Messages\IMessageWithClientState.cs" /> - <Compile Include="OAuth2\Messages\ScopedAccessTokenRequest.cs" /> <Compile Include="OAuth2\Messages\UnauthorizedResponse.cs" /> - <Compile Include="OAuth2\Messages\AccessTokenFailedResponse.cs" /> - <Compile Include="OAuth2\Messages\AccessTokenSuccessResponse.cs" /> - <Compile Include="OAuth2\Messages\EndUserAuthorizationSuccessResponseBase.cs" /> - <Compile Include="OAuth2\StandardAccessTokenAnalyzer.cs" /> <Compile Include="OAuth2\OAuthUtilities.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="OAuth2\ChannelElements\OAuth2AuthorizationServerChannel.cs" /> <Compile Include="OAuth2\Messages\MessageBase.cs" /> - <Compile Include="OAuth2\Messages\EndUserAuthorizationRequest.cs" /> <Compile Include="OAuth2\Protocol.cs" /> <Compile Include="OAuth2\OAuthStrings.Designer.cs"> <AutoGen>True</AutoGen> <DesignTime>True</DesignTime> <DependentUpon>OAuthStrings.resx</DependentUpon> </Compile> - <Compile Include="OAuth2\AuthorizationServerDescription.cs" /> </ItemGroup> <ItemGroup> - <None Include="OAuth2\Messages\OAuth 2 Messages.cd" /> <None Include="OAuth2\OAuth 2 client facades.cd" /> </ItemGroup> <ItemGroup> 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/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/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/Messages/OAuth 2 Messages.cd b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/OAuth 2 Messages.cd deleted file mode 100644 index 05e3ad9..0000000 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/OAuth 2 Messages.cd +++ /dev/null @@ -1,164 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<ClassDiagram MajorVersion="1" MinorVersion="1"> - <Class Name="DotNetOpenAuth.OAuth2.Messages.MessageBase" Collapsed="true"> - <Position X="0.5" Y="0.5" Width="1.5" /> - <TypeIdentifier> - <HashCode>IAAMACQAQAAAgAkAAAAIAAYACgAAIAAAIACAACAAAIA=</HashCode> - <FileName>OAuth2\Messages\MessageBase.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.AccessTokenAuthorizationCodeRequest" Collapsed="true"> - <Position X="8.5" Y="6.75" Width="3" /> - <TypeIdentifier> - <HashCode>ACAAEAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAgAAAATAA=</HashCode> - <FileName>OAuth2\Messages\AccessTokenAuthorizationCodeRequest.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.AccessTokenClientCredentialsRequest" Collapsed="true"> - <Position X="8.5" Y="8.75" Width="2.75" /> - <TypeIdentifier> - <HashCode>AAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAA=</HashCode> - <FileName>OAuth2\Messages\AccessTokenClientCredentialsRequest.cs</FileName> - </TypeIdentifier> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.AccessTokenFailedResponse" Collapsed="true"> - <Position X="3.25" Y="8.5" Width="2.25" /> - <TypeIdentifier> - <HashCode>AAAAAIAAAAAAAQAAAABAAAQAAAAAAAEQAAAAAAAAAAA=</HashCode> - <FileName>OAuth2\Messages\AccessTokenFailedResponse.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.AccessTokenRefreshRequest" Collapsed="true"> - <Position X="8.5" Y="9.75" Width="2.25" /> - <TypeIdentifier> - <HashCode>AAAAEAAAQAAAAAAAAAAAAAAQAAAAAAAAAAAgAAAABAA=</HashCode> - <FileName>OAuth2\Messages\AccessTokenRefreshRequest.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.AccessTokenRequestBase" Collapsed="true"> - <Position X="5.75" Y="5.75" Width="2" /> - <TypeIdentifier> - <HashCode>AAAAAAAAQABAAAAAAAAAAAAQAAAAAAAAAAAAAAAACAA=</HashCode> - <FileName>OAuth2\Messages\AccessTokenRequestBase.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.AccessTokenResourceOwnerPasswordCredentialsRequest" Collapsed="true"> - <Position X="8.5" Y="10.5" Width="4" /> - <TypeIdentifier> - <HashCode>AAAAAAAAAAAAAAAAAAAAAAAQAAAAAAACAQAAAAAAAAA=</HashCode> - <FileName>OAuth2\Messages\AccessTokenResourceOwnerPasswordCredentialsRequest.cs</FileName> - </TypeIdentifier> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.AccessTokenSuccessResponse" Collapsed="true"> - <Position X="3.25" Y="7.5" Width="2.25" /> - <TypeIdentifier> - <HashCode>AAAAAAAAQAAAACAAAAAAAAQAEAAAAAAQAEAAAAAAAgA=</HashCode> - <FileName>OAuth2\Messages\AccessTokenSuccessResponse.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.AuthenticatedClientRequestBase" Collapsed="true"> - <Position X="3.25" Y="5.25" Width="2.25" /> - <TypeIdentifier> - <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAA=</HashCode> - <FileName>OAuth2\Messages\AuthenticatedClientRequestBase.cs</FileName> - </TypeIdentifier> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.EndUserAuthorizationFailedResponse" Collapsed="true"> - <Position X="3.25" Y="4.5" Width="2.75" /> - <TypeIdentifier> - <HashCode>AAAAAIAAAAAAAQAAAAAAAAgAAAAAAAEAAAAAAAAAAAA=</HashCode> - <FileName>OAuth2\Messages\EndUserAuthorizationFailedResponse.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.EndUserAuthorizationRequest" Collapsed="true"> - <Position X="3.25" Y="0.5" Width="2.25" /> - <TypeIdentifier> - <HashCode>AAAAAAAAQABAACAAAAAAAACAAAQAAAQAAAAAAAAAQAA=</HashCode> - <FileName>OAuth2\Messages\EndUserAuthorizationRequest.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.EndUserAuthorizationSuccessAccessTokenResponse" Collapsed="true"> - <Position X="6.25" Y="3.75" Width="3.75" /> - <TypeIdentifier> - <HashCode>AAAAEAAAAAAAAAAAAAAAAAACEAAAAAAAAAAgAAAABgA=</HashCode> - <FileName>OAuth2\Messages\EndUserAuthorizationSuccessAccessTokenResponse.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.EndUserAuthorizationSuccessAuthCodeResponse" Collapsed="true"> - <Position X="6.25" Y="2.5" Width="3.5" /> - <TypeIdentifier> - <HashCode>ACAAEAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAgAAAABAA=</HashCode> - <FileName>OAuth2\Messages\EndUserAuthorizationSuccessAuthCodeResponse.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.EndUserAuthorizationSuccessResponseBase" Collapsed="true"> - <Position X="3.25" Y="1.5" Width="2.75" /> - <TypeIdentifier> - <HashCode>AAACAAAAAAAAACAAAAAAAAgAAAAAAAAAAEAAAAAAAAA=</HashCode> - <FileName>OAuth2\Messages\EndUserAuthorizationSuccessResponseBase.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.AccessProtectedResourceRequest" Collapsed="true"> - <Position X="3.25" Y="9.75" Width="2.5" /> - <TypeIdentifier> - <HashCode>AAAAEAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAgAAAABgA=</HashCode> - <FileName>OAuth2\Messages\AccessProtectedResourceRequest.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.UnauthorizedResponse" Collapsed="true"> - <Position X="3.25" Y="10.75" Width="2" /> - <TypeIdentifier> - <HashCode>AUABAAAAAAAAACAAAAAAAAQIAAAAAAAQAAAAAAAAABA=</HashCode> - <FileName>OAuth2\Messages\UnauthorizedResponse.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OAuth2.Messages.ScopedAccessTokenRequest" Collapsed="true"> - <Position X="6.75" Y="7.75" Width="2.25" /> - <TypeIdentifier> - <HashCode>AAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAACAA=</HashCode> - <FileName>OAuth2\Messages\ScopedAccessTokenRequest.cs</FileName> - </TypeIdentifier> - </Class> - <Interface Name="DotNetOpenAuth.OAuth2.Messages.IMessageWithClientState"> - <Position X="11.5" Y="0.5" Width="2" /> - <TypeIdentifier> - <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAA=</HashCode> - <FileName>OAuth2\Messages\IMessageWithClientState.cs</FileName> - </TypeIdentifier> - </Interface> - <Interface Name="DotNetOpenAuth.OAuth2.ChannelElements.IAuthorizationCarryingRequest"> - <Position X="11.75" Y="2" Width="2.5" /> - <TypeIdentifier> - <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAEAAAAA=</HashCode> - <FileName>OAuth2\ChannelElements\IAuthorizationCarryingRequest.cs</FileName> - </TypeIdentifier> - </Interface> - <Enum Name="DotNetOpenAuth.OAuth2.Messages.EndUserAuthorizationResponseType"> - <Position X="8" Y="0.5" Width="3" /> - <TypeIdentifier> - <HashCode>ACAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAA=</HashCode> - <FileName>OAuth2\Messages\EndUserAuthorizationResponseType.cs</FileName> - </TypeIdentifier> - </Enum> - <Enum Name="DotNetOpenAuth.OAuth2.Messages.GrantType"> - <Position X="6.25" Y="0.5" Width="1.5" /> - <TypeIdentifier> - <HashCode>ACAAAAAAQAAAAAQAAgAAAAAAAAAAAAACAAAAAAAAAAA=</HashCode> - <FileName>OAuth2\Messages\GrantType.cs</FileName> - </TypeIdentifier> - </Enum> - <Font Name="Segoe UI" Size="9" /> -</ClassDiagram>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.Designer.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.Designer.cs index 6ce3b53..d975330 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.Designer.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. -// Runtime Version:4.0.30319.239 +// Runtime Version:4.0.30319.17611 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -70,15 +70,6 @@ namespace DotNetOpenAuth.OAuth2 { } /// <summary> - /// Looks up a localized string similar to The requested access scope ("{0}") exceeds the grant scope ("{1}").. - /// </summary> - internal static string AccessScopeExceedsGrantScope { - get { - return ResourceManager.GetString("AccessScopeExceedsGrantScope", resourceCulture); - } - } - - /// <summary> /// Looks up a localized string similar to The access token contains characters that must not appear in the HTTP Authorization header.. /// </summary> internal static string AccessTokenInvalidForHttpAuthorizationHeader { diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.resx b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.resx index af1a955..11c24f4 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.resx +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.resx @@ -120,9 +120,6 @@ <data name="AbsoluteUriRequired" xml:space="preserve"> <value>The value for message part "{0}" must be an absolute URI.</value> </data> - <data name="AccessScopeExceedsGrantScope" xml:space="preserve"> - <value>The requested access scope ("{0}") exceeds the grant scope ("{1}").</value> - </data> <data name="AccessTokenInvalidForHttpAuthorizationHeader" xml:space="preserve"> <value>The access token contains characters that must not appear in the HTTP Authorization header.</value> </data> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs index dd7909b..eb5c8e4 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs @@ -129,26 +129,5 @@ namespace DotNetOpenAuth.OAuth2 { Protocol.BearerHttpAuthorizationHeaderFormat, accessToken); } - - /// <summary> - /// Gets information about the client with a given identifier. - /// </summary> - /// <param name="authorizationServer">The authorization server.</param> - /// <param name="clientIdentifier">The client identifier.</param> - /// <returns>The client information. Never null.</returns> - internal static IClientDescription GetClientOrThrow(this IAuthorizationServer authorizationServer, string clientIdentifier) { - Requires.NotNullOrEmpty(clientIdentifier, "clientIdentifier"); - Contract.Ensures(Contract.Result<IClientDescription>() != null); - - try { - var result = authorizationServer.GetClient(clientIdentifier); - ErrorUtilities.VerifyHost(result != null, OAuthStrings.ResultShouldNotBeNull, authorizationServer.GetType().FullName, "GetClient(string)"); - return result; - } catch (KeyNotFoundException ex) { - throw ErrorUtilities.Wrap(ex, OAuthStrings.ClientOrTokenSecretNotFound); - } catch (ArgumentException ex) { - throw ErrorUtilities.Wrap(ex, OAuthStrings.ClientOrTokenSecretNotFound); - } - } } } diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Protocol.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/Protocol.cs index 19fe845..986af13 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Protocol.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/Protocol.cs @@ -45,11 +45,6 @@ namespace DotNetOpenAuth.OAuth2 { internal const string BearerTokenEncodedUrlParameterName = "access_token"; /// <summary> - /// The "type" string. - /// </summary> - internal const string type = "type"; - - /// <summary> /// The "state" string. /// </summary> internal const string state = "state"; @@ -60,26 +55,6 @@ namespace DotNetOpenAuth.OAuth2 { internal const string redirect_uri_mismatch = "redirect_uri_mismatch"; /// <summary> - /// The "bad_verification_code" string. - /// </summary> - internal const string bad_verification_code = "bad_verification_code"; - - /// <summary> - /// The "incorrect_client_credentials" string. - /// </summary> - internal const string incorrect_client_credentials = "incorrect_client_credentials"; - - /// <summary> - /// The "unauthorized_client" string. - /// </summary> - internal const string unauthorized_client = "unauthorized_client"; - - /// <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"; @@ -95,11 +70,6 @@ namespace DotNetOpenAuth.OAuth2 { internal const string scope = "scope"; /// <summary> - /// The "immediate" string. - /// </summary> - internal const string immediate = "immediate"; - - /// <summary> /// The "client_secret" string. /// </summary> internal const string client_secret = "client_secret"; @@ -110,21 +80,6 @@ namespace DotNetOpenAuth.OAuth2 { internal const string code = "code"; /// <summary> - /// The "user_code" string. - /// </summary> - internal const string user_code = "user_code"; - - /// <summary> - /// The "verification_uri" string. - /// </summary> - internal const string verification_uri = "verification_uri"; - - /// <summary> - /// The "interval" string. - /// </summary> - internal const string interval = "interval"; - - /// <summary> /// The "error" string. /// </summary> internal const string error = "error"; @@ -135,11 +90,6 @@ namespace DotNetOpenAuth.OAuth2 { internal const string access_token = "access_token"; /// <summary> - /// The "access_token_secret" string. - /// </summary> - internal const string access_token_secret = "access_token_secret"; - - /// <summary> /// The "token_type" string. /// </summary> internal const string token_type = "token_type"; @@ -155,11 +105,6 @@ namespace DotNetOpenAuth.OAuth2 { internal const string expires_in = "expires_in"; /// <summary> - /// The "expired_delegation_code" string. - /// </summary> - internal const string expired_delegation_code = "expired_delegation_code"; - - /// <summary> /// The "username" string. /// </summary> internal const string username = "username"; @@ -170,26 +115,6 @@ namespace DotNetOpenAuth.OAuth2 { internal const string password = "password"; /// <summary> - /// The "format" string. - /// </summary> - internal const string format = "format"; - - /// <summary> - /// The "assertion" string. - /// </summary> - internal const string assertion = "assertion"; - - /// <summary> - /// The "assertion_type" string. - /// </summary> - internal const string assertion_type = "assertion_type"; - - /// <summary> - /// The "user_denied" string. - /// </summary> - internal const string user_denied = "user_denied"; - - /// <summary> /// Gets the <see cref="Protocol"/> instance with values initialized for V1.0 of the protocol. /// </summary> internal static readonly Protocol V20 = new Protocol { @@ -286,27 +211,38 @@ namespace DotNetOpenAuth.OAuth2 { internal static class AccessTokenRequestErrorCodes { /// <summary> - /// The request is missing a required parameter, includes an unknown parameter or parameter value, repeats a parameter, includes multiple credentials, utilizes more than one mechanism for authenticating the client, or is otherwise malformed. + /// The request is missing a required parameter, includes an unknown parameter or parameter value, repeats a parameter, + /// includes multiple credentials, utilizes more than one mechanism for authenticating the client, or is otherwise malformed. /// </summary> internal const string InvalidRequest = "invalid_request"; /// <summary> - /// The client is not authorized to use the access grant type provided. + /// Client authentication failed (e.g. unknown client, no client authentication included, or unsupported authentication method). + /// The authorization server MAY return an HTTP 401 (Unauthorized) status code to indicate which HTTP authentication schemes are supported. + /// If the client attempted to authenticate via the Authorization request header field, the authorization server MUST respond with + /// an HTTP 401 (Unauthorized) status code, and include the WWW-Authenticate response header field matching the authentication scheme + /// used by the client. /// </summary> - internal const string UnauthorizedClient = "unauthorized_client"; + internal const string InvalidClient = "invalid_client"; /// <summary> - /// The resource owner or authorization server denied the request. + /// The provided authorization grant (e.g. authorization code, resource owner credentials) or refresh token is invalid, expired, + /// revoked, does not match the redirection URI used in the authorization request, or was issued to another client. /// </summary> - internal const string AccessDenied = "access_denied"; + internal const string InvalidGrant = "invalid_grant"; + + /// <summary> + /// The authenticated client is not authorized to use this authorization grant type. + /// </summary> + internal const string UnauthorizedClient = "unauthorized_client"; /// <summary> - /// The authorization server does not support obtaining an access token using this method. + /// The authorization grant type is not supported by the authorization server. /// </summary> - internal const string UnsupportedGrantType = "unsupported_response_type"; + internal const string UnsupportedGrantType = "unsupported_grant_type"; /// <summary> - /// The requested scope is invalid, unknown, malformed, or exceeds the previously granted scope. + /// The requested scope is invalid, unknown, malformed, or exceeds the scope granted by the resource owner. /// </summary> internal const string InvalidScope = "invalid_scope"; } diff --git a/src/DotNetOpenAuth.OAuth2/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.OAuth2/Properties/AssemblyInfo.cs index 14fb526..26b1318 100644 --- a/src/DotNetOpenAuth.OAuth2/Properties/AssemblyInfo.cs +++ b/src/DotNetOpenAuth.OAuth2/Properties/AssemblyInfo.cs @@ -50,11 +50,13 @@ using System.Web.UI; [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.AuthorizationServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ResourceServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.Client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ClientAuthorization, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] #else [assembly: InternalsVisibleTo("DotNetOpenAuth.Test")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.AuthorizationServer")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ResourceServer")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.Client")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ClientAuthorization")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] #endif diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj index 00c1bb4..a3edcf6 100644 --- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj +++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj @@ -437,6 +437,10 @@ <Project>{ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}</Project> <Name>DotNetOpenAuth.OAuth2.Client.UI</Name> </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.OAuth2.ClientAuthorization\DotNetOpenAuth.OAuth2.ClientAuthorization.csproj"> + <Project>{CCF3728A-B3D7-404A-9BC6-75197135F2D7}</Project> + <Name>DotNetOpenAuth.OAuth2.ClientAuthorization</Name> + </ProjectReference> <ProjectReference Include="..\DotNetOpenAuth.OAuth2.Client\DotNetOpenAuth.OAuth2.Client.csproj"> <Project>{CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}</Project> <Name>DotNetOpenAuth.OAuth2.Client</Name> diff --git a/src/DotNetOpenAuth.Test/OAuth2/AuthorizationServerTests.cs b/src/DotNetOpenAuth.Test/OAuth2/AuthorizationServerTests.cs index f3d8feb..3791e28 100644 --- a/src/DotNetOpenAuth.Test/OAuth2/AuthorizationServerTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth2/AuthorizationServerTests.cs @@ -28,7 +28,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { AuthorizationServerMock, new UserAgentClient(AuthorizationServerDescription), client => { - var request = new AccessTokenAuthorizationCodeRequest(AuthorizationServerDescription) + var request = new AccessTokenAuthorizationCodeRequestC(AuthorizationServerDescription) { ClientIdentifier = ClientId, ClientSecret = ClientSecret, AuthorizationCode = "foo" }; var response = client.Channel.Request<AccessTokenFailedResponse>(request); diff --git a/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs b/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs index bec85e2..b5ee767 100644 --- a/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs @@ -17,18 +17,22 @@ namespace DotNetOpenAuth.Test.OAuth2 { using NUnit.Framework; /// <summary> - /// Verifies that the WRAP message types are recognized. + /// Verifies that the OAuth 2 message types are recognized. /// </summary> public class MessageFactoryTests : OAuth2TestBase { private readonly MessageReceivingEndpoint recipient = new MessageReceivingEndpoint("http://who", HttpDeliveryMethods.PostRequest); - private OAuth2AuthorizationServerChannel channel; - private IMessageFactory messageFactory; + private IMessageFactory authServerMessageFactory; + + private IMessageFactory clientMessageFactory; public override void SetUp() { base.SetUp(); - this.channel = new OAuth2AuthorizationServerChannel(new Mock<IAuthorizationServer>().Object); - this.messageFactory = this.channel.MessageFactoryTestHook; + var authServerChannel = new OAuth2AuthorizationServerChannel(new Mock<IAuthorizationServer>().Object); + this.authServerMessageFactory = authServerChannel.MessageFactoryTestHook; + + var clientChannel = new OAuth2ClientChannel(); + this.clientMessageFactory = clientChannel.MessageFactoryTestHook; } #region End user authorization messages @@ -40,7 +44,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.client_id, "abc" }, { Protocol.redirect_uri, "abc" }, }; - IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); + IDirectedProtocolMessage request = this.authServerMessageFactory.GetNewRequestMessage(this.recipient, fields); Assert.That(request, Is.InstanceOf(typeof(EndUserAuthorizationRequest))); } @@ -51,7 +55,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.client_id, "abc" }, { Protocol.redirect_uri, "abc" }, }; - IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); + IDirectedProtocolMessage request = this.authServerMessageFactory.GetNewRequestMessage(this.recipient, fields); Assert.That(request, Is.InstanceOf(typeof(EndUserAuthorizationImplicitRequest))); } @@ -60,7 +64,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { var fields = new Dictionary<string, string> { { Protocol.code, "abc" }, }; - IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); + IDirectedProtocolMessage request = this.clientMessageFactory.GetNewRequestMessage(this.recipient, fields); Assert.That(request, Is.InstanceOf(typeof(EndUserAuthorizationSuccessResponseBase))); } @@ -70,7 +74,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.access_token, "abc" }, { Protocol.token_type, "bearer" }, }; - IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); + IDirectedProtocolMessage request = this.clientMessageFactory.GetNewRequestMessage(this.recipient, fields); Assert.That(request, Is.InstanceOf(typeof(EndUserAuthorizationSuccessResponseBase))); } @@ -79,7 +83,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { var fields = new Dictionary<string, string> { { Protocol.error, "access-denied" }, }; - IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); + IDirectedProtocolMessage request = this.clientMessageFactory.GetNewRequestMessage(this.recipient, fields); Assert.That(request, Is.InstanceOf(typeof(EndUserAuthorizationFailedResponse))); } @@ -94,7 +98,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.refresh_token, "abc" }, { Protocol.grant_type, "refresh-token" }, }; - IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); + IDirectedProtocolMessage request = this.authServerMessageFactory.GetNewRequestMessage(this.recipient, fields); Assert.That(request, Is.InstanceOf(typeof(AccessTokenRefreshRequest))); } @@ -106,7 +110,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.grant_type, "authorization-code" }, { Protocol.redirect_uri, "http://someUri" }, }; - IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); + IDirectedProtocolMessage request = this.authServerMessageFactory.GetNewRequestMessage(this.recipient, fields); Assert.That(request, Is.InstanceOf(typeof(AccessTokenAuthorizationCodeRequest))); } @@ -119,7 +123,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.username, "abc" }, { Protocol.password, "abc" }, }; - IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); + IDirectedProtocolMessage request = this.authServerMessageFactory.GetNewRequestMessage(this.recipient, fields); Assert.That(request, Is.InstanceOf(typeof(AccessTokenResourceOwnerPasswordCredentialsRequest))); } @@ -130,7 +134,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.client_secret, "abc" }, { Protocol.grant_type, "none" }, }; - IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); + IDirectedProtocolMessage request = this.authServerMessageFactory.GetNewRequestMessage(this.recipient, fields); Assert.That(request, Is.InstanceOf(typeof(AccessTokenClientCredentialsRequest))); } diff --git a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs index 87d91f7..ed6ce70 100644 --- a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs +++ b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs @@ -13,6 +13,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { using DotNetOpenAuth.Messaging.Bindings; using DotNetOpenAuth.OAuth2; using DotNetOpenAuth.OAuth2.ChannelElements; + using DotNetOpenAuth.OAuth2.Messages; using Moq; public class OAuth2TestBase : TestBase { @@ -53,6 +54,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { d.ClientIdentifier == ClientId && d.User == ResourceOwnerUsername && MessagingUtilities.AreEquivalent(d.Scope, TestScopes)))).Returns(true); authHostMock.Setup(m => m.IsResourceOwnerCredentialValid(ResourceOwnerUsername, ResourceOwnerPassword)).Returns(true); + authHostMock.Setup(m => m.GetAccessTokenParameters(It.IsAny<IAccessTokenRequest>())).Returns(new AccessTokenParameters()); return authHostMock; } } diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln index 78928f3..0d29b80 100644 --- a/src/DotNetOpenAuth.sln +++ b/src/DotNetOpenAuth.sln @@ -80,27 +80,6 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "DotNetOpenAuth.TestWeb", "D TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" VWDPort = "5073" EndProjectSection - ProjectSection(WebsiteProperties) = preProject - Debug.AspNetCompiler.Debug = "True" - Debug.AspNetCompiler.FixedNames = "false" - Debug.AspNetCompiler.ForceOverwrite = "true" - Debug.AspNetCompiler.PhysicalPath = "DotNetOpenAuth.TestWeb\" - Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\DotNetOpenAuth.TestWeb\" - Debug.AspNetCompiler.Updateable = "false" - Debug.AspNetCompiler.VirtualPath = "/DotNetOpenAuth.TestWeb" - DefaultWebSiteLanguage = "Visual C#" - ProjectReferences = "{4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}|DotNetOpenAuth.Test.dll;{408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}|DotNetOpenAuth.InfoCard.dll;{60426312-6AE5-4835-8667-37EDEA670222}|DotNetOpenAuth.Core.dll;{A288FCC8-6FCF-46DA-A45E-5F9281556361}|DotNetOpenAuth.OAuth.dll;{3896A32A-E876-4C23-B9B8-78E17D134CD3}|DotNetOpenAuth.OpenId.dll;{56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}|DotNetOpenAuth.OAuth2.dll;{26DC877F-5987-48DD-9DDB-E62F2DE0E150}|Org.Mentalis.Security.Cryptography.dll;{F4CD3C04-6037-4946-B7A5-34BFC96A75D2}|Mono.Math.dll;{173E7B8D-E751-46E2-A133-F72297C0D2F4}|DotNetOpenAuth.Core.UI.dll;{E040EB58-B4D2-457B-A023-AE6EF3BD34DE}|DotNetOpenAuth.InfoCard.UI.dll;{B202E40D-4663-4A2B-ACDA-865F88FF7CAA}|DotNetOpenAuth.OAuth.Consumer.dll;{FED1923A-6D70-49B5-A37A-FB744FEC1C86}|DotNetOpenAuth.OAuth.ServiceProvider.dll;{99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}|DotNetOpenAuth.OAuth2.AuthorizationServer.dll;{CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}|DotNetOpenAuth.OAuth2.Client.dll;{ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}|DotNetOpenAuth.OAuth2.Client.UI.dll;{A1A3150A-7B0E-4A34-8E35-045296CD3C76}|DotNetOpenAuth.OAuth2.ResourceServer.dll;{F8284738-3B5D-4733-A511-38C23F4A763F}|DotNetOpenAuth.OpenId.Provider.dll;{F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}|DotNetOpenAuth.OpenId.RelyingParty.dll;{9D0F8866-2131-4C2A-BC0E-16FEA5B50828}|DotNetOpenAuth.OpenId.Provider.UI.dll;{75E13AAE-7D51-4421-ABFD-3F3DC91F576E}|DotNetOpenAuth.OpenId.UI.dll;{1ED8D424-F8AB-4050-ACEB-F27F4F909484}|DotNetOpenAuth.OpenId.RelyingParty.UI.dll;{115217C5-22CD-415C-A292-0DD0238CDD89}|DotNetOpenAuth.OAuth.Common.dll;" - Release.AspNetCompiler.Debug = "False" - Release.AspNetCompiler.FixedNames = "false" - Release.AspNetCompiler.ForceOverwrite = "true" - Release.AspNetCompiler.PhysicalPath = "DotNetOpenAuth.TestWeb\" - Release.AspNetCompiler.TargetPath = "PrecompiledWeb\DotNetOpenAuth.TestWeb\" - Release.AspNetCompiler.Updateable = "false" - Release.AspNetCompiler.VirtualPath = "/DotNetOpenAuth.TestWeb" - StartServerOnDebug = "false" - TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" - VWDPort = "5073" - EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdProviderWebForms", "..\samples\OpenIdProviderWebForms\OpenIdProviderWebForms.csproj", "{2A59DE0A-B76A-4B42-9A33-04D34548353D}" EndProject @@ -238,6 +217,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.AspNet.Test" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth.Common", "DotNetOpenAuth.OAuth.Common\DotNetOpenAuth.OAuth.Common.csproj", "{115217C5-22CD-415C-A292-0DD0238CDD89}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth2.ClientAuthorization", "DotNetOpenAuth.OAuth2.ClientAuthorization\DotNetOpenAuth.OAuth2.ClientAuthorization.csproj", "{CCF3728A-B3D7-404A-9BC6-75197135F2D7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution CodeAnalysis|Any CPU = CodeAnalysis|Any CPU @@ -470,6 +451,12 @@ Global {CAA2408C-6918-4902-A512-58BCD62216C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {CAA2408C-6918-4902-A512-58BCD62216C3}.Release|Any CPU.ActiveCfg = Release|Any CPU {CAA2408C-6918-4902-A512-58BCD62216C3}.Release|Any CPU.Build.0 = Release|Any CPU + {CCF3728A-B3D7-404A-9BC6-75197135F2D7}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {CCF3728A-B3D7-404A-9BC6-75197135F2D7}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {CCF3728A-B3D7-404A-9BC6-75197135F2D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCF3728A-B3D7-404A-9BC6-75197135F2D7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCF3728A-B3D7-404A-9BC6-75197135F2D7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCF3728A-B3D7-404A-9BC6-75197135F2D7}.Release|Any CPU.Build.0 = Release|Any CPU {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |