/// <summary>
/// Gets the access token by either requesting a new token or by using the refresh token of an already existing token.
/// </summary>
private async Task<string> GetAccessTokenAsync(CancellationToken ct)
{
if (_tokenResponse == null)
{
// Creates a new token response
_tokenResponse = await RequestTokenAsync(ct).ConfigureAwait(false);
}
else
{
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
// Parses JWT access token
var jwtSecurityToken = jwtSecurityTokenHandler.ReadToken(_tokenResponse.AccessToken) as JwtSecurityToken;
// The access token might be valid now, but expired the very next millisecond.
// Thus, add a reasonable reserve in minutes for the validity time comparison below.
var comparisionCorrectionInMinutes = 1;
// Compares the access token life time with the current time, modified by the comparison correction value.
if (jwtSecurityToken.ValidTo < DateTime.UtcNow.AddMinutes(comparisionCorrectionInMinutes))
{
// Updates the existing token response
_tokenResponse = await RefreshTokenAsync(_tokenResponse.RefreshToken, ct).ConfigureAwait(false);
}
}
return _tokenResponse.AccessToken;
}
/// <summary>
/// Gets an updated token response by using a refresh token.
/// </summary>
private async Task<TokenResponse> RefreshTokenAsync(string refreshToken, CancellationToken ct)
{
using (var client = new HttpClient())
{
var discoveryResponse = await GetDiscoveryDocumentAsync(ct).ConfigureAwait(false);
var tokenResponse = await client.RequestTokenAsync(new TokenRequest
{
ClientId = "[ClientId]",
ClientSecret = "[ClientSecret]",
Address = discoveryResponse.TokenEndpoint,
ClientCredentialStyle = ClientCredentialStyle.AuthorizationHeader,
GrantType = OidcConstants.GrantTypes.RefreshToken,
Parameters =
{
{ "refresh_token", refreshToken },
{ "scope", string.Join(" ", _scopes) }
}
});
if (tokenResponse.IsError)
throw new Exception(tokenResponse.Error);
return tokenResponse;
}
}
|