Merge branch 'AddRefreshToCsharpTemplate' of https://github.com/BryanAldrich/openapi-generator into BryanAldrich-AddRefreshToCsharpTemplate3

This commit is contained in:
William Cheng 2024-12-07 13:21:38 +08:00
commit 48ef1e6cf1
16 changed files with 456 additions and 136 deletions

View File

@ -11,8 +11,25 @@ namespace {{packageName}}.Client.Auth
/// <summary> /// <summary>
/// An authenticator for OAuth2 authentication flows /// An authenticator for OAuth2 authentication flows
/// </summary> /// </summary>
public class OAuthAuthenticator : AuthenticatorBase public class OAuthAuthenticator : IAuthenticator
{ {
private TokenResponse{{nrt?}} _token;
/// <summary>
/// Returns the current authentication token. Can return null if there is no authentication token, or it has expired.
/// </summary>
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 _tokenUrl;
readonly string _clientId; readonly string _clientId;
readonly string _clientSecret; readonly string _clientSecret;
@ -31,7 +48,7 @@ namespace {{packageName}}.Client.Auth
string{{nrt?}} scope, string{{nrt?}} scope,
OAuthFlow? flow, OAuthFlow? flow,
JsonSerializerSettings serializerSettings, JsonSerializerSettings serializerSettings,
IReadableConfiguration configuration) : base("") IReadableConfiguration configuration)
{ {
_tokenUrl = tokenUrl; _tokenUrl = tokenUrl;
_clientId = clientId; _clientId = clientId;
@ -62,9 +79,8 @@ namespace {{packageName}}.Client.Auth
/// <summary> /// <summary>
/// Creates an authentication parameter from an access token. /// Creates an authentication parameter from an access token.
/// </summary> /// </summary>
/// <param name="accessToken">Access token to create a parameter from.</param>
/// <returns>An authentication parameter.</returns> /// <returns>An authentication parameter.</returns>
protected override async ValueTask<Parameter> GetAuthenticationParameter(string accessToken) protected async ValueTask<Parameter> GetAuthenticationParameter()
{ {
var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token; var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token;
return new HeaderParameter(KnownHeaders.Authorization, token); return new HeaderParameter(KnownHeaders.Authorization, token);
@ -76,31 +92,45 @@ namespace {{packageName}}.Client.Auth
/// <returns>An authentication token.</returns> /// <returns>An authentication token.</returns>
async Task<string> GetToken() async Task<string> GetToken()
{ {
var client = new RestClient(_tokenUrl, var client = new RestClient(_tokenUrl, configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(_serializerSettings, _configuration)));
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 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)) if (!string.IsNullOrEmpty(_scope))
{ {
request.AddParameter("scope", _scope); request.AddParameter("scope", _scope);
} }
_token = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
var response = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
// RFC6749 - token_type is case insensitive. // RFC6749 - token_type is case insensitive.
// RFC6750 - In Authorization header Bearer should be capitalized. // RFC6750 - In Authorization header Bearer should be capitalized.
// Fix the capitalization irrespective of token_type casing. // Fix the capitalization irrespective of token_type casing.
switch (response.TokenType?.ToLower()) switch (_token?.TokenType?.ToLower())
{ {
case "bearer": case "bearer":
return $"Bearer {response.AccessToken}"; return $"Bearer {_token.AccessToken}";
default: default:
return $"{response.TokenType} {response.AccessToken}"; return $"{_token?.TokenType} {_token?.AccessToken}";
} }
} }
/// <summary>
/// Retrieves the authentication token (creating a new one if necessary) and adds it to the current request
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <returns></returns>
public async ValueTask Authenticate(IRestClient client, RestRequest request)
=> request.AddOrUpdateParameter(await GetAuthenticationParameter().ConfigureAwait(false));
} }
} }

View File

