summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.Core/Messaging/DataBag.cs2
-rw-r--r--src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs13
-rw-r--r--src/DotNetOpenAuth.Core/Messaging/IDataBagFormatter.cs15
-rw-r--r--src/DotNetOpenAuth.Core/Messaging/UriStyleMessageFormatter.cs2
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/DotNetOpenAuth.OAuth2.AuthorizationServer.csproj1
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs45
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServerAccessToken.cs52
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/TokenCodeSerializationBindingElement.cs11
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/IAuthorizationServerHost.cs11
-rw-r--r--src/DotNetOpenAuth.OAuth2.ClientAuthorization/DotNetOpenAuth.OAuth2.ClientAuthorization.csproj2
-rw-r--r--src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/AccessTokenParameters.cs102
-rw-r--r--src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenRequestBase.cs28
-rw-r--r--src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenResult.cs43
-rw-r--r--src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationImplicitRequest.cs7
-rw-r--r--src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenRequestInternal.cs7
-rw-r--r--src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/StandardAccessTokenAnalyzer.cs3
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/AccessToken.cs69
-rw-r--r--src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/ProviderAssociationHandleEncoder.cs4
-rw-r--r--src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs2
19 files changed, 201 insertions, 218 deletions
diff --git a/src/DotNetOpenAuth.Core/Messaging/DataBag.cs b/src/DotNetOpenAuth.Core/Messaging/DataBag.cs
index f09bcea..0800840 100644
--- a/src/DotNetOpenAuth.Core/Messaging/DataBag.cs
+++ b/src/DotNetOpenAuth.Core/Messaging/DataBag.cs
@@ -105,7 +105,7 @@ namespace DotNetOpenAuth.Messaging {
/// </remarks>
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Accessed by reflection")]
[MessagePart("t", IsRequired = true, AllowEmpty = false)]
- private Type BagType {
+ protected virtual Type BagType {
get { return this.GetType(); }
}
diff --git a/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs b/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs
index 746efb1..c9ceb81 100644
--- a/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs
+++ b/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs
@@ -22,7 +22,7 @@ namespace DotNetOpenAuth.Messaging {
/// A serializer for <see cref="DataBag"/>-derived types
/// </summary>
/// <typeparam name="T">The DataBag-derived type that is to be serialized/deserialized.</typeparam>
- internal abstract class DataBagFormatterBase<T> : IDataBagFormatter<T> where T : DataBag, new() {
+ internal abstract class DataBagFormatterBase<T> : IDataBagFormatter<T> where T : DataBag {
/// <summary>
/// The message description cache to use for data bag types.
/// </summary>
@@ -192,14 +192,13 @@ namespace DotNetOpenAuth.Messaging {
/// <summary>
/// Deserializes a <see cref="DataBag"/>, including decompression, decryption, signature and nonce validation where applicable.
/// </summary>
+ /// <param name="message">The instance to initialize with deserialized data.</param>
/// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be null.</param>
/// <param name="value">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param>
/// <param name="messagePartName">The name of the parameter whose value is to be deserialized. Used for error message generation.</param>
- /// <returns>
- /// The deserialized value. Never null.
- /// </returns>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "No apparent problem. False positive?")]
- public T Deserialize(IProtocolMessage containingMessage, string value, string messagePartName) {
+ public void Deserialize(T message, IProtocolMessage containingMessage, string value, string messagePartName) {
+ Requires.NotNull(message, "message");
Requires.NotNull(containingMessage, "containingMessage");
Requires.NotNullOrEmpty(value, "value");
Requires.NotNullOrEmpty(messagePartName, "messagePartName");
@@ -211,7 +210,7 @@ namespace DotNetOpenAuth.Messaging {
value = valueWithoutHandle;
}
- var message = new T { ContainingMessage = containingMessage };
+ message.ContainingMessage = containingMessage;
byte[] data = MessagingUtilities.FromBase64WebSafeString(value);
byte[] signature = null;
@@ -256,8 +255,6 @@ namespace DotNetOpenAuth.Messaging {
}
((IMessage)message).EnsureValidMessage();
-
- return message;
}
/// <summary>
diff --git a/src/DotNetOpenAuth.Core/Messaging/IDataBagFormatter.cs b/src/DotNetOpenAuth.Core/Messaging/IDataBagFormatter.cs
index 9086ee9..923773e 100644
--- a/src/DotNetOpenAuth.Core/Messaging/IDataBagFormatter.cs
+++ b/src/DotNetOpenAuth.Core/Messaging/IDataBagFormatter.cs
@@ -13,7 +13,7 @@ namespace DotNetOpenAuth.Messaging {
/// </summary>
/// <typeparam name="T">The DataBag-derived type that is to be serialized/deserialized.</typeparam>
[ContractClass(typeof(IDataBagFormatterContract<>))]
- internal interface IDataBagFormatter<T> where T : DataBag, new() {
+ internal interface IDataBagFormatter<in T> where T : DataBag {
/// <summary>
/// Serializes the specified message.
/// </summary>
@@ -24,13 +24,11 @@ namespace DotNetOpenAuth.Messaging {
/// <summary>
/// Deserializes a <see cref="DataBag"/>.
/// </summary>
+ /// <param name="message">The instance to deserialize into</param>
/// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be null.</param>
/// <param name="data">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param>
/// <param name="messagePartName">The name of the parameter whose value is to be deserialized. Used for error message generation.</param>
- /// <returns>
- /// The deserialized value. Never null.
- /// </returns>
- T Deserialize(IProtocolMessage containingMessage, string data, string messagePartName);
+ void Deserialize(T message, IProtocolMessage containingMessage, string data, string messagePartName);
}
/// <summary>
@@ -62,13 +60,12 @@ namespace DotNetOpenAuth.Messaging {
/// <summary>
/// Deserializes a <see cref="DataBag"/>.
/// </summary>
+ /// <param name="message">The instance to deserialize into</param>
/// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be nulll.</param>
/// <param name="data">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param>
/// <param name="messagePartName">Name of the message part whose value is to be deserialized. Used for exception messages.</param>
- /// <returns>
- /// The deserialized value. Never null.
- /// </returns>
- T IDataBagFormatter<T>.Deserialize(IProtocolMessage containingMessage, string data, string messagePartName) {
+ void IDataBagFormatter<T>.Deserialize(T message, IProtocolMessage containingMessage, string data, string messagePartName) {
+ Requires.NotNull(message, "message");
Requires.NotNull(containingMessage, "containingMessage");
Requires.NotNullOrEmpty(data, "data");
Requires.NotNullOrEmpty(messagePartName, "messagePartName");
diff --git a/src/DotNetOpenAuth.Core/Messaging/UriStyleMessageFormatter.cs b/src/DotNetOpenAuth.Core/Messaging/UriStyleMessageFormatter.cs
index 92b1928..242175e 100644
--- a/src/DotNetOpenAuth.Core/Messaging/UriStyleMessageFormatter.cs
+++ b/src/DotNetOpenAuth.Core/Messaging/UriStyleMessageFormatter.cs
@@ -20,7 +20,7 @@ namespace DotNetOpenAuth.Messaging {
/// A serializer for <see cref="DataBag"/>-derived types
/// </summary>
/// <typeparam name="T">The DataBag-derived type that is to be serialized/deserialized.</typeparam>
- internal class UriStyleMessageFormatter<T> : DataBagFormatterBase<T> where T : DataBag, new() {
+ internal class UriStyleMessageFormatter<T> : DataBagFormatterBase<T> where T : DataBag {
/// <summary>
/// Initializes a new instance of the <see cref="UriStyleMessageFormatter&lt;T&gt;"/> class.
/// </summary>
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/DotNetOpenAuth.OAuth2.AuthorizationServer.csproj b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/DotNetOpenAuth.OAuth2.AuthorizationServer.csproj
index 11b1cb2..34d59ee 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/DotNetOpenAuth.OAuth2.AuthorizationServer.csproj
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/DotNetOpenAuth.OAuth2.AuthorizationServer.csproj
@@ -20,6 +20,7 @@
<ItemGroup>
<Compile Include="Configuration\OAuth2AuthorizationServerSection.cs" />
<Compile Include="OAuth2\AuthorizationServer.cs" />
+ <Compile Include="OAuth2\AuthorizationServerAccessToken.cs" />
<Compile Include="OAuth2\AuthServerStrings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs
index ab20971..6a96c2d 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs
@@ -143,30 +143,30 @@ namespace DotNetOpenAuth.OAuth2 {
IProtocolMessage responseMessage;
try {
if (this.Channel.TryReadFromRequest(request, out requestMessage)) {
+ var accessTokenResult = this.AuthorizationServerServices.CreateAccessToken(requestMessage);
+ ErrorUtilities.VerifyHost(accessTokenResult != null, "IAuthorizationServerHost.CreateAccessToken must not return null.");
+
IAccessTokenRequestInternal accessRequestInternal = requestMessage;
- accessRequestInternal.AccessTokenCreationParameters = this.AuthorizationServerServices.GetAccessTokenParameters(requestMessage);
- ErrorUtilities.VerifyHost(accessRequestInternal.AccessTokenCreationParameters != null, "IAuthorizationServerHost.GetAccessTokenParameters must not return null.");
+ accessRequestInternal.AccessTokenResult = accessTokenResult;
- var successResponseMessage = this.PrepareAccessTokenResponse(requestMessage, accessRequestInternal.AccessTokenCreationParameters.IncludeRefreshToken);
- successResponseMessage.Lifetime = accessRequestInternal.AccessTokenCreationParameters.AccessTokenLifetime;
+ var successResponseMessage = this.PrepareAccessTokenResponse(requestMessage, accessTokenResult.AllowRefreshToken);
+ successResponseMessage.Lifetime = accessTokenResult.AccessToken.Lifetime;
var authCarryingRequest = requestMessage as IAuthorizationCarryingRequest;
if (authCarryingRequest != null) {
+ accessTokenResult.AccessToken.ApplyAuthorization(authCarryingRequest.AuthorizationDescription);
IAccessTokenIssuingResponse accessTokenIssuingResponse = successResponseMessage;
- accessTokenIssuingResponse.AuthorizationDescription = new AccessToken(authCarryingRequest.AuthorizationDescription, successResponseMessage.Lifetime);
- accessTokenIssuingResponse.AuthorizationDescription.ExtraData.AddRange(accessRequestInternal.AccessTokenCreationParameters.ExtraClaims);
+ accessTokenIssuingResponse.AuthorizationDescription = accessTokenResult.AccessToken;
}
responseMessage = successResponseMessage;
} else {
- responseMessage = new AccessTokenFailedResponse() { Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest, };
+ responseMessage = new AccessTokenFailedResponse() { Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest };
}
} catch (TokenEndpointProtocolException ex) {
responseMessage = ex.GetResponse();
} catch (ProtocolException) {
- responseMessage = new AccessTokenFailedResponse() {
- Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest,
- };
+ responseMessage = new AccessTokenFailedResponse() { Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest };
}
return this.Channel.PrepareResponse(responseMessage);
@@ -212,16 +212,17 @@ namespace DotNetOpenAuth.OAuth2 {
switch (authorizationRequest.ResponseType) {
case EndUserAuthorizationResponseType.AccessToken:
IAccessTokenRequestInternal accessRequestInternal = (EndUserAuthorizationImplicitRequest)authorizationRequest;
- accessRequestInternal.AccessTokenCreationParameters = this.AuthorizationServerServices.GetAccessTokenParameters(accessRequestInternal);
+ var accessTokenResult = this.AuthorizationServerServices.CreateAccessToken(accessRequestInternal);
+ ErrorUtilities.VerifyHost(accessTokenResult != null, "IAuthorizationServerHost.CreateAccessToken must not return null.");
+
+ accessRequestInternal.AccessTokenResult = accessTokenResult;
var implicitGrantResponse = new EndUserAuthorizationSuccessAccessTokenResponse(callback, authorizationRequest);
- implicitGrantResponse.Lifetime = accessRequestInternal.AccessTokenCreationParameters.AccessTokenLifetime;
+ implicitGrantResponse.Lifetime = accessTokenResult.AccessToken.Lifetime;
+ accessTokenResult.AccessToken.ApplyAuthorization(implicitGrantResponse.Scope, userName, implicitGrantResponse.Lifetime);
+
IAccessTokenCarryingRequest tokenCarryingResponse = implicitGrantResponse;
- tokenCarryingResponse.AuthorizationDescription = new AccessToken(
- implicitGrantResponse.Scope,
- userName,
- implicitGrantResponse.Lifetime);
- tokenCarryingResponse.AuthorizationDescription.ExtraData.AddRange(accessRequestInternal.AccessTokenCreationParameters.ExtraClaims);
+ tokenCarryingResponse.AuthorizationDescription = accessTokenResult.AccessToken;
response = implicitGrantResponse;
break;
@@ -279,24 +280,24 @@ namespace DotNetOpenAuth.OAuth2 {
/// Prepares the response to an access token request.
/// </summary>
/// <param name="request">The request for an access token.</param>
- /// <param name="includeRefreshToken">If set to <c>true</c>, the response will include a long-lived refresh token.</param>
+ /// <param name="allowRefreshToken">If set to <c>true</c>, the response will include a long-lived refresh token.</param>
/// <returns>The response message to send to the client.</returns>
- private AccessTokenSuccessResponse PrepareAccessTokenResponse(AccessTokenRequestBase request, bool includeRefreshToken = true) {
+ private AccessTokenSuccessResponse PrepareAccessTokenResponse(AccessTokenRequestBase request, bool allowRefreshToken = true) {
Requires.NotNull(request, "request");
- if (includeRefreshToken) {
+ if (allowRefreshToken) {
if (request is AccessTokenClientCredentialsRequest) {
// Per OAuth 2.0 section 4.4.3 (draft 23), refresh tokens should never be included
// in a response to an access token request that used the client credential grant type.
Logger.OAuth.Debug("Suppressing refresh token in access token response because the grant type used by the client disallows it.");
- includeRefreshToken = false;
+ allowRefreshToken = false;
}
}
var tokenRequest = (IAuthorizationCarryingRequest)request;
var accessTokenRequest = (IAccessTokenRequestInternal)request;
var response = new AccessTokenSuccessResponse(request) {
- HasRefreshToken = includeRefreshToken,
+ HasRefreshToken = allowRefreshToken,
};
response.Scope.ResetContents(tokenRequest.AuthorizationDescription.Scope);
return response;
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServerAccessToken.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServerAccessToken.cs
new file mode 100644
index 0000000..c577a0a
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServerAccessToken.cs
@@ -0,0 +1,52 @@
+//-----------------------------------------------------------------------
+// <copyright file="AuthorizationServerAccessToken.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth2 {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Linq;
+ using System.Security.Cryptography;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuth2.ChannelElements;
+
+ /// <summary>
+ /// An access token minted by the authorization server that can be serialized for transmission to the client.
+ /// </summary>
+ public class AuthorizationServerAccessToken : AccessToken {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AuthorizationServerAccessToken"/> class.
+ /// </summary>
+ public AuthorizationServerAccessToken() {
+ }
+
+ /// <summary>
+ /// Gets or sets the crypto service provider with the asymmetric private key to use for signing access tokens.
+ /// </summary>
+ /// <returns>A crypto service provider instance that contains the private key.</returns>
+ /// <value>Must not be null, and must contain the private key.</value>
+ /// <remarks>
+ /// The public key in the private/public key pair will be used by the resource
+ /// servers to validate that the access token is minted by a trusted authorization server.
+ /// </remarks>
+ public RSACryptoServiceProvider AccessTokenSigningKey { get; set; }
+
+ /// <summary>
+ /// Gets or sets the key to encrypt the access token.
+ /// </summary>
+ public RSACryptoServiceProvider ResourceServerEncryptionKey { get; set; }
+
+ /// <summary>
+ /// Serializes this instance to a simple string for transmission to the client.
+ /// </summary>
+ /// <returns>A non-empty string.</returns>
+ protected internal override string Serialize() {
+ var formatter = CreateFormatter(this.AccessTokenSigningKey, this.ResourceServerEncryptionKey);
+ return formatter.Serialize(this);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/TokenCodeSerializationBindingElement.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/TokenCodeSerializationBindingElement.cs
index 41bc609..494a10b 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/TokenCodeSerializationBindingElement.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/TokenCodeSerializationBindingElement.cs
@@ -71,10 +71,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
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(
- request.AccessTokenCreationParameters.AccessTokenSigningKey,
- request.AccessTokenCreationParameters.ResourceServerEncryptionKey);
- accessTokenResponse.AccessToken = accessTokenFormatter.Serialize(accessTokenResponse.AuthorizationDescription);
+ accessTokenResponse.AccessToken = accessTokenResponse.AuthorizationDescription.Serialize();
}
return null;
@@ -105,14 +102,16 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
var authCodeCarrier = message as IAuthorizationCodeCarryingRequest;
if (authCodeCarrier != null) {
var authorizationCodeFormatter = AuthorizationCode.CreateFormatter(this.AuthorizationServer);
- var authorizationCode = authorizationCodeFormatter.Deserialize(message, authCodeCarrier.Code, Protocol.code);
+ var authorizationCode = new AuthorizationCode();
+ authorizationCodeFormatter.Deserialize(authorizationCode, 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);
+ var refreshToken = new RefreshToken();
+ refreshTokenFormatter.Deserialize(refreshToken, message, refreshTokenCarrier.RefreshToken, Protocol.refresh_token);
refreshTokenCarrier.AuthorizationDescription = refreshToken;
}
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/IAuthorizationServerHost.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/IAuthorizationServerHost.cs
index c31ec81..4c25c16 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/IAuthorizationServerHost.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/IAuthorizationServerHost.cs
@@ -38,14 +38,15 @@ namespace DotNetOpenAuth.OAuth2 {
INonceStore NonceStore { get; }
/// <summary>
- /// Obtains parameters to go into the formulation of an access token.
+ /// Acquires the access token and related parameters that go into the formulation of the token endpoint's response to a client.
/// </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>
+ /// 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);
+ AccessTokenResult CreateAccessToken(IAccessTokenRequest accessTokenRequestMessage);
/// <summary>
/// Gets the client with a given identifier.
@@ -205,9 +206,9 @@ namespace DotNetOpenAuth.OAuth2 {
/// <returns>
/// A non-null parameters instance that DotNetOpenAuth will dispose after it has been used.
/// </returns>
- AccessTokenParameters IAuthorizationServerHost.GetAccessTokenParameters(IAccessTokenRequest accessTokenRequestMessage) {
+ AccessTokenResult IAuthorizationServerHost.CreateAccessToken(IAccessTokenRequest accessTokenRequestMessage) {
Contract.Requires(accessTokenRequestMessage != null);
- Contract.Ensures(Contract.Result<AccessTokenParameters>() != null);
+ Contract.Ensures(Contract.Result<AccessTokenResult>() != null);
throw new NotImplementedException();
}
}
diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/DotNetOpenAuth.OAuth2.ClientAuthorization.csproj b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/DotNetOpenAuth.OAuth2.ClientAuthorization.csproj
index 3fe6e27..4a0e344 100644
--- a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/DotNetOpenAuth.OAuth2.ClientAuthorization.csproj
+++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/DotNetOpenAuth.OAuth2.ClientAuthorization.csproj
@@ -18,7 +18,6 @@
<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" />
@@ -35,6 +34,7 @@
<Compile Include="OAuth2\Messages\AccessTokenRefreshRequest.cs" />
<Compile Include="OAuth2\Messages\AccessTokenRequestBase.cs" />
<Compile Include="OAuth2\Messages\AccessTokenResourceOwnerPasswordCredentialsRequest.cs" />
+ <Compile Include="OAuth2\Messages\AccessTokenResult.cs" />
<Compile Include="OAuth2\Messages\AccessTokenSuccessResponse.cs" />
<Compile Include="OAuth2\Messages\AuthenticatedClientRequestBase.cs" />
<Compile Include="OAuth2\Messages\EndUserAuthorizationFailedResponse.cs" />
diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/AccessTokenParameters.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/AccessTokenParameters.cs
deleted file mode 100644
index 8f383cd..0000000
--- a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/AccessTokenParameters.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-//-----------------------------------------------------------------------
-// <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);
- this.ExtraClaims = new Dictionary<string, string>();
- }
-
- /// <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 crypto service provider with the asymmetric private key to use for signing access tokens.
- /// </summary>
- /// <returns>A crypto service provider instance that contains the private key.</returns>
- /// <value>Must not be null, and must contain the private key.</value>
- /// <remarks>
- /// The public key in the private/public key pair will be used by the resource
- /// servers to validate that the access token is minted by a trusted authorization server.
- /// </remarks>
- public RSACryptoServiceProvider AccessTokenSigningKey { 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; }
-
- /// <summary>
- /// Gets or sets a dictionary of additional claims to include in the <see cref="AccessToken"/>.
- /// </summary>
- public IDictionary<string, string> ExtraClaims { 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();
- }
-
- if (this.AccessTokenSigningKey != null) {
- IDisposable value = this.AccessTokenSigningKey;
- value.Dispose();
- }
- }
- }
-
- #endregion
- }
-}
diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenRequestBase.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenRequestBase.cs
index c2ab347..e6bbc34 100644
--- a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/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, IAccessTokenRequestInternal, IDisposable {
+ public abstract class AccessTokenRequestBase : AuthenticatedClientRequestBase, IAccessTokenRequestInternal {
/// <summary>
/// Initializes a new instance of the <see cref="AccessTokenRequestBase"/> class.
/// </summary>
@@ -43,12 +43,9 @@ namespace DotNetOpenAuth.OAuth2.Messages {
public bool ClientAuthenticated { get; internal set; }
/// <summary>
- /// Gets or sets the access token creation parameters.
+ /// Gets or sets the result of calling the authorization server host's access token creation method.
/// </summary>
- /// <remarks>
- /// This property's value is set by a binding element in the OAuth 2 channel.
- /// </remarks>
- AccessTokenParameters IAccessTokenRequestInternal.AccessTokenCreationParameters { get; set; }
+ AccessTokenResult IAccessTokenRequestInternal.AccessTokenResult { get; set; }
/// <summary>
/// Gets the type of the grant.
@@ -63,25 +60,6 @@ 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.ClientAuthorization/OAuth2/Messages/AccessTokenResult.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenResult.cs
new file mode 100644
index 0000000..11e486b
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/AccessTokenResult.cs
@@ -0,0 +1,43 @@
+//-----------------------------------------------------------------------
+// <copyright file="AccessTokenResult.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 AccessTokenResult {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AccessTokenResult"/> class.
+ /// </summary>
+ /// <param name="accessToken">The access token to include in this result.</param>
+ public AccessTokenResult(AccessToken accessToken) {
+ Requires.NotNull(accessToken, "accessToken");
+ this.AllowRefreshToken = true;
+ this.AccessToken = accessToken;
+ }
+
+ /// <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 AllowRefreshToken { get; set; }
+
+ /// <summary>
+ /// Gets the access token.
+ /// </summary>
+ public AccessToken AccessToken { get; private set; }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationImplicitRequest.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationImplicitRequest.cs
index 661e2ae..4b662cd 100644
--- a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationImplicitRequest.cs
+++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/EndUserAuthorizationImplicitRequest.cs
@@ -43,12 +43,9 @@ namespace DotNetOpenAuth.OAuth2.Messages {
}
/// <summary>
- /// Gets or sets the access token creation parameters.
+ /// Gets or sets the result of calling the authorization server host's access token creation method.
/// </summary>
- /// <remarks>
- /// This property's value is set by a binding element in the OAuth 2 channel.
- /// </remarks>
- AccessTokenParameters IAccessTokenRequestInternal.AccessTokenCreationParameters { get; set; }
+ AccessTokenResult IAccessTokenRequestInternal.AccessTokenResult { get; set; }
/// <summary>
/// Gets a value indicating whether the client requesting the access token has authenticated itself.
diff --git a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenRequestInternal.cs b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenRequestInternal.cs
index e218462..44af074 100644
--- a/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenRequestInternal.cs
+++ b/src/DotNetOpenAuth.OAuth2.ClientAuthorization/OAuth2/Messages/IAccessTokenRequestInternal.cs
@@ -15,11 +15,8 @@ namespace DotNetOpenAuth.OAuth2.Messages {
/// </summary>
public interface IAccessTokenRequestInternal : IAccessTokenRequest {
/// <summary>
- /// Gets or sets the access token creation parameters.
+ /// Gets or sets the result of calling the authorization server host's access token creation method.
/// </summary>
- /// <remarks>
- /// This property's value is set by a binding element in the OAuth 2 channel.
- /// </remarks>
- AccessTokenParameters AccessTokenCreationParameters { get; set; }
+ AccessTokenResult AccessTokenResult { get; set; }
}
}
diff --git a/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/StandardAccessTokenAnalyzer.cs b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/StandardAccessTokenAnalyzer.cs
index 992e93c..54d86ff 100644
--- a/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/StandardAccessTokenAnalyzer.cs
+++ b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/StandardAccessTokenAnalyzer.cs
@@ -50,7 +50,8 @@ namespace DotNetOpenAuth.OAuth2 {
/// <exception cref="ProtocolException">Thrown if the access token is expired, invalid, or from an untrusted authorization server.</exception>
public virtual AccessToken DeserializeAccessToken(IDirectedProtocolMessage message, string accessToken) {
var accessTokenFormatter = AccessToken.CreateFormatter(this.AuthorizationServerPublicSigningKey, this.ResourceServerPrivateEncryptionKey);
- var token = accessTokenFormatter.Deserialize(message, accessToken, Protocol.access_token);
+ var token = new AccessToken();
+ accessTokenFormatter.Deserialize(token, message, accessToken, Protocol.access_token);
return token;
}
}
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/AccessToken.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/AccessToken.cs
index 3a12faa..5890d93 100644
--- a/src/DotNetOpenAuth.OAuth2/OAuth2/AccessToken.cs
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/AccessToken.cs
@@ -24,22 +24,55 @@ namespace DotNetOpenAuth.OAuth2 {
}
/// <summary>
- /// Initializes a new instance of the <see cref="AccessToken"/> class.
+ /// Gets or sets the lifetime of the access token.
+ /// </summary>
+ /// <value>The lifetime.</value>
+ [MessagePart(Encoder = typeof(TimespanSecondsEncoder))]
+ public TimeSpan? Lifetime { get; set; }
+
+ /// <summary>
+ /// Gets the type of this instance.
+ /// </summary>
+ /// <value>The type of the bag.</value>
+ /// <remarks>
+ /// This ensures that one token cannot be misused as another kind of token.
+ /// </remarks>
+ protected override Type BagType {
+ get {
+ // different roles (authorization server vs. Client) may derive from AccessToken, but they are all interoperable.
+ return typeof(AccessToken);
+ }
+ }
+
+ /// <summary>
+ /// Creates a formatter capable of serializing/deserializing an access token.
+ /// </summary>
+ /// <param name="signingKey">The crypto service provider with the authorization server's private key used to asymmetrically sign the access token.</param>
+ /// <param name="encryptingKey">The crypto service provider with the resource server's public key used to encrypt the access token.</param>
+ /// <returns>An access token serializer.</returns>
+ internal static IDataBagFormatter<AccessToken> CreateFormatter(RSACryptoServiceProvider signingKey, RSACryptoServiceProvider encryptingKey) {
+ Contract.Requires(signingKey != null || !signingKey.PublicOnly);
+ Contract.Requires(encryptingKey != null);
+ Contract.Ensures(Contract.Result<IDataBagFormatter<AccessToken>>() != null);
+
+ return new UriStyleMessageFormatter<AccessToken>(signingKey, encryptingKey);
+ }
+
+ /// <summary>
+ /// Initializes this instance of the <see cref="AccessToken"/> class.
/// </summary>
- /// <param name="authorization">The authorization to be described by the access token.</param>
- /// <param name="lifetime">The lifetime of the access token.</param>
- internal AccessToken(IAuthorizationDescription authorization, TimeSpan? lifetime) {
+ /// <param name="authorization">The authorization to apply to this access token.</param>
+ internal void ApplyAuthorization(IAuthorizationDescription authorization) {
Requires.NotNull(authorization, "authorization");
this.ClientIdentifier = authorization.ClientIdentifier;
this.UtcCreationDate = authorization.UtcIssued;
this.User = authorization.User;
this.Scope.ResetContents(authorization.Scope);
- this.Lifetime = lifetime;
}
/// <summary>
- /// Initializes a new instance of the <see cref="AccessToken"/> class.
+ /// Initializes this instance of the <see cref="AccessToken"/> class.
/// </summary>
/// <param name="scopes">The scopes.</param>
/// <param name="username">The username of the account that authorized this token.</param>
@@ -49,7 +82,7 @@ namespace DotNetOpenAuth.OAuth2 {
/// is invoked in the case where the client is <em>not</em> authenticated, and therefore no
/// trust in the client_id is appropriate.
/// </remarks>
- internal AccessToken(IEnumerable<string> scopes, string username, TimeSpan? lifetime) {
+ internal void ApplyAuthorization(IEnumerable<string> scopes, string username, TimeSpan? lifetime) {
this.Scope.ResetContents(scopes);
this.User = username;
this.Lifetime = lifetime;
@@ -57,24 +90,12 @@ namespace DotNetOpenAuth.OAuth2 {
}
/// <summary>
- /// Gets or sets the lifetime of the access token.
- /// </summary>
- /// <value>The lifetime.</value>
- [MessagePart(Encoder = typeof(TimespanSecondsEncoder))]
- public TimeSpan? Lifetime { get; set; }
-
- /// <summary>
- /// Creates a formatter capable of serializing/deserializing an access token.
+ /// Serializes this instance to a simple string for transmission to the client.
/// </summary>
- /// <param name="signingKey">The crypto service provider with the authorization server's private key used to asymmetrically sign the access token.</param>
- /// <param name="encryptingKey">The crypto service provider with the resource server's public key used to encrypt the access token.</param>
- /// <returns>An access token serializer.</returns>
- internal static IDataBagFormatter<AccessToken> CreateFormatter(RSACryptoServiceProvider signingKey, RSACryptoServiceProvider encryptingKey) {
- Contract.Requires(signingKey != null || !signingKey.PublicOnly);
- Contract.Requires(encryptingKey != null);
- Contract.Ensures(Contract.Result<IDataBagFormatter<AccessToken>>() != null);
-
- return new UriStyleMessageFormatter<AccessToken>(signingKey, encryptingKey);
+ /// <returns>A non-empty string.</returns>
+ protected internal virtual string Serialize() {
+ Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>()));
+ throw new NotSupportedException();
}
/// <summary>
diff --git a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/ProviderAssociationHandleEncoder.cs b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/ProviderAssociationHandleEncoder.cs
index 594803d..5c39c5e 100644
--- a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/ProviderAssociationHandleEncoder.cs
+++ b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/ProviderAssociationHandleEncoder.cs
@@ -68,9 +68,9 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// <exception cref="ProtocolException">Thrown if the association is not of the expected type.</exception>
public Association Deserialize(IProtocolMessage containingMessage, bool privateAssociation, string handle) {
var formatter = AssociationDataBag.CreateFormatter(this.cryptoKeyStore, AssociationHandleEncodingSecretBucket);
- AssociationDataBag bag;
+ AssociationDataBag bag = new AssociationDataBag();
try {
- bag = formatter.Deserialize(containingMessage, handle, Protocol.Default.openid.assoc_handle);
+ formatter.Deserialize(bag, containingMessage, handle, Protocol.Default.openid.assoc_handle);
} catch (ProtocolException ex) {
Logger.OpenId.Error("Rejecting an association because deserialization of the encoded handle failed.", ex);
return null;
diff --git a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs
index e6fd81e..41bfaa0 100644
--- a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs
+++ b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs
@@ -55,7 +55,7 @@ namespace DotNetOpenAuth.Test.OAuth2 {
MessagingUtilities.AreEquivalent(d.Scope, TestScopes)))).Returns(true);
string canonicalUserName = ResourceOwnerUsername;
authHostMock.Setup(m => m.IsResourceOwnerCredentialValid(ResourceOwnerUsername, ResourceOwnerPassword, It.IsAny<IAccessTokenRequest>(), out canonicalUserName)).Returns(true);
- authHostMock.Setup(m => m.GetAccessTokenParameters(It.IsAny<IAccessTokenRequest>())).Returns(new AccessTokenParameters());
+ authHostMock.Setup(m => m.CreateAccessToken(It.IsAny<IAccessTokenRequest>())).Returns(new AccessTokenResult(new AuthorizationServerAccessToken()));
return authHostMock;
}
}