diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/DotNetOpenAuth/OAuth2/ClientBase.cs | 71 | ||||
-rw-r--r-- | src/DotNetOpenAuth/OAuth2/OAuth 2 client facades.cd | 8 | ||||
-rw-r--r-- | src/DotNetOpenAuth/OAuth2/WebServerClient.cs | 2 |
3 files changed, 51 insertions, 30 deletions
diff --git a/src/DotNetOpenAuth/OAuth2/ClientBase.cs b/src/DotNetOpenAuth/OAuth2/ClientBase.cs index f91b1f5..51aac39 100644 --- a/src/DotNetOpenAuth/OAuth2/ClientBase.cs +++ b/src/DotNetOpenAuth/OAuth2/ClientBase.cs @@ -83,19 +83,26 @@ namespace DotNetOpenAuth.OAuth2 { if (authorization.AccessTokenExpirationUtc.HasValue && authorization.AccessTokenExpirationUtc.Value < DateTime.UtcNow) { ErrorUtilities.VerifyProtocol(authorization.RefreshToken != null, "Access token has expired and cannot be automatically refreshed."); - this.RefreshToken(authorization); + this.RefreshAuthorization(authorization); } AuthorizeRequest(request, authorization.AccessToken); } /// <summary> - /// Refreshes a short-lived access token using a longer-lived refresh token. + /// 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. + /// The refresh token itself may also be refreshed. /// </summary> /// <param name="authorization">The authorization to update.</param> /// <param name="skipIfUsefulLifeExceeds">If given, the access token will <em>not</em> be refreshed if its remaining lifetime exceeds this value.</param> /// <returns>A value indicating whether the access token was actually renewed; <c>true</c> if it was renewed, or <c>false</c> if it still had useful life remaining.</returns> - public bool RefreshToken(IAuthorizationState authorization, TimeSpan? skipIfUsefulLifeExceeds = null) { + /// <remarks> + /// This method may modify the value of the <see cref="IAuthorizationState.RefreshToken"/> property on + /// the <paramref name="authorization"/> parameter if the authorization server has cycled out your refresh token. + /// If the parameter value was updated, this method calls <see cref="IAuthorizationState.SaveChanges"/> on that instance. + /// </remarks> + public bool RefreshAuthorization(IAuthorizationState authorization, TimeSpan? skipIfUsefulLifeExceeds = null) { Contract.Requires<ArgumentNullException>(authorization != null); Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(authorization.RefreshToken)); @@ -115,22 +122,37 @@ namespace DotNetOpenAuth.OAuth2 { }; var response = this.Channel.Request<AccessTokenSuccessResponse>(request); - authorization.AccessToken = response.AccessToken; - authorization.AccessTokenExpirationUtc = DateTime.UtcNow + response.Lifetime; - authorization.AccessTokenIssueDateUtc = DateTime.UtcNow; + UpdateAuthorizationWithResponse(authorization, response); + return true; + } - // Just in case the scope has changed... - if (response.Scope != null) { - authorization.Scope.ResetContents(response.Scope); - } + /// <summary> + /// Gets an access token that may be used for only a subset of the scope for which a given + /// refresh token is authorized. + /// </summary> + /// <param name="refreshToken">The refresh token.</param> + /// <param name="scope">The scope subset desired in the access token.</param> + /// <returns>A description of the obtained access token, and possibly a new refresh token.</returns> + /// <remarks> + /// If the return value includes a new refresh token, the old refresh token should be discarded and + /// replaced with the new one. + /// </remarks> + public IAuthorizationState GetScopedAccessToken(string refreshToken, HashSet<string> scope) { + Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(refreshToken)); + Contract.Requires<ArgumentNullException>(scope != null); + Contract.Ensures(Contract.Result<IAuthorizationState>() != null); - // The authorization server MAY choose to renew the refresh token itself. - if (response.RefreshToken != null) { - authorization.RefreshToken = response.RefreshToken; - } + var request = new AccessTokenRefreshRequest(this.AuthorizationServer) { + ClientIdentifier = this.ClientIdentifier, + ClientSecret = this.ClientSecret, + RefreshToken = refreshToken, + }; - authorization.SaveChanges(); - return true; + var response = this.Channel.Request<AccessTokenSuccessResponse>(request); + var authorization = new AuthorizationState(); + UpdateAuthorizationWithResponse(authorization, response); + + return authorization; } /// <summary> @@ -143,17 +165,18 @@ namespace DotNetOpenAuth.OAuth2 { Contract.Requires<ArgumentNullException>(accessTokenSuccess != null); authorizationState.AccessToken = accessTokenSuccess.AccessToken; - authorizationState.RefreshToken = accessTokenSuccess.RefreshToken; authorizationState.AccessTokenExpirationUtc = DateTime.UtcNow + accessTokenSuccess.Lifetime; authorizationState.AccessTokenIssueDateUtc = DateTime.UtcNow; - if (accessTokenSuccess.Scope != null && accessTokenSuccess.Scope != authorizationState.Scope) { - if (authorizationState.Scope != null) { - Logger.OAuth.InfoFormat( - "Requested scope of \"{0}\" changed to \"{1}\" by authorization server.", - authorizationState.Scope, - accessTokenSuccess.Scope); - } + // The authorization server MAY choose to renew the refresh token itself. + if (accessTokenSuccess.RefreshToken != null) { + authorizationState.RefreshToken = accessTokenSuccess.RefreshToken; + } + + // An included scope parameter in the response only describes the access token's scope. + // Don't update the whole authorization state object with that scope because that represents + // the refresh token's original scope. + if ((authorizationState.Scope == null || authorizationState.Scope.Count == 0) && accessTokenSuccess.Scope != null) { authorizationState.Scope.ResetContents(accessTokenSuccess.Scope); } diff --git a/src/DotNetOpenAuth/OAuth2/OAuth 2 client facades.cd b/src/DotNetOpenAuth/OAuth2/OAuth 2 client facades.cd index c18c5e8..97bf2eb 100644 --- a/src/DotNetOpenAuth/OAuth2/OAuth 2 client facades.cd +++ b/src/DotNetOpenAuth/OAuth2/OAuth 2 client facades.cd @@ -3,7 +3,7 @@ <Class Name="DotNetOpenAuth.OAuth2.ClientBase"> <Position X="0.5" Y="0.5" Width="3.5" /> <TypeIdentifier> - <HashCode>AAACAAAwQEAAAAAAAgAAAAAAAAwAAAAAAAAAAAAAAAA=</HashCode> + <HashCode>AAACAAAwAEAAAAAAAgAAAIEAAAwAAAAAAAAAAAAAAAA=</HashCode> <FileName>OAuth2\ClientBase.cs</FileName> </TypeIdentifier> </Class> @@ -18,10 +18,8 @@ <Position X="4.5" Y="3" Width="3.5" /> <InheritanceLine Type="DotNetOpenAuth.OAuth2.ClientBase" FixedFromPoint="true"> <Path> - <Point X="4" Y="3" /> - <Point X="4.24" Y="3" /> - <Point X="4.24" Y="3.809" /> - <Point X="4.5" Y="3.809" /> + <Point X="4" Y="3.166" /> + <Point X="4.5" Y="3.166" /> </Path> </InheritanceLine> <TypeIdentifier> diff --git a/src/DotNetOpenAuth/OAuth2/WebServerClient.cs b/src/DotNetOpenAuth/OAuth2/WebServerClient.cs index fb084d1..a6fae13 100644 --- a/src/DotNetOpenAuth/OAuth2/WebServerClient.cs +++ b/src/DotNetOpenAuth/OAuth2/WebServerClient.cs @@ -115,7 +115,7 @@ namespace DotNetOpenAuth.OAuth2 { var failure = response as EndUserAuthorizationFailedResponse; ErrorUtilities.VerifyProtocol(success != null || failure != null, MessagingStrings.UnexpectedMessageReceivedOfMany); if (success != null) { - UpdateAuthorizationWithResponse(authorizationState, success); + this.UpdateAuthorizationWithResponse(authorizationState, success); } else { // failure Logger.OAuth.Info("User refused to grant the requested authorization at the Authorization Server."); authorizationState.Delete(); |