@ -1,5 +1,6 @@
{{>partial_header}} {{>partial_header}}
using System;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace {{packageName}}.Client.Auth namespace {{packageName}}.Client.Auth
@ -10,5 +11,14 @@ namespace {{packageName}}.Client.Auth
public string TokenType { get; set; } public string TokenType { get; set; }
[JsonProperty("access_token")] [JsonProperty("access_token")]
public string AccessToken { get; set; } 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);
} }
} }

View File

@ -19,8 +19,25 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// An authenticator for OAuth2 authentication flows /// An authenticator for OAuth2 authentication flows
/// </summary> /// </summary>
public class OAuthAuthenticator : AuthenticatorBase public class OAuthAuthenticator : IAuthenticator
{ {
private TokenResponse _token;
/// <summary>
/// Returns the current authentication token. Can return null if there is no authentication token, or it has expired.
/// </summary>
public string 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 _tokenUrl;
readonly string _clientId; readonly string _clientId;
readonly string _clientSecret; readonly string _clientSecret;
@ -39,7 +56,7 @@ namespace Org.OpenAPITools.Client.Auth
string scope, string scope,
OAuthFlow? flow, OAuthFlow? flow,
JsonSerializerSettings serializerSettings, JsonSerializerSettings serializerSettings,
IReadableConfiguration configuration) : base("") IReadableConfiguration configuration)
{ {
_tokenUrl = tokenUrl; _tokenUrl = tokenUrl;
_clientId = clientId; _clientId = clientId;
@ -70,9 +87,8 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// Creates an authentication parameter from an access token. /// Creates an authentication parameter from an access token.
/// </summary> /// </summary>
/// <param name="accessToken">Access token to create a parameter from.</param>
/// <returns>An authentication parameter.</returns> /// <returns>An authentication parameter.</returns>
protected override async ValueTask<Parameter> GetAuthenticationParameter(string accessToken) protected async ValueTask<Parameter> GetAuthenticationParameter()
{ {
var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token; var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token;
return new HeaderParameter(KnownHeaders.Authorization, token); return new HeaderParameter(KnownHeaders.Authorization, token);
@ -84,31 +100,45 @@ namespace Org.OpenAPITools.Client.Auth
/// <returns>An authentication token.</returns> /// <returns>An authentication token.</returns>
async Task<string> GetToken() async Task<string> GetToken()
{ {
var client = new RestClient(_tokenUrl, var client = new RestClient(_tokenUrl, configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(_serializerSettings, _configuration)));
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 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)) if (!string.IsNullOrEmpty(_scope))
{ {
request.AddParameter("scope", _scope); request.AddParameter("scope", _scope);
} }
_token = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
var response = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
// RFC6749 - token_type is case insensitive. // RFC6749 - token_type is case insensitive.
// RFC6750 - In Authorization header Bearer should be capitalized. // RFC6750 - In Authorization header Bearer should be capitalized.
// Fix the capitalization irrespective of token_type casing. // Fix the capitalization irrespective of token_type casing.
switch (response.TokenType?.ToLower()) switch (_token?.TokenType?.ToLower())
{ {
case "bearer": case "bearer":
return $"Bearer {response.AccessToken}"; return $"Bearer {_token.AccessToken}";
default: default:
return $"{response.TokenType} {response.AccessToken}"; return $"{_token?.TokenType} {_token?.AccessToken}";
} }
} }
/// <summary>
/// Retrieves the authentication token (creating a new one if necessary) and adds it to the current request
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <returns></returns>
public async ValueTask Authenticate(IRestClient client, RestRequest request)
=> request.AddOrUpdateParameter(await GetAuthenticationParameter().ConfigureAwait(false));
} }
} }

View File

@ -8,6 +8,7 @@
*/ */
using System;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Org.OpenAPITools.Client.Auth namespace Org.OpenAPITools.Client.Auth
@ -18,5 +19,14 @@ namespace Org.OpenAPITools.Client.Auth
public string TokenType { get; set; } public string TokenType { get; set; }
[JsonProperty("access_token")] [JsonProperty("access_token")]
public string AccessToken { get; set; } 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 RefreshToken { get; set; }
public DateTime? ExpiresAt => ExpiresIn == null ? null : Created?.AddSeconds(ExpiresIn.Value);
} }
} }

