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

Commit dc4ea8b

Browse files
committed
OAuth2.Client builds.
1 parent 6ab8955 commit dc4ea8b

File tree

13 files changed

+168
-93
lines changed

13 files changed

+168
-93
lines changed

src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace DotNetOpenAuth.Messaging {
1515
using System.Linq;
1616
using System.Net;
1717
using System.Net.Http;
18+
using System.Net.Http.Headers;
1819
using System.Net.Mime;
1920
using System.Runtime.Serialization.Json;
2021
using System.Security;
@@ -624,6 +625,26 @@ internal static string GetNonCryptoRandomDataAsBase64(int binaryLength) {
624625
return uniq;
625626
}
626627

628+
/// <summary>
629+
/// Adds a Set-Cookie HTTP header for the specified cookie.
630+
/// WARNING: support for cookie properties is currently VERY LIMITED.
631+
/// </summary>
632+
internal static void SetCookie(this HttpResponseHeaders headers, Cookie cookie) {
633+
Requires.NotNull(headers, "headers");
634+
Requires.NotNull(cookie, "cookie");
635+
636+
var cookieBuilder = new StringBuilder(HttpUtility.UrlEncode(cookie.Name) + "=" + HttpUtility.UrlEncode(cookie.Value));
637+
if (cookie.HttpOnly) {
638+
cookieBuilder.Append("; HttpOnly");
639+
}
640+
641+
if (cookie.Secure) {
642+
cookieBuilder.Append("; Secure");
643+
}
644+
645+
headers.Add("Set-Cookie", cookieBuilder.ToString());
646+
}
647+
627648
/// <summary>
628649
/// Gets a random string made up of a given set of allowable characters.
629650
/// </summary>
@@ -1525,6 +1546,27 @@ internal static void AddExtraParameters(this MessageDictionary messageDictionary
15251546
}
15261547
}
15271548

1549+
internal static Uri GetDirectUriRequest(this HttpResponseMessage response) {
1550+
Requires.NotNull(response, "response");
1551+
Requires.Argument(
1552+
response.StatusCode == HttpStatusCode.Redirect || response.StatusCode == HttpStatusCode.RedirectKeepVerb
1553+
|| response.StatusCode == HttpStatusCode.RedirectMethod || response.StatusCode == HttpStatusCode.TemporaryRedirect,
1554+
"response",
1555+
"Redirecting response expected.");
1556+
Requires.Argument(response.Headers.Location != null, "response", "Redirect URL header expected.");
1557+
Requires.Argument(response.Content == null || response.Content is FormUrlEncodedContent, "response", "FormUrlEncodedContent expected");
1558+
1559+
var builder = new UriBuilder(response.Headers.Location);
1560+
if (response.Content != null) {
1561+
var content = response.Content.ReadAsStringAsync();
1562+
Assumes.True(content.IsCompleted); // cached in memory, so it should never complete asynchronously.
1563+
var formFields = HttpUtility.ParseQueryString(content.Result).ToDictionary();
1564+
MessagingUtilities.AppendQueryArgs(builder, formFields);
1565+
}
1566+
1567+
return builder.Uri;
1568+
}
1569+
15281570
/// <summary>
15291571
/// Collects a sequence of key=value pairs into a dictionary.
15301572
/// </summary>

src/DotNetOpenAuth.OAuth2.Client/OAuth2/BearerTokenHttpMessageHandler.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,21 @@ public BearerTokenHttpMessageHandler(ClientBase client, IAuthorizationState auth
7272
/// <returns>
7373
/// Returns <see cref="T:System.Threading.Tasks.Task`1" />. The task object representing the asynchronous operation.
7474
/// </returns>
75-
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
75+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
7676
string bearerToken = this.BearerToken;
7777
if (bearerToken == null) {
7878
ErrorUtilities.VerifyProtocol(!this.Authorization.AccessTokenExpirationUtc.HasValue || this.Authorization.AccessTokenExpirationUtc < DateTime.UtcNow || this.Authorization.RefreshToken != null, ClientStrings.AuthorizationExpired);
7979

8080
if (this.Authorization.AccessTokenExpirationUtc.HasValue && this.Authorization.AccessTokenExpirationUtc.Value < DateTime.UtcNow) {
8181
ErrorUtilities.VerifyProtocol(this.Authorization.RefreshToken != null, ClientStrings.AccessTokenRefreshFailed);
82-
this.Client.RefreshAuthorization(this.Authorization);
82+
await this.Client.RefreshAuthorizationAsync(this.Authorization, cancellationToken: cancellationToken);
8383
}
8484

8585
bearerToken = this.Authorization.AccessToken;
8686
}
8787

8888
request.Headers.Authorization = new AuthenticationHeaderValue(Protocol.BearerHttpAuthorizationScheme, bearerToken);
89-
return base.SendAsync(request, cancellationToken);
89+
return await base.SendAsync(request, cancellationToken);
9090
}
9191
}
9292
}

