/// <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> /// <param name="cancellationToken">The cancellation 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 async Task<IAuthorizationState> GetScopedAccessTokenAsync(string refreshToken, HashSet<string> scope, CancellationToken cancellationToken) { Requires.NotNullOrEmpty(refreshToken, "refreshToken"); Requires.NotNull(scope, "scope"); var request = new AccessTokenRefreshRequestC(this.AuthorizationServer) { ClientIdentifier = this.ClientIdentifier, RefreshToken = refreshToken, }; this.ApplyClientCredential(request); var response = await this.Channel.RequestAsync<AccessTokenSuccessResponse>(request, cancellationToken); var authorization = new AuthorizationState(); UpdateAuthorizationWithResponse(authorization, response); return authorization; }
/// <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) { Requires.NotNullOrEmpty(refreshToken, "refreshToken"); Requires.NotNull(scope, "scope"); Contract.Ensures(Contract.Result<IAuthorizationState>() != null); var request = new AccessTokenRefreshRequestC(this.AuthorizationServer) { ClientIdentifier = this.ClientIdentifier, ClientSecret = this.ClientSecret, RefreshToken = refreshToken, }; var response = this.Channel.Request<AccessTokenSuccessResponse>(request); var authorization = new AuthorizationState(); UpdateAuthorizationWithResponse(authorization, response); return authorization; }
/// <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. /// 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> /// <param name="cancellationToken">The cancellation token.</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> /// <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 async Task<bool> RefreshAuthorizationAsync(IAuthorizationState authorization, TimeSpan? skipIfUsefulLifeExceeds = null, CancellationToken cancellationToken = default(CancellationToken)) { Requires.NotNull(authorization, "authorization"); Requires.That(!string.IsNullOrEmpty(authorization.RefreshToken), "authorization", "RefreshToken required."); if (skipIfUsefulLifeExceeds.HasValue && authorization.AccessTokenExpirationUtc.HasValue) { TimeSpan usefulLifeRemaining = authorization.AccessTokenExpirationUtc.Value - DateTime.UtcNow; if (usefulLifeRemaining > skipIfUsefulLifeExceeds.Value) { // There is useful life remaining in the access token. Don't refresh. Logger.OAuth.DebugFormat("Skipping token refresh step because access token's remaining life is {0}, which exceeds {1}.", usefulLifeRemaining, skipIfUsefulLifeExceeds.Value); return false; } } var request = new AccessTokenRefreshRequestC(this.AuthorizationServer) { ClientIdentifier = this.ClientIdentifier, RefreshToken = authorization.RefreshToken, }; this.ApplyClientCredential(request); var response = await this.Channel.RequestAsync<AccessTokenSuccessResponse>(request, cancellationToken); UpdateAuthorizationWithResponse(authorization, response); return true; }
/// <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. /// 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> /// <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) { Requires.NotNull(authorization, "authorization"); Requires.True(!string.IsNullOrEmpty(authorization.RefreshToken), "authorization"); if (skipIfUsefulLifeExceeds.HasValue && authorization.AccessTokenExpirationUtc.HasValue) { TimeSpan usefulLifeRemaining = authorization.AccessTokenExpirationUtc.Value - DateTime.UtcNow; if (usefulLifeRemaining > skipIfUsefulLifeExceeds.Value) { // There is useful life remaining in the access token. Don't refresh. Logger.OAuth.DebugFormat("Skipping token refresh step because access token's remaining life is {0}, which exceeds {1}.", usefulLifeRemaining, skipIfUsefulLifeExceeds.Value); return false; } } var request = new AccessTokenRefreshRequestC(this.AuthorizationServer) { ClientIdentifier = this.ClientIdentifier, ClientSecret = this.ClientSecret, RefreshToken = authorization.RefreshToken, }; var response = this.Channel.Request<AccessTokenSuccessResponse>(request); UpdateAuthorizationWithResponse(authorization, response); return true; }