View File

@ -19,8 +19,25 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// An authenticator for OAuth2 authentication flows /// An authenticator for OAuth2 authentication flows
/// </summary> /// </summary>
public class OAuthAuthenticator : AuthenticatorBase public class OAuthAuthenticator : IAuthenticator
{ {
private TokenResponse _token;
/// <summary>
/// Returns the current authentication token. Can return null if there is no authentication token, or it has expired.
/// </summary>
public string 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 _tokenUrl;
readonly string _clientId; readonly string _clientId;
readonly string _clientSecret; readonly string _clientSecret;
@ -39,7 +56,7 @@ namespace Org.OpenAPITools.Client.Auth
string scope, string scope,
OAuthFlow? flow, OAuthFlow? flow,
JsonSerializerSettings serializerSettings, JsonSerializerSettings serializerSettings,
IReadableConfiguration configuration) : base("") IReadableConfiguration configuration)
{ {
_tokenUrl = tokenUrl; _tokenUrl = tokenUrl;
_clientId = clientId; _clientId = clientId;
@ -70,9 +87,8 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// Creates an authentication parameter from an access token. /// Creates an authentication parameter from an access token.
/// </summary> /// </summary>
/// <param name="accessToken">Access token to create a parameter from.</param>
/// <returns>An authentication parameter.</returns> /// <returns>An authentication parameter.</returns>
protected override async ValueTask<Parameter> GetAuthenticationParameter(string accessToken) protected async ValueTask<Parameter> GetAuthenticationParameter()
{ {
var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token; var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token;
return new HeaderParameter(KnownHeaders.Authorization, token); return new HeaderParameter(KnownHeaders.Authorization, token);
@ -84,31 +100,45 @@ namespace Org.OpenAPITools.Client.Auth
/// <returns>An authentication token.</returns> /// <returns>An authentication token.</returns>
async Task<string> GetToken() async Task<string> GetToken()
{ {
var client = new RestClient(_tokenUrl, var client = new RestClient(_tokenUrl, configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(_serializerSettings, _configuration)));
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 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)) if (!string.IsNullOrEmpty(_scope))
{ {
request.AddParameter("scope", _scope); request.AddParameter("scope", _scope);
} }
_token = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
var response = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
// RFC6749 - token_type is case insensitive. // RFC6749 - token_type is case insensitive.
// RFC6750 - In Authorization header Bearer should be capitalized. // RFC6750 - In Authorization header Bearer should be capitalized.
// Fix the capitalization irrespective of token_type casing. // Fix the capitalization irrespective of token_type casing.
switch (response.TokenType?.ToLower()) switch (_token?.TokenType?.ToLower())
{ {
case "bearer": case "bearer":
return $"Bearer {response.AccessToken}"; return $"Bearer {_token.AccessToken}";
default: default:
return $"{response.TokenType} {response.AccessToken}"; return $"{_token?.TokenType} {_token?.AccessToken}";
} }
} }
/// <summary>
/// Retrieves the authentication token (creating a new one if necessary) and adds it to the current request
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <returns></returns>
public async ValueTask Authenticate(IRestClient client, RestRequest request)
=> request.AddOrUpdateParameter(await GetAuthenticationParameter().ConfigureAwait(false));
} }
} }

View File

@ -8,6 +8,7 @@
*/ */
using System;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Org.OpenAPITools.Client.Auth namespace Org.OpenAPITools.Client.Auth
@ -18,5 +19,14 @@ namespace Org.OpenAPITools.Client.Auth
public string TokenType { get; set; } public string TokenType { get; set; }
[JsonProperty("access_token")] [JsonProperty("access_token")]
public string AccessToken { get; set; } 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 RefreshToken { get; set; }
public DateTime? ExpiresAt => ExpiresIn == null ? null : Created?.AddSeconds(ExpiresIn.Value);
} }
} }

