summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs')
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs99
1 files changed, 84 insertions, 15 deletions
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs
index eda6bc1..49d0732 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;
@@ -26,13 +29,16 @@ namespace DotNetOpenAuth.OAuth2 {
/// </summary>
/// <param name="authorizationServer">The token issuer.</param>
/// <param name="clientIdentifier">The client identifier.</param>
- /// <param name="clientSecret">The client secret.</param>
- protected ClientBase(AuthorizationServerDescription authorizationServer, string clientIdentifier = null, string clientSecret = null) {
+ /// <param name="clientCredentialApplicator">
+ /// The tool to use to apply client credentials to authenticated requests to the Authorization Server.
+ /// May be <c>null</c> for clients with no secret or other means of authentication.
+ /// </param>
+ protected ClientBase(AuthorizationServerDescription authorizationServer, string clientIdentifier = null, ClientCredentialApplicator clientCredentialApplicator = null) {
Requires.NotNull(authorizationServer, "authorizationServer");
this.AuthorizationServer = authorizationServer;
this.Channel = new OAuth2ClientChannel();
this.ClientIdentifier = clientIdentifier;
- this.ClientSecret = clientSecret;
+ this.ClientCredentialApplicator = clientCredentialApplicator;
}
/// <summary>
@@ -50,12 +56,26 @@ namespace DotNetOpenAuth.OAuth2 {
/// <summary>
/// Gets or sets the identifier by which this client is known to the Authorization Server.
/// </summary>
- public string ClientIdentifier { get; set; }
+ public string ClientIdentifier {
+ get { return this.OAuthChannel.ClientIdentifier; }
+ set { this.OAuthChannel.ClientIdentifier = value; }
+ }
/// <summary>
- /// Gets or sets the client secret shared with the Authorization Server.
+ /// Gets or sets the tool to use to apply client credentials to authenticated requests to the Authorization Server.
/// </summary>
- public string ClientSecret { get; set; }
+ /// <value>May be <c>null</c> if this client has no client secret.</value>
+ public ClientCredentialApplicator ClientCredentialApplicator {
+ get { return this.OAuthChannel.ClientCredentialApplicator; }
+ set { this.OAuthChannel.ClientCredentialApplicator = value; }
+ }
+
+ /// <summary>
+ /// Gets the OAuth client channel.
+ /// </summary>
+ internal IOAuth2ChannelWithClient OAuthChannel {
+ get { return (IOAuth2ChannelWithClient)this.Channel; }
+ }
/// <summary>
/// Adds the necessary HTTP Authorization header to an HTTP request for protected resources
@@ -80,7 +100,7 @@ namespace DotNetOpenAuth.OAuth2 {
Requires.NotNull(request, "request");
Requires.NotNull(authorization, "authorization");
Requires.True(!string.IsNullOrEmpty(authorization.AccessToken), "authorization");
- ErrorUtilities.VerifyProtocol(!authorization.AccessTokenExpirationUtc.HasValue || authorization.AccessTokenExpirationUtc < DateTime.UtcNow || authorization.RefreshToken != null, ClientStrings.AuthorizationExpired);
+ ErrorUtilities.VerifyProtocol(!authorization.AccessTokenExpirationUtc.HasValue || authorization.AccessTokenExpirationUtc >= DateTime.UtcNow || authorization.RefreshToken != null, ClientStrings.AuthorizationExpired);
if (authorization.AccessTokenExpirationUtc.HasValue && authorization.AccessTokenExpirationUtc.Value < DateTime.UtcNow) {
ErrorUtilities.VerifyProtocol(authorization.RefreshToken != null, ClientStrings.AccessTokenRefreshFailed);
@@ -90,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.
@@ -116,12 +162,13 @@ namespace DotNetOpenAuth.OAuth2 {
}
}
- var request = new AccessTokenRefreshRequest(this.AuthorizationServer) {
+ var request = new AccessTokenRefreshRequestC(this.AuthorizationServer) {
ClientIdentifier = this.ClientIdentifier,
- ClientSecret = this.ClientSecret,
RefreshToken = authorization.RefreshToken,
};
+ this.ApplyClientCredential(request);
+
var response = this.Channel.Request<AccessTokenSuccessResponse>(request);
UpdateAuthorizationWithResponse(authorization, response);
return true;
@@ -143,12 +190,13 @@ namespace DotNetOpenAuth.OAuth2 {
Requires.NotNull(scope, "scope");
Contract.Ensures(Contract.Result<IAuthorizationState>() != null);
- var request = new AccessTokenRefreshRequest(this.AuthorizationServer) {
+ var request = new AccessTokenRefreshRequestC(this.AuthorizationServer) {
ClientIdentifier = this.ClientIdentifier,
- ClientSecret = this.ClientSecret,
RefreshToken = refreshToken,
};
+ this.ApplyClientCredential(request);
+
var response = this.Channel.Request<AccessTokenSuccessResponse>(request);
var authorization = new AuthorizationState();
UpdateAuthorizationWithResponse(authorization, response);
@@ -248,12 +296,12 @@ namespace DotNetOpenAuth.OAuth2 {
Requires.NotNull(authorizationState, "authorizationState");
Requires.NotNull(authorizationSuccess, "authorizationSuccess");
- var accessTokenRequest = new AccessTokenAuthorizationCodeRequest(this.AuthorizationServer) {
+ var accessTokenRequest = new AccessTokenAuthorizationCodeRequestC(this.AuthorizationServer) {
ClientIdentifier = this.ClientIdentifier,
- ClientSecret = this.ClientSecret,
Callback = authorizationState.Callback,
AuthorizationCode = authorizationSuccess.AuthorizationCode,
};
+ this.ApplyClientCredential(accessTokenRequest);
IProtocolMessage accessTokenResponse = this.Channel.Request(accessTokenRequest);
var accessTokenSuccess = accessTokenResponse as AccessTokenSuccessResponse;
var failedAccessTokenResponse = accessTokenResponse as AccessTokenFailedResponse;
@@ -262,7 +310,28 @@ namespace DotNetOpenAuth.OAuth2 {
} else {
authorizationState.Delete();
string error = failedAccessTokenResponse != null ? failedAccessTokenResponse.Error : "(unknown)";
- ErrorUtilities.ThrowProtocol(OAuthStrings.CannotObtainAccessTokenWithReason, error);
+ ErrorUtilities.ThrowProtocol(ClientStrings.CannotObtainAccessTokenWithReason, error);
+ }
+ }
+
+ /// <summary>
+ /// Applies the default client authentication mechanism given a client secret.
+ /// </summary>
+ /// <param name="secret">The client secret. May be <c>null</c></param>
+ /// <returns>The client credential applicator.</returns>
+ protected static ClientCredentialApplicator DefaultSecretApplicator(string secret) {
+ return secret == null ? ClientCredentialApplicator.NoSecret() : ClientCredentialApplicator.NetworkCredential(secret);
+ }
+
+ /// <summary>
+ /// Applies any applicable client credential to an authenticated outbound request to the authorization server.
+ /// </summary>
+ /// <param name="request">The request to apply authentication information to.</param>
+ protected void ApplyClientCredential(AuthenticatedClientRequestBase request) {
+ Requires.NotNull(request, "request");
+
+ if (this.ClientCredentialApplicator != null) {
+ this.ClientCredentialApplicator.ApplyClientCredential(this.ClientIdentifier, request);
}
}
@@ -295,7 +364,7 @@ namespace DotNetOpenAuth.OAuth2 {
var authorizationState = new AuthorizationState(scopes);
request.ClientIdentifier = this.ClientIdentifier;
- request.ClientSecret = this.ClientSecret;
+ this.ApplyClientCredential(request);
request.Scope.UnionWith(authorizationState.Scope);
var response = this.Channel.Request(request);