src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
99
using System.Collections.Generic;
1010
using System.Collections.Specialized;
1111
using System.Net;
12+
using System.Net.Http;
13+
using System.Threading;
14+
using System.Threading.Tasks;
1215
using System.Web;
1316
using System.Xml;
14-
1517
using DotNetOpenAuth.Messaging;
1618
using DotNetOpenAuth.OAuth2.Messages;
1719

@@ -67,8 +69,8 @@ public XmlDictionaryReaderQuotas JsonReaderQuotas {
6769
/// This method must be overridden by a derived class, unless the <see cref="Channel.RequestCore"/> method
6870
/// is overridden and does not require this method.
6971
/// </remarks>
70-
protected override HttpWebRequest CreateHttpRequest(IDirectedProtocolMessage request) {
71-
HttpWebRequest httpRequest;
72+
protected override HttpRequestMessage CreateHttpRequest(IDirectedProtocolMessage request) {
73+
HttpRequestMessage httpRequest;
7274
if ((request.HttpMethods & HttpDeliveryMethods.GetRequest) != 0) {
7375
httpRequest = InitializeRequestAsGet(request);
7476
} else if ((request.HttpMethods & HttpDeliveryMethods.PostRequest) != 0) {
@@ -88,16 +90,17 @@ protected override HttpWebRequest CreateHttpRequest(IDirectedProtocolMessage req
8890
/// The deserialized message parts, if found. Null otherwise.
8991
/// </returns>
9092
/// <exception cref="ProtocolException">Thrown when the response is not valid.</exception>
91-
protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) {
93+
protected override async Task<IDictionary<string, string>> ReadFromResponseCoreAsync(HttpResponseMessage response) {
9294
// The spec says direct responses should be JSON objects, but Facebook uses HttpFormUrlEncoded instead, calling it text/plain
9395
// Others return text/javascript. Again bad.
94-
string body = response.GetResponseReader().ReadToEnd();
95-
if (response.ContentType.MediaType == JsonEncoded || response.ContentType.MediaType == JsonTextEncoded) {
96+
string body = await response.Content.ReadAsStringAsync();
97+
var contentType = response.Content.Headers.ContentType.MediaType;
98+
if (contentType == JsonEncoded || contentType == JsonTextEncoded) {
9699
return this.DeserializeFromJson(body);
97-
} else if (response.ContentType.MediaType == HttpFormUrlEncoded || response.ContentType.MediaType == PlainTextEncoded) {
100+
} else if (contentType == HttpFormUrlEncoded || contentType == PlainTextEncoded) {
98101
return HttpUtility.ParseQueryString(body).ToDictionary();
99102
} else {
100-
throw ErrorUtilities.ThrowProtocol(ClientStrings.UnexpectedResponseContentType, response.ContentType.MediaType);
103+
throw ErrorUtilities.ThrowProtocol(ClientStrings.UnexpectedResponseContentType, contentType);
101104
}
102105
}
103106

@@ -108,7 +111,7 @@ protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebR
108111
/// <returns>
109112
/// The deserialized message, if one is found. Null otherwise.
110113
/// </returns>
111-
protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) {
114+
protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request, CancellationToken cancellationToken) {
112115
Logger.Channel.DebugFormat("Incoming HTTP request: {0} {1}", request.HttpMethod, request.GetPublicFacingUrl().AbsoluteUri);
113116

114117
var fields = request.GetQueryStringBeforeRewriting().ToDictionary();
@@ -146,7 +149,7 @@ protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase
146149
/// <remarks>
147150
/// This method implements spec OAuth V1.0 section 5.3.
148151
/// </remarks>
149-
protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) {
152+
protected override HttpResponseMessage PrepareDirectResponse(IProtocolMessage response) {
150153
// Clients don't ever send direct responses.
151154
throw new NotImplementedException();
152155
}
@@ -155,7 +158,7 @@ protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage re
155158
/// Performs additional processing on an outgoing web request before it is sent to the remote server.
156159
/// </summary>
157160
/// <param name="request">The request.</param>
158-
protected override void PrepareHttpWebRequest(HttpWebRequest request) {
161+
protected override void PrepareHttpWebRequest(HttpRequestMessage request) {
159162
base.PrepareHttpWebRequest(request);
160163

161164
if (this.ClientCredentialApplicator != null) {

src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ namespace DotNetOpenAuth.OAuth2 {
1313
using System.Net.Http;
1414
using System.Security;
1515
using System.Text;
16+
using System.Threading;
17+
using System.Threading.Tasks;
1618
using System.Xml;
17-
1819
using DotNetOpenAuth.Messaging;
1920
using DotNetOpenAuth.OAuth2.ChannelElements;
2021
using DotNetOpenAuth.OAuth2.Messages;
@@ -116,11 +117,11 @@ public static void AuthorizeRequest(WebHeaderCollection requestHeaders, string a
116117
/// </summary>
117118
/// <param name="request">The request for protected resources from the service provider.</param>
118119
/// <param name="authorization">The authorization for this request previously obtained via OAuth.</param>
119-
public void AuthorizeRequest(HttpWebRequest request, IAuthorizationState authorization) {
120+
public Task AuthorizeRequestAsync(HttpWebRequest request, IAuthorizationState authorization, CancellationToken cancellationToken) {
120121
Requires.NotNull(request, "request");
121122
Requires.NotNull(authorization, "authorization");
122123

123-
this.AuthorizeRequest(request.Headers, authorization);
124+
return this.AuthorizeRequestAsync(request.Headers, authorization, cancellationToken);
124125
}
125126

126127
/// <summary>
@@ -129,15 +130,15 @@ public void AuthorizeRequest(HttpWebRequest request, IAuthorizationState authori
129130
/// </summary>
130131
/// <param name="requestHeaders">The headers on the request for protected resources from the service provider.</param>
131132
/// <param name="authorization">The authorization for this request previously obtained via OAuth.</param>
132-
public void AuthorizeRequest(WebHeaderCollection requestHeaders, IAuthorizationState authorization) {
133+
public async Task AuthorizeRequestAsync(WebHeaderCollection requestHeaders, IAuthorizationState authorization, CancellationToken cancellationToken) {
133134
Requires.NotNull(requestHeaders, "requestHeaders");
134135
Requires.NotNull(authorization, "authorization");
135136
Requires.That(!string.IsNullOrEmpty(authorization.AccessToken), "authorization", "AccessToken required.");
136137
ErrorUtilities.VerifyProtocol(!authorization.AccessTokenExpirationUtc.HasValue || authorization.AccessTokenExpirationUtc >= DateTime.UtcNow || authorization.RefreshToken != null, ClientStrings.AuthorizationExpired);
137138

138139
if (authorization.AccessTokenExpirationUtc.HasValue && authorization.AccessTokenExpirationUtc.Value < DateTime.UtcNow) {
139140
ErrorUtilities.VerifyProtocol(authorization.RefreshToken != null, ClientStrings.AccessTokenRefreshFailed);
140-
this.RefreshAuthorization(authorization);
141+
await this.RefreshAuthorizationAsync(authorization, cancellationToken: cancellationToken);
141142
}
142143

143144
AuthorizeRequest(requestHeaders, authorization.AccessToken);
@@ -180,7 +181,7 @@ public DelegatingHandler CreateAuthorizingHandler(IAuthorizationState authorizat
180181
/// the <paramref name="authorization"/> parameter if the authorization server has cycled out your refresh token.
181182
/// If the parameter value was updated, this method calls <see cref="IAuthorizationState.SaveChanges"/> on that instance.
182183
/// </remarks>
183-
public bool RefreshAuthorization(IAuthorizationState authorization, TimeSpan? skipIfUsefulLifeExceeds = null) {
184+
public async Task<bool> RefreshAuthorizationAsync(IAuthorizationState authorization, TimeSpan? skipIfUsefulLifeExceeds = null, CancellationToken cancellationToken = default(CancellationToken)) {
184185
Requires.NotNull(authorization, "authorization");
185186
Requires.That(!string.IsNullOrEmpty(authorization.RefreshToken), "authorization", "RefreshToken required.");
186187

@@ -200,7 +201,7 @@ public bool RefreshAuthorization(IAuthorizationState authorization, TimeSpan? sk
200201

201202
this.ApplyClientCredential(request);
202203

203-
var response = this.Channel.Request<AccessTokenSuccessResponse>(request);
204+
var response = await this.Channel.RequestAsync<AccessTokenSuccessResponse>(request, cancellationToken);
204205
UpdateAuthorizationWithResponse(authorization, response);
205206
return true;
206207
}
@@ -216,7 +217,7 @@ public bool RefreshAuthorization(IAuthorizationState authorization, TimeSpan? sk
216217
/// If the return value includes a new refresh token, the old refresh token should be discarded and
217218
/// replaced with the new one.
218219
/// </remarks>
219-
public IAuthorizationState GetScopedAccessToken(string refreshToken, HashSet<string> scope) {
220+
public async Task<IAuthorizationState> GetScopedAccessTokenAsync(string refreshToken, HashSet<string> scope, CancellationToken cancellationToken) {
220221
Requires.NotNullOrEmpty(refreshToken, "refreshToken");
221222
Requires.NotNull(scope, "scope");
222223

@@ -227,7 +228,7 @@ public IAuthorizationState GetScopedAccessToken(string refreshToken, HashSet<str
227228

228229
this.ApplyClientCredential(request);
229230

230-
var response = this.Channel.Request<AccessTokenSuccessResponse>(request);
231+
var response = await this.Channel.RequestAsync<AccessTokenSuccessResponse>(request, cancellationToken);
231232
var authorization = new AuthorizationState();
232233
UpdateAuthorizationWithResponse(authorization, response);
233234

@@ -241,7 +242,7 @@ public IAuthorizationState GetScopedAccessToken(string refreshToken, HashSet<str
241242
/// <param name="password">The resource owner's account password.</param>
242243
/// <param name="scopes">The desired scope of access.</param>
243244
/// <returns>The result, containing the tokens if successful.</returns>
244-
public IAuthorizationState ExchangeUserCredentialForToken(string userName, string password, IEnumerable<string> scopes = null) {
245+
public Task<IAuthorizationState> ExchangeUserCredentialForTokenAsync(string userName, string password, IEnumerable<string> scopes = null, CancellationToken cancellationToken = default(CancellationToken)) {
245246
Requires.NotNullOrEmpty(userName, "userName");
246247
Requires.NotNull(password, "password");
247248

@@ -250,17 +251,17 @@ public IAuthorizationState ExchangeUserCredentialForToken(string userName, strin
250251
Password = password,
251252
};
252253

253-
return this.RequestAccessToken(request, scopes);
254+
return this.RequestAccessTokenAsync(request, scopes, cancellationToken);
254255
}
255256

256257
/// <summary>
257258
/// Obtains an access token for accessing client-controlled resources on the resource server.
258259
/// </summary>
259260
/// <param name="scopes">The desired scopes.</param>
260261
/// <returns>The result of the authorization request.</returns>
261-
public IAuthorizationState GetClientAccessToken(IEnumerable<string> scopes = null) {
262+
public Task<IAuthorizationState> GetClientAccessTokenAsync(IEnumerable<string> scopes = null, CancellationToken cancellationToken = default(CancellationToken)) {
262263
var request = new AccessTokenClientCredentialsRequest(this.AuthorizationServer.TokenEndpoint, this.AuthorizationServer.Version);
263-
return this.RequestAccessToken(request, scopes);
264+
return this.RequestAccessTokenAsync(request, scopes, cancellationToken);
264265
}
265266

266267
/// <summary>
@@ -322,7 +323,7 @@ internal static void UpdateAuthorizationWithResponse(IAuthorizationState authori
322323
/// </summary>
323324
/// <param name="authorizationState">The authorization state to update.</param>
324325
/// <param name="authorizationSuccess">The authorization success message obtained from the authorization server.</param>
325-
internal void UpdateAuthorizationWithResponse(IAuthorizationState authorizationState, EndUserAuthorizationSuccessAuthCodeResponse authorizationSuccess) {
326+
internal async Task UpdateAuthorizationWithResponseAsync(IAuthorizationState authorizationState, EndUserAuthorizationSuccessAuthCodeResponse authorizationSuccess, CancellationToken cancellationToken) {
326327
Requires.NotNull(authorizationState, "authorizationState");
327328
Requires.NotNull(authorizationSuccess, "authorizationSuccess");
328329

@@ -332,7 +333,7 @@ internal void UpdateAuthorizationWithResponse(IAuthorizationState authorizationS
332333
AuthorizationCode = authorizationSuccess.AuthorizationCode,
333334
};
334335
this.ApplyClientCredential(accessTokenRequest);
335-
IProtocolMessage accessTokenResponse = this.Channel.Request(accessTokenRequest);
336+
IProtocolMessage accessTokenResponse = await this.Channel.RequestAsync(accessTokenRequest, cancellationToken);
336337
var accessTokenSuccess = accessTokenResponse as AccessTokenSuccessResponse;
337338
var failedAccessTokenResponse = accessTokenResponse as AccessTokenFailedResponse;
338339
if (accessTokenSuccess != null) {
@@ -388,7 +389,7 @@ private static double ProportionalLifeRemaining(IAuthorizationState authorizatio
388389
/// <param name="request">The request message.</param>
389390
/// <param name="scopes">The scopes requested by the client.</param>
390391
/// <returns>The result of the request.</returns>
391-
private IAuthorizationState RequestAccessToken(ScopedAccessTokenRequest request, IEnumerable<string> scopes = null) {
392+
private async Task<IAuthorizationState> RequestAccessTokenAsync(ScopedAccessTokenRequest request, IEnumerable<string> scopes, CancellationToken cancellationToken) {
392393
Requires.NotNull(request, "request");
393394

394395
var authorizationState = new AuthorizationState(scopes);
@@ -397,7 +398,7 @@ private IAuthorizationState RequestAccessToken(ScopedAccessTokenRequest request,
397398
this.ApplyClientCredential(request);
398399
request.Scope.UnionWith(authorizationState.Scope);
399400

400-
var response = this.Channel.Request(request);
401+
var response = await this.Channel.RequestAsync(request, cancellationToken);
401402
var success = response as AccessTokenSuccessResponse;
402403
var failure = response as AccessTokenFailedResponse;
403404
ErrorUtilities.VerifyProtocol(success != null || failure != null, MessagingStrings.UnexpectedMessageReceivedOfMany);

src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientCredentialApplicator.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace DotNetOpenAuth.OAuth2 {
99
using System.Collections.Generic;
1010
using System.Linq;
1111
using System.Net;
12+
using System.Net.Http;
1213
using System.Text;
1314
using DotNetOpenAuth.Messaging;
1415
using DotNetOpenAuth.OAuth2.Messages;
@@ -75,7 +76,7 @@ public virtual void ApplyClientCredential(string clientIdentifier, Authenticated
7576
/// </summary>
7677
/// <param name="clientIdentifier">The identifier by which the authorization server should recognize this client.</param>
7778
/// <param name="request">The outbound message to apply authentication information to.</param>
78-
public virtual void ApplyClientCredential(string clientIdentifier, HttpWebRequest request) {
79+
public virtual void ApplyClientCredential(string clientIdentifier, HttpRequestMessage request) {
7980
}
8081

8182
/// <summary>
@@ -126,7 +127,7 @@ public override void ApplyClientCredential(string clientIdentifier, Authenticate
126127
/// </summary>
127128
/// <param name="clientIdentifier">The identifier by which the authorization server should recognize this client.</param>
128129
/// <param name="request">The outbound message to apply authentication information to.</param>
129-
public override void ApplyClientCredential(string clientIdentifier, HttpWebRequest request) {
130+
public override void ApplyClientCredential(string clientIdentifier, HttpRequestMessage request) {
130131
if (clientIdentifier != null) {
131132
if (this.credential != null) {
132133
ErrorUtilities.VerifyHost(

0 commit comments

Comments
 (0)