diff --git a/modules/openapi-generator/src/main/resources/csharp/auth/OAuthAuthenticator.mustache b/modules/openapi-generator/src/main/resources/csharp/auth/OAuthAuthenticator.mustache index d71f262a810..2e5a0521281 100644 --- a/modules/openapi-generator/src/main/resources/csharp/auth/OAuthAuthenticator.mustache +++ b/modules/openapi-generator/src/main/resources/csharp/auth/OAuthAuthenticator.mustache @@ -11,8 +11,22 @@ namespace {{packageName}}.Client.Auth /// /// An authenticator for OAuth2 authentication flows /// - public class OAuthAuthenticator : AuthenticatorBase + public class OAuthAuthenticator : IAuthenticator { + private TokenResponse{{nrt?}} _token; + + public string{{nrt?}} Token + { + get + { + if (_token == null) return null; + if (_token.ExpiresIn == null) return _token.AccessToken; + if (_token.ExpiresAt < DateTime.Now) return null; + + return _token.AccessToken; + } + } + readonly string _tokenUrl; readonly string _clientId; readonly string _clientSecret; @@ -31,7 +45,7 @@ namespace {{packageName}}.Client.Auth string{{nrt?}} scope, OAuthFlow? flow, JsonSerializerSettings serializerSettings, - IReadableConfiguration configuration) : base("") + IReadableConfiguration configuration) { _tokenUrl = tokenUrl; _clientId = clientId; @@ -64,10 +78,10 @@ namespace {{packageName}}.Client.Auth /// /// Access token to create a parameter from. /// An authentication parameter. - protected override async ValueTask GetAuthenticationParameter(string accessToken) + protected async ValueTask GetAuthenticationParameter() { var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token; - return new HeaderParameter(KnownHeaders.Authorization, token); + return new HeaderParameter(KnownHeaders.Authorization, token!); } /// @@ -76,31 +90,39 @@ namespace {{packageName}}.Client.Auth /// An authentication token. async Task GetToken() { - var client = new RestClient(_tokenUrl, - configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(_serializerSettings, _configuration))); - - var request = new RestRequest() - .AddParameter("grant_type", _grantType) - .AddParameter("client_id", _clientId) - .AddParameter("client_secret", _clientSecret); + var client = new RestClient(_tokenUrl, configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(_serializerSettings, _configuration))); + var request = new RestRequest(); + if (!string.IsNullOrWhiteSpace(_token?.RefreshToken)) + { + request.AddParameter("grant_type", "refresh_token") + .AddParameter("refresh_token", _token!.RefreshToken); + } + else + { + request + .AddParameter("grant_type", _grantType) + .AddParameter("client_id", _clientId) + .AddParameter("client_secret", _clientSecret); + } if (!string.IsNullOrEmpty(_scope)) { request.AddParameter("scope", _scope); } - - var response = await client.PostAsync(request).ConfigureAwait(false); - + _token = await client.PostAsync(request).ConfigureAwait(false); // RFC6749 - token_type is case insensitive. // RFC6750 - In Authorization header Bearer should be capitalized. // Fix the capitalization irrespective of token_type casing. - switch (response.TokenType?.ToLower()) + switch (_token?.TokenType?.ToLower()) { case "bearer": - return $"Bearer {response.AccessToken}"; + return $"Bearer {_token.AccessToken}"; default: - return $"{response.TokenType} {response.AccessToken}"; + return $"{_token?.TokenType} {_token?.AccessToken}"; } } + + public async ValueTask Authenticate(IRestClient client, RestRequest request) + => request.AddOrUpdateParameter(await GetAuthenticationParameter().ConfigureAwait(false)); } } diff --git a/modules/openapi-generator/src/main/resources/csharp/auth/TokenResponse.mustache b/modules/openapi-generator/src/main/resources/csharp/auth/TokenResponse.mustache index f118b97a9dd..443479677a9 100644 --- a/modules/openapi-generator/src/main/resources/csharp/auth/TokenResponse.mustache +++ b/modules/openapi-generator/src/main/resources/csharp/auth/TokenResponse.mustache @@ -10,5 +10,14 @@ namespace {{packageName}}.Client.Auth public string TokenType { get; set; } [JsonProperty("access_token")] public string AccessToken { get; set; } + [JsonProperty("expires_in")] + public int? ExpiresIn { get; set; } + [JsonProperty("created")] + public DateTime Created { get; set; } + + [JsonProperty("refresh_token")] + public string{{nrt?}} RefreshToken { get; set; } + + public DateTime? ExpiresAt => ExpiresIn == null ? null : Created.AddSeconds(ExpiresIn.Value); } } \ No newline at end of file