/// <inheritdoc/> public virtual async Task <CloudStorageToken> RefreshTokenAsync(CloudStorageToken token) { if (token == null) { throw new ArgumentNullException(nameof(token)); } if (string.IsNullOrWhiteSpace(token.RefreshToken)) { throw new ArgumentNullException(string.Format("{0}.{1}", nameof(token), nameof(CloudStorageToken.RefreshToken))); } try { // Installable apps cannot keep secrets, thus the client secret is not transmitted string clientSecret = Config.ClientSecretHandling == ClientSecretHandling.SendEmptyParam ? string.Empty // Serializes as empty parameter : null; // Won't be serialized string jsonResponse = await Flurl .Request(Config.TokenServiceEndpoint) .PostUrlEncodedAsync(new { refresh_token = token.RefreshToken, client_id = Config.ClientId, client_secret = clientSecret, grant_type = "refresh_token", }) .ReceiveString(); JsonTokenExchangeResponse response = JsonConvert.DeserializeObject <JsonTokenExchangeResponse>(jsonResponse); CloudStorageToken result = new CloudStorageToken { AccessToken = response.AccessToken, RefreshToken = token.RefreshToken // keep the refresh token }; result.SetExpiryDateBySecondsFromNow(response.ExpiresIn); return(result); } catch (Exception ex) { if (await IsInvalidGrantException(ex)) { throw new RefreshTokenExpiredException(ex); } throw ConvertToCloudStorageException(ex); } }
/// <summary> /// If the OAuth2 service requires the code flow, we have to exchange the authorization /// code with an access token, which can be used to access the API of the cloud storage /// service. /// </summary> /// <param name="authorizationCode">The code form the authorization request, it can be /// found in <see cref="AuthorizationResponse.Code"/>. /// </param> /// <param name="codeVerifier">The optional code verifier.</param> /// <returns>A token object containing the access token and a refresh token.</returns> protected virtual async Task <CloudStorageToken> ExchangeCodeForTokenAsync( string authorizationCode, string codeVerifier) { if (string.IsNullOrWhiteSpace(authorizationCode)) { throw new InvalidParameterException(nameof(authorizationCode)); } try { // Installable apps cannot keep secrets, thus the client secret is not transmitted string clientSecret = Config.ClientSecretHandling == ClientSecretHandling.SendEmptyParam ? string.Empty // Serializes as empty parameter : null; // Won't be serialized string jsonResponse = await Flurl .Request(Config.TokenServiceEndpoint) .PostUrlEncodedAsync(new { code = authorizationCode, client_id = Config.ClientId, client_secret = clientSecret, redirect_uri = Config.RedirectUrl, grant_type = "authorization_code", code_verifier = codeVerifier, }) .ReceiveString(); JsonTokenExchangeResponse response = JsonConvert.DeserializeObject <JsonTokenExchangeResponse>(jsonResponse); CloudStorageToken result = new CloudStorageToken { AccessToken = response.AccessToken, RefreshToken = response.RefreshToken }; result.SetExpiryDateBySecondsFromNow(response.ExpiresIn); return(result); } catch (Exception ex) { throw ConvertToCloudStorageException(ex); } }