Skip to content
This repository was archived by the owner on Mar 20, 2019. It is now read-only.

Commit 85b43c8

Browse files
committed
Access token endpoint now can respond with appropriate errors.
1 parent f4f3295 commit 85b43c8

10 files changed

Lines changed: 85 additions & 83 deletions

File tree

projecttemplates/MvcRelyingParty/OAuthTokenEndpoint.ashx.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,7 @@ public bool IsReusable {
4040
/// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
4141
public void ProcessRequest(HttpContext context) {
4242
var serviceProvider = OAuthServiceProvider.AuthorizationServer;
43-
IDirectResponseProtocolMessage response;
44-
if (serviceProvider.TryPrepareAccessTokenResponse(new HttpRequestWrapper(context.Request), out response)) {
45-
serviceProvider.Channel.Respond(response);
46-
} else {
47-
throw new InvalidOperationException();
48-
}
43+
serviceProvider.HandleTokenRequest().Respond();
4944
}
5045
}
5146
}

projecttemplates/WebFormsRelyingParty/OAuthTokenEndpoint.ashx.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,7 @@ public bool IsReusable {
3939
/// </summary>
4040
/// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
4141
public void ProcessRequest(HttpContext context) {
42-
var serviceProvider = OAuthServiceProvider.AuthorizationServer;
43-
IDirectResponseProtocolMessage response;
44-
if (serviceProvider.TryPrepareAccessTokenResponse(new HttpRequestWrapper(context.Request), out response)) {
45-
serviceProvider.Channel.Respond(response);
46-
} else {
47-
throw new InvalidOperationException();
48-
}
42+
OAuthServiceProvider.AuthorizationServer.HandleTokenRequest().Respond();
4943
}
5044
}
5145
}

samples/OAuthAuthorizationServer/Controllers/OAuthController.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@ public class OAuthController : Controller {
2121
/// </summary>
2222
/// <returns>The response to the Client.</returns>
2323
public ActionResult Token() {
24-
IDirectResponseProtocolMessage response;
25-
if (this.authorizationServer.TryPrepareAccessTokenResponse(out response)) {
26-
return this.authorizationServer.Channel.PrepareResponse(response).AsActionResult();
27-
} else {
28-
throw new HttpException((int)HttpStatusCode.BadRequest, "Missing OAuth 2.0 request message.");
29-
}
24+
return this.authorizationServer.HandleTokenRequest(this.Request).AsActionResult();
3025
}
3126

3227
/// <summary>

src/DotNetOpenAuth.Core/Messaging/OutgoingWebResponseActionResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ internal OutgoingWebResponseActionResult(OutgoingWebResponse response) {
3434
/// </summary>
3535
/// <param name="context">The context in which to set the response.</param>
3636
public override void ExecuteResult(ControllerContext context) {
37-
this.response.Respond();
37+
this.response.Respond(context.HttpContext);
3838
}
3939
}
4040
}

src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -97,55 +97,33 @@ public void RejectAuthorizationRequest(EndUserAuthorizationRequest authorization
9797
}
9898