View File

@ -19,8 +19,25 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// An authenticator for OAuth2 authentication flows /// An authenticator for OAuth2 authentication flows
/// </summary> /// </summary>
public class OAuthAuthenticator : AuthenticatorBase public class OAuthAuthenticator : IAuthenticator
{ {
private TokenResponse _token;
/// <summary>
/// Returns the current authentication token. Can return null if there is no authentication token, or it has expired.
/// </summary>
public string 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 _tokenUrl;
readonly string _clientId; readonly string _clientId;
readonly string _clientSecret; readonly string _clientSecret;
@ -39,7 +56,7 @@ namespace Org.OpenAPITools.Client.Auth
string scope, string scope,
OAuthFlow? flow, OAuthFlow? flow,
JsonSerializerSettings serializerSettings, JsonSerializerSettings serializerSettings,
IReadableConfiguration configuration) : base("") IReadableConfiguration configuration)
{ {
_tokenUrl = tokenUrl; _tokenUrl = tokenUrl;
_clientId = clientId; _clientId = clientId;
@ -70,9 +87,8 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// Creates an authentication parameter from an access token. /// Creates an authentication parameter from an access token.
/// </summary> /// </summary>
/// <param name="accessToken">Access token to create a parameter from.</param>
/// <returns>An authentication parameter.</returns> /// <returns>An authentication parameter.</returns>
protected override async ValueTask<Parameter> GetAuthenticationParameter(string accessToken) protected async ValueTask<Parameter> GetAuthenticationParameter()
{ {
var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token; var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token;
return new HeaderParameter(KnownHeaders.Authorization, token); return new HeaderParameter(KnownHeaders.Authorization, token);
@ -84,31 +100,45 @@ namespace Org.OpenAPITools.Client.Auth
/// <returns>An authentication token.</returns> /// <returns>An authentication token.</returns>
async Task<string> GetToken() async Task<string> GetToken()
{ {
var client = new RestClient(_tokenUrl, var client = new RestClient(_tokenUrl, configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(_serializerSettings, _configuration)));
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 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)) if (!string.IsNullOrEmpty(_scope))
{ {
request.AddParameter("scope", _scope); request.AddParameter("scope", _scope);
} }
_token = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
var response = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
// RFC6749 - token_type is case insensitive. // RFC6749 - token_type is case insensitive.
// RFC6750 - In Authorization header Bearer should be capitalized. // RFC6750 - In Authorization header Bearer should be capitalized.
// Fix the capitalization irrespective of token_type casing. // Fix the capitalization irrespective of token_type casing.
switch (response.TokenType?.ToLower()) switch (_token?.TokenType?.ToLower())
{ {
case "bearer": case "bearer":
return $"Bearer {response.AccessToken}"; return $"Bearer {_token.AccessToken}";
default: default:
return $"{response.TokenType} {response.AccessToken}"; return $"{_token?.TokenType} {_token?.AccessToken}";
} }
} }
/// <summary>
/// Retrieves the authentication token (creating a new one if necessary) and adds it to the current request
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <returns></returns>
public async ValueTask Authenticate(IRestClient client, RestRequest request)
=> request.AddOrUpdateParameter(await GetAuthenticationParameter().ConfigureAwait(false));
} }
} }

View File

@ -8,6 +8,7 @@
*/ */
using System;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Org.OpenAPITools.Client.Auth namespace Org.OpenAPITools.Client.Auth
@ -18,5 +19,14 @@ namespace Org.OpenAPITools.Client.Auth
public string TokenType { get; set; } public string TokenType { get; set; }
[JsonProperty("access_token")] [JsonProperty("access_token")]
public string AccessToken { get; set; } 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 RefreshToken { get; set; }
public DateTime? ExpiresAt => ExpiresIn == null ? null : Created?.AddSeconds(ExpiresIn.Value);
} }
} }

