summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2')
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerUtilities.cs14
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs2
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/AggregatingClientCredentialReader.cs21
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientAuthenticationModule.cs (renamed from src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientAuthenticationModuleBase.cs)11
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientCredentialHttpBasicReader.cs9
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientCredentialMessagePartReader.cs2
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/MessageValidationBindingElement.cs18
7 files changed, 62 insertions, 15 deletions
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerUtilities.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerUtilities.cs
index cd222e2..b8a1071 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerUtilities.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthServerUtilities.cs
@@ -12,6 +12,8 @@ namespace DotNetOpenAuth.OAuth2 {
using System.Linq;
using System.Text;
using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuth2.ChannelElements;
+ using DotNetOpenAuth.OAuth2.Messages;
/// <summary>
/// Utility methods for authorization servers.
@@ -42,13 +44,21 @@ namespace DotNetOpenAuth.OAuth2 {
/// 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="requestMessage">The request message.</param>
/// <param name="error">A single error code from <see cref="Protocol.AccessTokenRequestErrorCodes"/>.</param>
+ /// <param name="authenticationModule">The authentication module from which to glean the WWW-Authenticate header when applicable.</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) {
+ internal static void TokenEndpointVerify(bool condition, AccessTokenRequestBase requestMessage, string error, ClientAuthenticationModule authenticationModule = null, string unformattedDescription = null, params object[] args) {
if (!condition) {
string description = unformattedDescription != null ? string.Format(CultureInfo.CurrentCulture, unformattedDescription, args) : null;
- throw new TokenEndpointProtocolException(error, description);
+
+ string wwwAuthenticateHeader = null;
+ if (authenticationModule != null) {
+ wwwAuthenticateHeader = authenticationModule.AuthenticateHeader;
+ }
+
+ throw new TokenEndpointProtocolException(requestMessage, error, description, authenticateHeader: wwwAuthenticateHeader);
}
}
}
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs
index fecc6be..59b75bf 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs
@@ -148,7 +148,7 @@ namespace DotNetOpenAuth.OAuth2 {
responseMessage = new AccessTokenFailedResponse() { Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest, };
}
} catch (TokenEndpointProtocolException ex) {
- responseMessage = new AccessTokenFailedResponse() { Error = ex.Error, ErrorDescription = ex.Description, ErrorUri = ex.MoreInformation };
+ responseMessage = ex.GetResponse();
} catch (ProtocolException) {
responseMessage = new AccessTokenFailedResponse() {
Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest,
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/AggregatingClientCredentialReader.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/AggregatingClientCredentialReader.cs
index 4f60303..ace95b3 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/AggregatingClientCredentialReader.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/AggregatingClientCredentialReader.cs
@@ -33,6 +33,27 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
}
/// <summary>
+ /// Gets this module's contribution to an HTTP 401 WWW-Authenticate header so the client knows what kind of authentication this module supports.
+ /// </summary>
+ public override string AuthenticateHeader {
+ get {
+ var builder = new StringBuilder();
+ foreach (var authenticator in this.authenticators) {
+ string scheme = authenticator.AuthenticateHeader;
+ if (scheme != null) {
+ if (builder.Length > 0) {
+ builder.Append(", ");
+ }
+
+ builder.Append(scheme);
+ }
+ }
+
+ return builder.Length > 0 ? builder.ToString() : null;
+ }
+ }
+
+ /// <summary>
/// Attempts to extract client identification/authentication information from a message.
/// </summary>
/// <param name="authorizationServerHost">The authorization server host.</param>
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientAuthenticationModuleBase.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientAuthenticationModule.cs
index e835e1e..027929a 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientAuthenticationModuleBase.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientAuthenticationModule.cs
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------
-// <copyright file="ClientAuthenticationModuleBase.cs" company="Andrew Arnott">
+// <copyright file="ClientAuthenticationModule.cs" company="Andrew Arnott">
// Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
@@ -26,6 +26,13 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
}
/// <summary>
+ /// Gets this module's contribution to an HTTP 401 WWW-Authenticate header so the client knows what kind of authentication this module supports.
+ /// </summary>
+ public virtual string AuthenticateHeader {
+ get { return null; }
+ }
+
+ /// <summary>
/// Attempts to extract client identification/authentication information from a message.
/// </summary>
/// <param name="authorizationServerHost">The authorization server host.</param>
@@ -41,7 +48,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
/// <param name="clientIdentifier">The alleged client identifier.</param>
/// <param name="clientSecret">The alleged client secret to be verified.</param>
/// <returns>An indication as to the outcome of the validation.</returns>
- protected static ClientAuthenticationResult TryAuthenticateClient(IAuthorizationServerHost authorizationServerHost, string clientIdentifier, string clientSecret) {
+ protected static ClientAuthenticationResult TryAuthenticateClientBySecret(IAuthorizationServerHost authorizationServerHost, string clientIdentifier, string clientSecret) {
Requires.NotNull(authorizationServerHost, "authorizationServerHost");
if (!string.IsNullOrEmpty(clientIdentifier)) {
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientCredentialHttpBasicReader.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientCredentialHttpBasicReader.cs
index 44af332..655d38f 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientCredentialHttpBasicReader.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientCredentialHttpBasicReader.cs
@@ -18,6 +18,13 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
/// </summary>
public class ClientCredentialHttpBasicReader : ClientAuthenticationModule {
/// <summary>
+ /// Gets this module's contribution to an HTTP 401 WWW-Authenticate header so the client knows what kind of authentication this module supports.
+ /// </summary>
+ public override string AuthenticateHeader {
+ get { return "Basic"; }
+ }
+
+ /// <summary>
/// Attempts to extract client identification/authentication information from a message.
/// </summary>
/// <param name="authorizationServerHost">The authorization server host.</param>
@@ -31,7 +38,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
var credential = OAuthUtilities.ParseHttpBasicAuth(requestMessage.Headers);
if (credential != null) {
clientIdentifier = credential.UserName;
- return TryAuthenticateClient(authorizationServerHost, credential.UserName, credential.Password);
+ return TryAuthenticateClientBySecret(authorizationServerHost, credential.UserName, credential.Password);
}
clientIdentifier = null;
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientCredentialMessagePartReader.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientCredentialMessagePartReader.cs
index 6579df2..2afd06e 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientCredentialMessagePartReader.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/ClientCredentialMessagePartReader.cs
@@ -28,7 +28,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
Requires.NotNull(requestMessage, "requestMessage");
clientIdentifier = requestMessage.ClientIdentifier;
- return TryAuthenticateClient(authorizationServerHost, requestMessage.ClientIdentifier, requestMessage.ClientSecret);
+ return TryAuthenticateClientBySecret(authorizationServerHost, requestMessage.ClientIdentifier, requestMessage.ClientSecret);
}
}
}
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/MessageValidationBindingElement.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/MessageValidationBindingElement.cs
index e114208..ac23e24 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/MessageValidationBindingElement.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ChannelElements/MessageValidationBindingElement.cs
@@ -37,6 +37,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
/// Initializes a new instance of the <see cref="MessageValidationBindingElement"/> class.
/// </summary>
/// <param name="clientAuthenticationModule">The aggregating client authentication module.</param>
+ /// <param name="authorizationServer">The authorization server host.</param>
internal MessageValidationBindingElement(ClientAuthenticationModule clientAuthenticationModule, IAuthorizationServerHost authorizationServer) {
Requires.NotNull(clientAuthenticationModule, "clientAuthenticationModule");
Requires.NotNull(authorizationServer, "authorizationServer");
@@ -101,11 +102,12 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
// Check that the client secret is correct for client authenticated messages.
var clientCredentialOnly = message as AccessTokenClientCredentialsRequest;
var authenticatedClientRequest = message as AuthenticatedClientRequestBase;
+ var accessTokenRequest = authenticatedClientRequest as AccessTokenRequestBase; // currently the only type of message.
if (authenticatedClientRequest != null) {
string clientIdentifier;
var result = this.clientAuthenticationModule.TryAuthenticateClient(this.authorizationServer, authenticatedClientRequest, out clientIdentifier);
- AuthServerUtilities.TokenEndpointVerify(result != ClientAuthenticationResult.ClientIdNotAuthenticated, Protocol.AccessTokenRequestErrorCodes.UnauthorizedClient); // an empty secret is not allowed for client authenticated calls.
- AuthServerUtilities.TokenEndpointVerify(result == ClientAuthenticationResult.ClientAuthenticated, Protocol.AccessTokenRequestErrorCodes.InvalidClient, AuthServerStrings.ClientSecretMismatch);
+ AuthServerUtilities.TokenEndpointVerify(result != ClientAuthenticationResult.ClientIdNotAuthenticated, accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.UnauthorizedClient); // an empty secret is not allowed for client authenticated calls.
+ AuthServerUtilities.TokenEndpointVerify(result == ClientAuthenticationResult.ClientAuthenticated, accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidClient, this.clientAuthenticationModule, AuthServerStrings.ClientSecretMismatch);
authenticatedClientRequest.ClientIdentifier = clientIdentifier;
if (clientCredentialOnly != null) {
@@ -128,12 +130,12 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
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);
+ throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidGrant, AuthServerStrings.InvalidResourceOwnerPasswordCredential);
}
} catch (NotSupportedException) {
- throw new TokenEndpointProtocolException(Protocol.AccessTokenRequestErrorCodes.UnsupportedGrantType);
+ throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.UnsupportedGrantType);
} catch (NotImplementedException) {
- throw new TokenEndpointProtocolException(Protocol.AccessTokenRequestErrorCodes.UnsupportedGrantType);
+ throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.UnsupportedGrantType);
}
}
@@ -159,14 +161,14 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
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);
+ AuthServerUtilities.TokenEndpointVerify(string.Equals(accessRequest.ClientIdentifier, authCarrier.AuthorizationDescription.ClientIdentifier, StringComparison.Ordinal), accessTokenRequest, 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);
+ throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidScope, AuthServerStrings.AccessScopeExceedsGrantScope);
}
}
}
@@ -174,7 +176,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
// 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 IAuthorizationServerHost.IsAuthorizationValid method returned false.");
- throw new TokenEndpointProtocolException(Protocol.AccessTokenRequestErrorCodes.InvalidGrant);
+ throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidGrant);
}
applied = true;