summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs14
-rw-r--r--samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs9
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs18
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs26
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenResourceOwnerPasswordCredentialsRequest.cs45
-rw-r--r--src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs1
-rw-r--r--src/DotNetOpenAuth.Test/OAuth2/WebServerClientAuthorizeTests.cs2
7 files changed, 111 insertions, 4 deletions
diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs
index 3f0c48d..8556c55 100644
--- a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs
+++ b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs
@@ -129,6 +129,20 @@ namespace RelyingPartyLogic {
return this.IsAuthorizationValid(authorization.Scope, authorization.ClientIdentifier, authorization.UtcIssued, authorization.User);
}
+ /// <summary>
+ /// Determines whether a given set of resource owner credentials is valid based on the authorization server's user database.
+ /// </summary>
+ /// <param name="userName">Username on the account.</param>
+ /// <param name="password">The user's password.</param>
+ /// <returns>
+ /// <c>true</c> if the given credentials are valid; otherwise, <c>false</c>.
+ /// </returns>
+ /// <exception cref="NotSupportedException">May be thrown if the authorization server does not support the resource owner password credential grant type.</exception>
+ public bool IsResourceOwnerCredentialValid(string userName, string password) {
+ // This web site delegates user authentication to OpenID Providers, and as such no users have local passwords with this server.
+ throw new NotSupportedException();
+ }
+
#endregion
public bool CanBeAutoApproved(EndUserAuthorizationRequest authorizationRequest) {
diff --git a/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs b/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs
index f515949..b837d4c 100644
--- a/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs
+++ b/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs
@@ -80,12 +80,17 @@
return consumerRow;
}
- #endregion
-
public bool IsAuthorizationValid(IAuthorizationDescription authorization) {
return this.IsAuthorizationValid(authorization.Scope, authorization.ClientIdentifier, authorization.UtcIssued, authorization.User);
}
+ public bool IsResourceOwnerCredentialValid(string userName, string password) {
+ // This web site delegates user authentication to OpenID Providers, and as such no users have local passwords with this server.
+ throw new NotSupportedException();
+ }
+
+ #endregion
+
public bool CanBeAutoApproved(EndUserAuthorizationRequest authorizationRequest) {
if (authorizationRequest == null) {
throw new ArgumentNullException("authorizationRequest");
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs
index 6132c98..b0cef58 100644
--- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs
@@ -114,6 +114,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
try {
var authCodeCarrier = message as IAuthorizationCodeCarryingRequest;
var refreshTokenCarrier = message as IRefreshTokenCarryingRequest;
+ var resourceOwnerPasswordCarrier = message as AccessTokenResourceOwnerPasswordCredentialsRequest;
if (authCodeCarrier != null) {
var authorizationCodeFormatter = AuthorizationCode.CreateFormatter(this.AuthorizationServer);
var authorizationCode = authorizationCodeFormatter.Deserialize(message, authCodeCarrier.Code);
@@ -122,6 +123,23 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServer.CryptoKeyStore);
var refreshToken = refreshTokenFormatter.Deserialize(message, refreshTokenCarrier.RefreshToken);
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 {
throw ErrorUtilities.ThrowInternal("Unexpected message type: " + tokenRequest.GetType());
}
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs
index 1732003..8f4745f 100644
--- a/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs
@@ -113,6 +113,17 @@ namespace DotNetOpenAuth.OAuth2 {
/// account or piece of hardware in which the tokens were stored. </para>
/// </remarks>
bool IsAuthorizationValid(IAuthorizationDescription authorization);
+
+ /// <summary>
+ /// Determines whether a given set of resource owner credentials is valid based on the authorization server's user database.
+ /// </summary>
+ /// <param name="userName">Username on the account.</param>
+ /// <param name="password">The user's password.</param>
+ /// <returns>
+ /// <c>true</c> if the given credentials are valid; otherwise, <c>false</c>.
+ /// </returns>
+ /// <exception cref="NotSupportedException">May be thrown if the authorization server does not support the resource owner password credential grant type.</exception>
+ bool IsResourceOwnerCredentialValid(string userName, string password);
}
/// <summary>
@@ -234,5 +245,20 @@ namespace DotNetOpenAuth.OAuth2 {
Requires.NotNull(authorization, "authorization");
throw new NotImplementedException();
}
+
+ /// <summary>
+ /// Determines whether a given set of resource owner credentials is valid based on the authorization server's user database.
+ /// </summary>
+ /// <param name="userName">Username on the account.</param>
+ /// <param name="password">The user's password.</param>
+ /// <returns>
+ /// <c>true</c> if the given credentials are valid; otherwise, <c>false</c>.
+ /// </returns>
+ /// <exception cref="NotSupportedException">May be thrown if the authorization server does not support the resource owner password credential grant type.</exception>
+ bool IAuthorizationServer.IsResourceOwnerCredentialValid(string userName, string password) {
+ Contract.Requires(!String.IsNullOrEmpty(userName));
+ Contract.Requires(password != null);
+ throw new NotImplementedException();
+ }
}
}
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenResourceOwnerPasswordCredentialsRequest.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenResourceOwnerPasswordCredentialsRequest.cs
index a5deb4a..52e65be 100644
--- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenResourceOwnerPasswordCredentialsRequest.cs
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenResourceOwnerPasswordCredentialsRequest.cs
@@ -11,11 +11,12 @@ namespace DotNetOpenAuth.OAuth2.Messages {
using System.Text;
using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuth2.ChannelElements;
/// <summary>
/// A request from a Client to an Authorization Server to exchange the user's username and password for an access token.
/// </summary>
- internal class AccessTokenResourceOwnerPasswordCredentialsRequest : ScopedAccessTokenRequest {
+ internal class AccessTokenResourceOwnerPasswordCredentialsRequest : ScopedAccessTokenRequest, IAuthorizationCarryingRequest, IAuthorizationDescription {
/// <summary>
/// Initializes a new instance of the <see cref="AccessTokenResourceOwnerPasswordCredentialsRequest"/> class.
/// </summary>
@@ -25,6 +26,43 @@ namespace DotNetOpenAuth.OAuth2.Messages {
: base(accessTokenEndpoint, version) {
}
+ #region IAuthorizationCarryingRequest members
+
+ /// <summary>
+ /// Gets the authorization that the code or token describes.
+ /// </summary>
+ IAuthorizationDescription IAuthorizationCarryingRequest.AuthorizationDescription {
+ get { return this.CredentialsValidated ? this : null; }
+ }
+
+ #endregion
+
+ #region IAuthorizationDescription Members
+
+ /// <summary>
+ /// Gets the date this authorization was established or the token was issued.
+ /// </summary>
+ /// <value>A date/time expressed in UTC.</value>
+ DateTime IAuthorizationDescription.UtcIssued {
+ get { return DateTime.UtcNow; }
+ }
+
+ /// <summary>
+ /// Gets the name on the account whose data on the resource server is accessible using this authorization.
+ /// </summary>
+ string IAuthorizationDescription.User {
+ get { return this.UserName; }
+ }
+
+ /// <summary>
+ /// Gets the scope of operations the client is allowed to invoke.
+ /// </summary>
+ HashSet<string> IAuthorizationDescription.Scope {
+ get { return this.Scope; }
+ }
+
+ #endregion
+
/// <summary>
/// Gets the type of the grant.
/// </summary>
@@ -46,5 +84,10 @@ namespace DotNetOpenAuth.OAuth2.Messages {
/// <value>The password.</value>
[MessagePart(Protocol.password, IsRequired = true)]
internal string Password { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the resource owner's credentials have been validated at the authorization server.
+ /// </summary>
+ internal bool CredentialsValidated { get; set; }
}
}
diff --git a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs
index ee35b24..1b5c329 100644
--- a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs
+++ b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs
@@ -43,6 +43,7 @@ namespace DotNetOpenAuth.Test.OAuth2 {
authHostMock.Setup(m => m.GetClient(ClientId)).Returns(ClientDescription);
authHostMock.SetupGet(m => m.CryptoKeyStore).Returns(cryptoStore);
authHostMock.Setup(m => m.IsAuthorizationValid(It.Is<IAuthorizationDescription>(d => d.ClientIdentifier == ClientId && d.User == ResourceOwnerUsername))).Returns(true);
+ authHostMock.Setup(m => m.IsResourceOwnerCredentialValid(ResourceOwnerUsername, ResourceOwnerPassword)).Returns(true);
return authHostMock;
}
}
diff --git a/src/DotNetOpenAuth.Test/OAuth2/WebServerClientAuthorizeTests.cs b/src/DotNetOpenAuth.Test/OAuth2/WebServerClientAuthorizeTests.cs
index faf50bd..1615f97 100644
--- a/src/DotNetOpenAuth.Test/OAuth2/WebServerClientAuthorizeTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth2/WebServerClientAuthorizeTests.cs
@@ -42,7 +42,7 @@ namespace DotNetOpenAuth.Test.OAuth2 {
coordinator.Run();
}
- [TestCase, Ignore("Not yet passing")]
+ [TestCase]
public void ResourceOwnerPasswordCredentialGrant() {
var coordinator = new OAuth2Coordinator<WebServerClient>(
AuthorizationServerDescription,