View File

@ -19,8 +19,25 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// An authenticator for OAuth2 authentication flows /// An authenticator for OAuth2 authentication flows
/// </summary> /// </summary>
public class OAuthAuthenticator : AuthenticatorBase public class OAuthAuthenticator : IAuthenticator
{ {
private TokenResponse? _token;
/// <summary>
/// Returns the current authentication token. Can return null if there is no authentication token, or it has expired.
/// </summary>
public string? 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 _tokenUrl;
readonly string _clientId; readonly string _clientId;
readonly string _clientSecret; readonly string _clientSecret;
@ -39,7 +56,7 @@ namespace Org.OpenAPITools.Client.Auth
string? scope, string? scope,
OAuthFlow? flow, OAuthFlow? flow,
JsonSerializerSettings serializerSettings, JsonSerializerSettings serializerSettings,
IReadableConfiguration configuration) : base("") IReadableConfiguration configuration)
{ {
_tokenUrl = tokenUrl; _tokenUrl = tokenUrl;
_clientId = clientId; _clientId = clientId;
@ -70,9 +87,8 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// Creates an authentication parameter from an access token. /// Creates an authentication parameter from an access token.
/// </summary> /// </summary>
/// <param name="accessToken">Access token to create a parameter from.</param>
/// <returns>An authentication parameter.</returns> /// <returns>An authentication parameter.</returns>
protected override async ValueTask<Parameter> GetAuthenticationParameter(string accessToken) protected async ValueTask<Parameter> GetAuthenticationParameter()
{ {
var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token; var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token;
return new HeaderParameter(KnownHeaders.Authorization, token); return new HeaderParameter(KnownHeaders.Authorization, token);
@ -84,31 +100,45 @@ namespace Org.OpenAPITools.Client.Auth
/// <returns>An authentication token.</returns> /// <returns>An authentication token.</returns>
async Task<string> GetToken() async Task<string> GetToken()
{ {
var client = new RestClient(_tokenUrl, var client = new RestClient(_tokenUrl, configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(_serializerSettings, _configuration)));
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 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)) if (!string.IsNullOrEmpty(_scope))
{ {
request.AddParameter("scope", _scope); request.AddParameter("scope", _scope);
} }
_token = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
var response = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
// RFC6749 - token_type is case insensitive. // RFC6749 - token_type is case insensitive.
// RFC6750 - In Authorization header Bearer should be capitalized. // RFC6750 - In Authorization header Bearer should be capitalized.
// Fix the capitalization irrespective of token_type casing. // Fix the capitalization irrespective of token_type casing.
switch (response.TokenType?.ToLower()) switch (_token?.TokenType?.ToLower())
{ {
case "bearer": case "bearer":
return $"Bearer {response.AccessToken}"; return $"Bearer {_token.AccessToken}";
default: default:
return $"{response.TokenType} {response.AccessToken}"; return $"{_token?.TokenType} {_token?.AccessToken}";
} }
} }
/// <summary>
/// Retrieves the authentication token (creating a new one if necessary) and adds it to the current request
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <returns></returns>
public async ValueTask Authenticate(IRestClient client, RestRequest request)
=> request.AddOrUpdateParameter(await GetAuthenticationParameter().ConfigureAwait(false));
} }
} }

View File

@ -8,6 +8,7 @@
*/ */
using System;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Org.OpenAPITools.Client.Auth namespace Org.OpenAPITools.Client.Auth
@ -18,5 +19,14 @@ namespace Org.OpenAPITools.Client.Auth
public string TokenType { get; set; } public string TokenType { get; set; }
[JsonProperty("access_token")] [JsonProperty("access_token")]
public string AccessToken { get; set; } 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? RefreshToken { get; set; }
public DateTime? ExpiresAt => ExpiresIn == null ? null : Created?.AddSeconds(ExpiresIn.Value);
} }
} }

