/// <summary> /// Checks whether the access token should be refreshed, or if it can still be used. /// </summary> /// <param name="token">The token with the expiry date.</param> /// <returns>Returns true if the token should be refreshed, otherwise false.</returns> public static bool NeedsRefresh(this CloudStorageToken token) { if (token?.RefreshToken == null) { return(false); } if (token.ExpiryDate != null) { return(token.ExpiryDate < DateTime.UtcNow); } else { return(true); } }
/// <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); } }
/// <summary> /// Call this method after deserialization, it decrypts all sensitive properties, so they /// can be used by the application. /// </summary> /// <param name="decrypt">A delegate used to do the decryption of the encrypted textes.</param> public void DecryptAfterDeserialization(Func <string, string> decrypt) { CloudStorageToken token = new CloudStorageToken { AccessToken = DecryptProperty(SerializeableAccessToken, decrypt), ExpiryDate = SerializeableExpiryDate, RefreshToken = DecryptProperty(SerializeableRefreshToken, decrypt), }; if ((token.AccessToken == null) && (token.RefreshToken == null)) { token = null; } CloudStorageId = SerializeableCloudStorageId; Token = token; Username = DecryptProperty(SerializeableUsername, decrypt); UnprotectedPassword = DecryptProperty(SerializeablePassword, decrypt); Url = SerializeableUrl; Secure = SerializeableSecure; }