9999
/// <summary>
100-
/// Checks the incoming HTTP request for an access token request and prepares a response if the request message was found.
100+
/// Handles an incoming request to the authorization server's token endpoint.
101101
/// </summary>
102-
/// <param name="response">The formulated response, or <c>null</c> if the request was not found..</param>
103-
/// <returns>A value indicating whether any access token request was found in the HTTP request.</returns>
104-
/// <remarks>
105-
/// This method assumes that the authorization server and the resource server are the same and that they share a single
106-
/// asymmetric key for signing and encrypting the access token. If this is not true, use the <see cref="ReadAccessTokenRequest"/> method instead.
107-
/// </remarks>
108-
public bool TryPrepareAccessTokenResponse(out IDirectResponseProtocolMessage response) {
109-
return this.TryPrepareAccessTokenResponse(this.Channel.GetRequestFromContext(), out response);
110-
}
111-
112-
/// <summary>
113-
/// Checks the incoming HTTP request for an access token request and prepares a response if the request message was found.
114-
/// </summary>
115-
/// <param name="httpRequestInfo">The HTTP request info.</param>
116-
/// <param name="response">The formulated response, or <c>null</c> if the request was not found..</param>
117-
/// <returns>A value indicating whether any access token request was found in the HTTP request.</returns>
118-
/// <remarks>
119-
/// This method assumes that the authorization server and the resource server are the same and that they share a single
120-
/// asymmetric key for signing and encrypting the access token. If this is not true, use the <see cref="ReadAccessTokenRequest"/> method instead.
121-
/// </remarks>
122-
public bool TryPrepareAccessTokenResponse(HttpRequestBase httpRequestInfo, out IDirectResponseProtocolMessage response) {
123-
Requires.NotNull(httpRequestInfo, "httpRequestInfo");
124-
Contract.Ensures(Contract.Result<bool>() == (Contract.ValueAtReturn<IDirectResponseProtocolMessage>(out response) != null));
125-
126-
var request = this.ReadAccessTokenRequest(httpRequestInfo);
127-
if (request != null) {
128-
response = this.PrepareAccessTokenResponse(request);
129-
return true;
102+
/// <param name="request">The HTTP request.</param>
103+
/// <returns>The HTTP response to send to the client.</returns>
104+
public OutgoingWebResponse HandleTokenRequest(HttpRequestBase request = null) {
105+
if (request == null) {
106+
request = this.Channel.GetRequestFromContext();
130107
}
131108

132-
response = null;
133-
return false;
134-
}
135-
136-
/// <summary>
137-
/// Reads the access token request.
138-
/// </summary>
139-
/// <param name="requestInfo">The request info.</param>
140-
/// <returns>The Client's request for an access token; or <c>null</c> if no such message was found in the request.</returns>
141-
public AccessTokenRequestBase ReadAccessTokenRequest(HttpRequestBase requestInfo = null) {
142-
if (requestInfo == null) {
143-
requestInfo = this.Channel.GetRequestFromContext();
109+
AccessTokenRequestBase requestMessage;
110+
IProtocolMessage responseMessage;
111+
try {
112+
if (this.Channel.TryReadFromRequest(request, out requestMessage)) {
113+
// TODO: refreshToken should be set appropriately based on authorization server policy.
114+
responseMessage = this.PrepareAccessTokenResponse(requestMessage);
115+
} else {
116+
responseMessage = new AccessTokenFailedResponse() {
117+
Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest,
118+
};
119+
}
120+
} catch (ProtocolException ex) {
121+
responseMessage = new AccessTokenFailedResponse() {
122+
Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest,
123+
};
144124
}
145125

146-
AccessTokenRequestBase request;
147-
this.Channel.TryReadFromRequest(requestInfo, out request);
148-
return request;
126+
return this.Channel.PrepareResponse(responseMessage);
149127
}
150128

151129
/// <summary>
@@ -214,7 +192,7 @@ public EndUserAuthorizationSuccessResponseBase PrepareApproveAuthorizationReques
214192
/// <param name="request">The request for an access token.</param>
215193
/// <param name="includeRefreshToken">If set to <c>true</c>, the response will include a long-lived refresh token.</param>
216194
/// <returns>The response message to send to the client.</returns>
217-
public virtual IDirectResponseProtocolMessage PrepareAccessTokenResponse(AccessTokenRequestBase request, bool includeRefreshToken = true) {
195+
private IDirectResponseProtocolMessage PrepareAccessTokenResponse(AccessTokenRequestBase request, bool includeRefreshToken = true) {
218196
Requires.NotNull(request, "request");
219197

220198
if (includeRefreshToken) {

src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenFailedResponse.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,18 @@ internal AccessTokenFailedResponse(AccessTokenRequestBase request)
3838
/// <param name="request">The faulty request.</param>
3939
/// <param name="invalidClientCredentialsInAuthorizationHeader">A value indicating whether this error response is in result to a request that had invalid client credentials which were supplied in the HTTP Authorization header.</param>
4040
internal AccessTokenFailedResponse(AccessTokenRequestBase request, bool invalidClientCredentialsInAuthorizationHeader)
41-
: base(request)
42-
{
41+
: base(request) {
4342
this.invalidClientCredentialsInAuthorizationHeader = invalidClientCredentialsInAuthorizationHeader;
4443
}
4544

45+
/// <summary>
46+
/// Initializes a new instance of the <see cref="AccessTokenFailedResponse"/> class.
47+
/// </summary>
48+
/// <param name="version">The protocol version.</param>
49+
internal AccessTokenFailedResponse(Version version = null)
50+
: base(version ?? Protocol.Default.Version) {
51+
}
52+
4653
#region IHttpDirectResponse Members
4754

4855
/// <summary>

src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@
243243
<Compile Include="Mocks\TestChannel.cs" />
244244
<Compile Include="Mocks\TestMessage.cs" />
245245
<Compile Include="Mocks\TestMessageFactory.cs" />
246+
<Compile Include="OAuth2\AuthorizationServerTests.cs" />
246247
<Compile Include="OAuth2\MessageFactoryTests.cs" />
247248
<Compile Include="OAuth2\UserAgentClientAuthorizeTests.cs" />
248249
<Compile Include="OAuth2\OAuth2Coordinator.cs" />
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//-----------------------------------------------------------------------
2+
// <copyright file="AuthorizationServerTests.cs" company="Andrew Arnott">
3+
// Copyright (c) Andrew Arnott. All rights reserved.
4+
// </copyright>
5+
//-----------------------------------------------------------------------
6+
7+
namespace DotNetOpenAuth.Test.OAuth2 {
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Linq;
11+
using System.Text;
12+
using DotNetOpenAuth.OAuth2;
13+
using DotNetOpenAuth.OAuth2.Messages;
14+
using NUnit.Framework;
15+
16+
/// <summary>
17+
/// Verifies authorization server functionality.
18+
/// </summary>
19+
[TestFixture]
20+
public class AuthorizationServerTests : OAuth2TestBase {
21+
/// <summary>
22+
/// Verifies that authorization server responds with an appropriate error response.
23+
/// </summary>
24+
[Test]
25+
public void ErrorResponseTest() {
26+
var coordinator = new OAuth2Coordinator<UserAgentClient>(
27+
AuthorizationServerDescription,
28+
AuthorizationServerMock,
29+
new UserAgentClient(AuthorizationServerDescription),
30+
client => {
31+
var request = new AccessTokenAuthorizationCodeRequest(AuthorizationServerDescription)
32+
{ ClientIdentifier = ClientId, ClientSecret = ClientSecret, AuthorizationCode = "foo" };
33+
34+
var response = client.Channel.Request<AccessTokenFailedResponse>(request);
35+
Assert.That(response.Error, Is.Not.Null.And.Not.Empty);
36+
Assert.That(response.Error, Is.EqualTo(Protocol.AccessTokenRequestErrorCodes.InvalidRequest));
37+
},
38+
server => {
39+
server.HandleTokenRequest().Respond();
40+
});
41+
coordinator.Run();
42+
}
43+
}
44+
}

src/DotNetOpenAuth.Test/OAuth2/UserAgentClientAuthorizeTests.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,7 @@ public void AuthorizationCodeGrant() {
4141
var request = server.ReadAuthorizationRequest();
4242
Assert.That(request, Is.Not.Null);
4343
server.ApproveAuthorizationRequest(request, ResourceOwnerUsername);
44-
var tokenRequest = server.ReadAccessTokenRequest();
45-
IAccessTokenRequest accessTokenRequest = tokenRequest;
46-
Assert.That(accessTokenRequest.ClientAuthenticated);
47-
var tokenResponse = server.PrepareAccessTokenResponse(tokenRequest);
48-
server.Channel.Respond(tokenResponse);
44+
server.HandleTokenRequest().Respond();
4945
});
5046
coordinator.Run();
5147
}

src/DotNetOpenAuth.Test/OAuth2/WebServerClientAuthorizeTests.cs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,7 @@ public void AuthorizationCodeGrant() {
3737
var request = server.ReadAuthorizationRequest();
3838
Assert.That(request, Is.Not.Null);
3939
server.ApproveAuthorizationRequest(request, ResourceOwnerUsername);
40-
var tokenRequest = server.ReadAccessTokenRequest();
41-
IAccessTokenRequest accessTokenRequest = tokenRequest;
42-
Assert.That(accessTokenRequest.ClientAuthenticated);
43-
var tokenResponse = server.PrepareAccessTokenResponse(tokenRequest);
44-
server.Channel.Respond(tokenResponse);
40+
server.HandleTokenRequest().Respond();
4541
});
4642
coordinator.Run();
4743
}
@@ -58,9 +54,7 @@ public void ResourceOwnerPasswordCredentialGrant() {
5854
Assert.That(authState.RefreshToken, Is.Not.Null.And.Not.Empty);
5955
},
6056
server => {
61-
var request = server.ReadAccessTokenRequest();
62-
var response = server.PrepareAccessTokenResponse(request);
63-
server.Channel.Respond(response);
57+
server.HandleTokenRequest().Respond();
6458
});
6559
coordinator.Run();
6660
}
@@ -81,9 +75,7 @@ public void ClientCredentialGrant() {
8175
Assert.That(authState.RefreshToken, Is.Null);
8276
},
8377
server => {
84-
var request = server.ReadAccessTokenRequest();
85-
var response = server.PrepareAccessTokenResponse(request);
86-
server.Channel.Respond(response);
78+
server.HandleTokenRequest().Respond();
8779
});
8880
coordinator.Run();
8981
}

0 commit comments

Comments
 (0)