View File

@ -19,8 +19,25 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// An authenticator for OAuth2 authentication flows /// An authenticator for OAuth2 authentication flows
/// </summary> /// </summary>
public class OAuthAuthenticator : AuthenticatorBase public class OAuthAuthenticator : IAuthenticator
{ {
private TokenResponse? _token;
/// <summary>
/// Returns the current authentication token. Can return null if there is no authentication token, or it has expired.
/// </summary>
public string? 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 _tokenUrl;
readonly string _clientId; readonly string _clientId;
readonly string _clientSecret; readonly string _clientSecret;
@ -39,7 +56,7 @@ namespace Org.OpenAPITools.Client.Auth
string? scope, string? scope,
OAuthFlow? flow, OAuthFlow? flow,
JsonSerializerSettings serializerSettings, JsonSerializerSettings serializerSettings,
IReadableConfiguration configuration) : base("") IReadableConfiguration configuration)
{ {
_tokenUrl = tokenUrl; _tokenUrl = tokenUrl;
_clientId = clientId; _clientId = clientId;
@ -70,9 +87,8 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// Creates an authentication parameter from an access token. /// Creates an authentication parameter from an access token.
/// </summary> /// </summary>
/// <param name="accessToken">Access token to create a parameter from.</param>
/// <returns>An authentication parameter.</returns> /// <returns>An authentication parameter.</returns>
protected override async ValueTask<Parameter> GetAuthenticationParameter(string accessToken) protected async ValueTask<Parameter> GetAuthenticationParameter()
{ {
var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token; var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token;
return new HeaderParameter(KnownHeaders.Authorization, token); return new HeaderParameter(KnownHeaders.Authorization, token);
@ -84,31 +100,45 @@ namespace Org.OpenAPITools.Client.Auth
/// <returns>An authentication token.</returns> /// <returns>An authentication token.</returns>
async Task<string> GetToken() async Task<string> GetToken()
{ {
var client = new RestClient(_tokenUrl, var client = new RestClient(_tokenUrl, configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(_serializerSettings, _configuration)));
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 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)) if (!string.IsNullOrEmpty(_scope))
{ {
request.AddParameter("scope", _scope); request.AddParameter("scope", _scope);
} }
_token = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
var response = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
// RFC6749 - token_type is case insensitive. // RFC6749 - token_type is case insensitive.
// RFC6750 - In Authorization header Bearer should be capitalized. // RFC6750 - In Authorization header Bearer should be capitalized.
// Fix the capitalization irrespective of token_type casing. // Fix the capitalization irrespective of token_type casing.
switch (response.TokenType?.ToLower()) switch (_token?.TokenType?.ToLower())
{ {
case "bearer": case "bearer":
return $"Bearer {response.AccessToken}"; return $"Bearer {_token.AccessToken}";
default: default:
return $"{response.TokenType} {response.AccessToken}"; return $"{_token?.TokenType} {_token?.AccessToken}";
} }
} }
/// <summary>
/// Retrieves the authentication token (creating a new one if necessary) and adds it to the current request
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <returns></returns>
public async ValueTask Authenticate(IRestClient client, RestRequest request)
=> request.AddOrUpdateParameter(await GetAuthenticationParameter().ConfigureAwait(false));
} }
} }

View File

@ -8,6 +8,7 @@
*/ */
using System;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Org.OpenAPITools.Client.Auth namespace Org.OpenAPITools.Client.Auth
@ -18,5 +19,14 @@ namespace Org.OpenAPITools.Client.Auth
public string TokenType { get; set; } public string TokenType { get; set; }
[JsonProperty("access_token")] [JsonProperty("access_token")]
public string AccessToken { get; set; } 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? RefreshToken { get; set; }
public DateTime? ExpiresAt => ExpiresIn == null ? null : Created?.AddSeconds(ExpiresIn.Value);
} }
} }

View File

