diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2012-09-26 17:30:39 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2012-09-26 17:30:39 -0700 |
commit | 6989c1b54778cc93edf9b305ffb827c389769c07 (patch) | |
tree | 46b7c453c7901dd733f9ccfcb1377fbab5006c9b /src/DotNetOpenAuth.OAuth2.Client/OAuth2 | |
parent | a657a72b7f6fb89d1a8adb82d2888a8d3f7f9bab (diff) | |
download | DotNetOpenAuth-6989c1b54778cc93edf9b305ffb827c389769c07.zip DotNetOpenAuth-6989c1b54778cc93edf9b305ffb827c389769c07.tar.gz DotNetOpenAuth-6989c1b54778cc93edf9b305ffb827c389769c07.tar.bz2 |
Adds ClientBase.CreateAuthorizingHandler
This method creates an HttpMessageHandler that automatically applies the OAuth 2 access token (bearer) to all outbound HTTP requests.
Fixes #205
Diffstat (limited to 'src/DotNetOpenAuth.OAuth2.Client/OAuth2')
-rw-r--r-- | src/DotNetOpenAuth.OAuth2.Client/OAuth2/BearerTokenHttpMessageHandler.cs | 93 | ||||
-rw-r--r-- | src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs | 29 |
2 files changed, 122 insertions, 0 deletions
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/BearerTokenHttpMessageHandler.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/BearerTokenHttpMessageHandler.cs new file mode 100644 index 0000000..6b2e937 --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/BearerTokenHttpMessageHandler.cs @@ -0,0 +1,93 @@ +//----------------------------------------------------------------------- +// <copyright file="BearerTokenHttpMessageHandler.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +#if CLR4 +namespace DotNetOpenAuth.OAuth2 { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Net.Http; + using System.Net.Http.Headers; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using DotNetOpenAuth.Messaging; + + /// <summary> + /// An <see cref="HttpMessageHandler"/> that applies a bearer token to each outbound HTTP request. + /// </summary> + internal class BearerTokenHttpMessageHandler : DelegatingHandler { + /// <summary> + /// Initializes a new instance of the <see cref="BearerTokenHttpMessageHandler" /> class. + /// </summary> + /// <param name="bearerToken">The bearer token.</param> + /// <param name="innerHandler">The inner handler.</param> + public BearerTokenHttpMessageHandler(string bearerToken, HttpMessageHandler innerHandler) + : base(innerHandler) { + Requires.NotNullOrEmpty(bearerToken, "bearerToken"); + this.BearerToken = bearerToken; + } + + /// <summary> + /// Initializes a new instance of the <see cref="BearerTokenHttpMessageHandler" /> class. + /// </summary> + /// <param name="client">The client associated with the authorization.</param> + /// <param name="authorization">The authorization.</param> + /// <param name="innerHandler">The inner handler.</param> + public BearerTokenHttpMessageHandler(ClientBase client, IAuthorizationState authorization, HttpMessageHandler innerHandler) + : base(innerHandler) { + Requires.NotNull(client, "client"); + Requires.NotNull(authorization, "authorization"); + Requires.True(!string.IsNullOrEmpty(authorization.AccessToken), "authorization.AccessToken"); + this.Client = client; + this.Authorization = authorization; + } + + /// <summary> + /// Gets the bearer token. + /// </summary> + /// <value> + /// The bearer token. + /// </value> + internal string BearerToken { get; private set; } + + /// <summary> + /// Gets the authorization. + /// </summary> + internal IAuthorizationState Authorization { get; private set; } + + /// <summary> + /// Gets the OAuth 2 client associated with the <see cref="Authorization"/>. + /// </summary> + internal ClientBase Client { get; private set; } + + /// <summary> + /// Sends an HTTP request to the inner handler to send to the server as an asynchronous operation. + /// </summary> + /// <param name="request">The HTTP request message to send to the server.</param> + /// <param name="cancellationToken">A cancellation token to cancel operation.</param> + /// <returns> + /// Returns <see cref="T:System.Threading.Tasks.Task`1" />. The task object representing the asynchronous operation. + /// </returns> + protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { + string bearerToken = this.BearerToken; + if (bearerToken == null) { + ErrorUtilities.VerifyProtocol(!this.Authorization.AccessTokenExpirationUtc.HasValue || this.Authorization.AccessTokenExpirationUtc < DateTime.UtcNow || this.Authorization.RefreshToken != null, ClientStrings.AuthorizationExpired); + + if (this.Authorization.AccessTokenExpirationUtc.HasValue && this.Authorization.AccessTokenExpirationUtc.Value < DateTime.UtcNow) { + ErrorUtilities.VerifyProtocol(this.Authorization.RefreshToken != null, ClientStrings.AccessTokenRefreshFailed); + this.Client.RefreshAuthorization(this.Authorization); + } + + bearerToken = this.Authorization.AccessToken; + } + + request.Headers.Authorization = new AuthenticationHeaderValue(Protocol.BearerHttpAuthorizationScheme, bearerToken); + return base.SendAsync(request, cancellationToken); + } + } +} +#endif
\ No newline at end of file diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs index 5f377ae..c983f8c 100644 --- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs @@ -11,6 +11,9 @@ namespace DotNetOpenAuth.OAuth2 { using System.Globalization; using System.Linq; using System.Net; +#if CLR4 + using System.Net.Http; +#endif using System.Security; using System.Text; using DotNetOpenAuth.Messaging; @@ -107,6 +110,32 @@ namespace DotNetOpenAuth.OAuth2 { AuthorizeRequest(request, authorization.AccessToken); } +#if CLR4 + /// <summary> + /// Creates an HTTP handler that automatically applies an OAuth 2 (bearer) access token to outbound HTTP requests. + /// The result of this method can be supplied to the <see cref="HttpClient(HttpMessageHandler)"/> constructor. + /// </summary> + /// <param name="bearerAccessToken">The bearer token to apply to each outbound HTTP message.</param> + /// <param name="innerHandler">The inner HTTP handler to use. The default uses <see cref="HttpClientHandler"/> as the inner handler.</param> + /// <returns>An <see cref="HttpMessageHandler"/> instance.</returns> + public DelegatingHandler CreateAuthorizingHandler(string bearerAccessToken, HttpMessageHandler innerHandler = null) { + Requires.NotNullOrEmpty(bearerAccessToken, "bearerAccessToken"); + return new BearerTokenHttpMessageHandler(bearerAccessToken, innerHandler ?? new HttpClientHandler()); + } + + /// <summary> + /// Creates an HTTP handler that automatically applies the OAuth 2 access token to outbound HTTP requests. + /// The result of this method can be supplied to the <see cref="HttpClient(HttpMessageHandler)"/> constructor. + /// </summary> + /// <param name="authorization">The authorization to apply to the message.</param> + /// <param name="innerHandler">The inner HTTP handler to use. The default uses <see cref="HttpClientHandler"/> as the inner handler.</param> + /// <returns>An <see cref="HttpMessageHandler"/> instance.</returns> + public DelegatingHandler CreateAuthorizingHandler(IAuthorizationState authorization, HttpMessageHandler innerHandler = null) { + Requires.NotNull(authorization, "authorization"); + return new BearerTokenHttpMessageHandler(this, authorization, innerHandler ?? new HttpClientHandler()); + } +#endif + /// <summary> /// Refreshes a short-lived access token using a longer-lived refresh token /// with a new access token that has the same scope as the refresh token. |