@ -19,8 +19,25 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// An authenticator for OAuth2 authentication flows /// An authenticator for OAuth2 authentication flows
/// </summary> /// </summary>
public class OAuthAuthenticator : AuthenticatorBase public class OAuthAuthenticator : IAuthenticator
{ {
private TokenResponse _token;
/// <summary>
/// Returns the current authentication token. Can return null if there is no authentication token, or it has expired.
/// </summary>
public string 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 _tokenUrl;
readonly string _clientId; readonly string _clientId;
readonly string _clientSecret; readonly string _clientSecret;
@ -39,7 +56,7 @@ namespace Org.OpenAPITools.Client.Auth
string scope, string scope,
OAuthFlow? flow, OAuthFlow? flow,
JsonSerializerSettings serializerSettings, JsonSerializerSettings serializerSettings,
IReadableConfiguration configuration) : base("") IReadableConfiguration configuration)
{ {
_tokenUrl = tokenUrl; _tokenUrl = tokenUrl;
_clientId = clientId; _clientId = clientId;
@ -70,9 +87,8 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// Creates an authentication parameter from an access token. /// Creates an authentication parameter from an access token.
/// </summary> /// </summary>
/// <param name="accessToken">Access token to create a parameter from.</param>
/// <returns>An authentication parameter.</returns> /// <returns>An authentication parameter.</returns>
protected override async ValueTask<Parameter> GetAuthenticationParameter(string accessToken) protected async ValueTask<Parameter> GetAuthenticationParameter()
{ {
var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token; var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token;
return new HeaderParameter(KnownHeaders.Authorization, token); return new HeaderParameter(KnownHeaders.Authorization, token);
@ -84,31 +100,45 @@ namespace Org.OpenAPITools.Client.Auth
/// <returns>An authentication token.</returns> /// <returns>An authentication token.</returns>
async Task<string> GetToken() async Task<string> GetToken()
{ {
var client = new RestClient(_tokenUrl, var client = new RestClient(_tokenUrl, configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(_serializerSettings, _configuration)));
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 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)) if (!string.IsNullOrEmpty(_scope))
{ {
request.AddParameter("scope", _scope); request.AddParameter("scope", _scope);
} }
_token = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
var response = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
// RFC6749 - token_type is case insensitive. // RFC6749 - token_type is case insensitive.
// RFC6750 - In Authorization header Bearer should be capitalized. // RFC6750 - In Authorization header Bearer should be capitalized.
// Fix the capitalization irrespective of token_type casing. // Fix the capitalization irrespective of token_type casing.
switch (response.TokenType?.ToLower()) switch (_token?.TokenType?.ToLower())
{ {
case "bearer": case "bearer":
return $"Bearer {response.AccessToken}"; return $"Bearer {_token.AccessToken}";
default: default:
return $"{response.TokenType} {response.AccessToken}"; return $"{_token?.TokenType} {_token?.AccessToken}";
} }
} }
/// <summary>
/// Retrieves the authentication token (creating a new one if necessary) and adds it to the current request
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <returns></returns>
public async ValueTask Authenticate(IRestClient client, RestRequest request)
=> request.AddOrUpdateParameter(await GetAuthenticationParameter().ConfigureAwait(false));
} }
} }

View File

@ -8,6 +8,7 @@
*/ */
using System;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Org.OpenAPITools.Client.Auth namespace Org.OpenAPITools.Client.Auth
@ -18,5 +19,14 @@ namespace Org.OpenAPITools.Client.Auth
public string TokenType { get; set; } public string TokenType { get; set; }
[JsonProperty("access_token")] [JsonProperty("access_token")]
public string AccessToken { get; set; } 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 RefreshToken { get; set; }
public DateTime? ExpiresAt => ExpiresIn == null ? null : Created?.AddSeconds(ExpiresIn.Value);
} }
} }

View File

@ -19,8 +19,25 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// An authenticator for OAuth2 authentication flows /// An authenticator for OAuth2 authentication flows
/// </summary> /// </summary>
public class OAuthAuthenticator : AuthenticatorBase public class OAuthAuthenticator : IAuthenticator
{ {
private TokenResponse _token;
/// <summary>
/// Returns the current authentication token. Can return null if there is no authentication token, or it has expired.
/// </summary>
public string 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 _tokenUrl;
readonly string _clientId; readonly string _clientId;
readonly string _clientSecret; readonly string _clientSecret;
@ -39,7 +56,7 @@ namespace Org.OpenAPITools.Client.Auth
string scope, string scope,
OAuthFlow? flow, OAuthFlow? flow,
JsonSerializerSettings serializerSettings, JsonSerializerSettings serializerSettings,
IReadableConfiguration configuration) : base("") IReadableConfiguration configuration)
{ {
_tokenUrl = tokenUrl; _tokenUrl = tokenUrl;
_clientId = clientId; _clientId = clientId;
@ -70,9 +87,8 @@ namespace Org.OpenAPITools.Client.Auth
/// <summary> /// <summary>
/// Creates an authentication parameter from an access token. /// Creates an authentication parameter from an access token.
/// </summary> /// </summary>
/// <param name="accessToken">Access token to create a parameter from.</param>
/// <returns>An authentication parameter.</returns> /// <returns>An authentication parameter.</returns>
protected override async ValueTask<Parameter> GetAuthenticationParameter(string accessToken) protected async ValueTask<Parameter> GetAuthenticationParameter()
{ {
var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token; var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token;
return new HeaderParameter(KnownHeaders.Authorization, token); return new HeaderParameter(KnownHeaders.Authorization, token);
@ -84,31 +100,45 @@ namespace Org.OpenAPITools.Client.Auth
/// <returns>An authentication token.</returns> /// <returns>An authentication token.</returns>
async Task<string> GetToken() async Task<string> GetToken()
{ {
var client = new RestClient(_tokenUrl, var client = new RestClient(_tokenUrl, configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(_serializerSettings, _configuration)));
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 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)) if (!string.IsNullOrEmpty(_scope))
{ {
request.AddParameter("scope", _scope); request.AddParameter("scope", _scope);
} }
_token = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
var response = await client.PostAsync<TokenResponse>(request).ConfigureAwait(false);
// RFC6749 - token_type is case insensitive. // RFC6749 - token_type is case insensitive.
// RFC6750 - In Authorization header Bearer should be capitalized. // RFC6750 - In Authorization header Bearer should be capitalized.
// Fix the capitalization irrespective of token_type casing. // Fix the capitalization irrespective of token_type casing.
switch (response.TokenType?.ToLower()) switch (_token?.TokenType?.ToLower())
{ {
case "bearer": case "bearer":
return $"Bearer {response.AccessToken}"; return $"Bearer {_token.AccessToken}";
default: default:
return $"{response.TokenType} {response.AccessToken}"; return $"{_token?.TokenType} {_token?.AccessToken}";
} }
} }
/// <summary>
/// Retrieves the authentication token (creating a new one if necessary) and adds it to the current request
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <returns></returns>
public async ValueTask Authenticate(IRestClient client, RestRequest request)
=> request.AddOrUpdateParameter(await GetAuthenticationParameter().ConfigureAwait(false));
} }
} }

View File

@ -8,6 +8,7 @@
*/ */
using System;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Org.OpenAPITools.Client.Auth namespace Org.OpenAPITools.Client.Auth
@ -18,5 +19,14 @@ namespace Org.OpenAPITools.Client.Auth
public string TokenType { get; set; } public string TokenType { get; set; }
[JsonProperty("access_token")] [JsonProperty("access_token")]
public string AccessToken { get; set; } 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 RefreshToken { get; set; }
public DateTime? ExpiresAt => ExpiresIn == null ? null : Created?.AddSeconds(ExpiresIn.Value);
} }
} }