Added Credentials Authenticator

This commit is contained in:
Jonas Dellinger 2020-05-14 23:26:40 +02:00
parent 9b8a4cd2c9
commit 255bbd5c2f
4 changed files with 82 additions and 9 deletions

View File

@ -16,8 +16,16 @@ namespace SpotifyAPI.Web
public OAuthClient(SpotifyClientConfig config) : base(ValidateConfig(config)) { } public OAuthClient(SpotifyClientConfig config) : base(ValidateConfig(config)) { }
public Task<TokenResponse> RequestToken(ClientCredentialsRequest request) public Task<TokenResponse> RequestToken(ClientCredentialsRequest request)
{
return RequestToken(request, API);
}
public static Task<TokenResponse> RequestToken(
ClientCredentialsRequest request, IAPIConnector apiConnector
)
{ {
Ensure.ArgumentNotNull(request, nameof(request)); Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(apiConnector, nameof(apiConnector));
var form = new List<KeyValuePair<string, string>> var form = new List<KeyValuePair<string, string>>
{ {
@ -30,7 +38,7 @@ namespace SpotifyAPI.Web
{ "Authorization", $"Basic {base64}"} { "Authorization", $"Basic {base64}"}
}; };
return API.Post<TokenResponse>(SpotifyUrls.OAuthToken, null, new FormUrlEncodedContent(form), headers); return apiConnector.Post<TokenResponse>(SpotifyUrls.OAuthToken, null, new FormUrlEncodedContent(form), headers);
} }
private static APIConnector ValidateConfig(SpotifyClientConfig config) private static APIConnector ValidateConfig(SpotifyClientConfig config)

View File

@ -192,10 +192,7 @@ namespace SpotifyAPI.Web.Http
private async Task<IResponse> DoRequest(IRequest request) private async Task<IResponse> DoRequest(IRequest request)
{ {
if (_authenticator != null) await ApplyAuthenticator(request).ConfigureAwait(false);
{
await _authenticator.Apply(request, this).ConfigureAwait(false);
}
_httpLogger?.OnRequest(request); _httpLogger?.OnRequest(request);
IResponse response = await _httpClient.DoRequest(request).ConfigureAwait(false); IResponse response = await _httpClient.DoRequest(request).ConfigureAwait(false);
_httpLogger?.OnResponse(response); _httpLogger?.OnResponse(response);
@ -203,10 +200,7 @@ namespace SpotifyAPI.Web.Http
{ {
response = await _retryHandler.HandleRetry(request, response, async (newRequest) => response = await _retryHandler.HandleRetry(request, response, async (newRequest) =>
{ {
if (_authenticator != null) await ApplyAuthenticator(request).ConfigureAwait(false);
{
await _authenticator.Apply(request, this).ConfigureAwait(false);
}
var newResponse = await _httpClient.DoRequest(request).ConfigureAwait(false); var newResponse = await _httpClient.DoRequest(request).ConfigureAwait(false);
_httpLogger?.OnResponse(newResponse); _httpLogger?.OnResponse(newResponse);
return newResponse; return newResponse;
@ -216,6 +210,14 @@ namespace SpotifyAPI.Web.Http
return response; return response;
} }
private async Task ApplyAuthenticator(IRequest request)
{
if (_authenticator != null && !request.Endpoint.IsAbsoluteUri)
{
await _authenticator.Apply(request, this).ConfigureAwait(false);
}
}
public Task<IResponse> SendRawRequest( public Task<IResponse> SendRawRequest(
Uri uri, Uri uri,
HttpMethod method, HttpMethod method,

View File

@ -0,0 +1,54 @@
using System.Threading.Tasks;
namespace SpotifyAPI.Web.Http
{
/// <summary>
/// This Authenticator requests new credentials token on demand and stores them into memory.
/// It is unable to query user specifc details.
/// </summary>
public class CredentialsAuthenticator : IAuthenticator
{
private TokenResponse _token;
/// <summary>
/// Initiate a new instance. The first token will be fetched when the first API call occurs
/// </summary>
/// <param name="clientId">
/// The ClientID, defined in a spotify application in your Spotify Developer Dashboard
/// </param>
/// <param name="clientSecret">
/// The ClientID, defined in a spotify application in your Spotify Developer Dashboard
/// </param>
public CredentialsAuthenticator(string clientId, string clientSecret)
{
Ensure.ArgumentNotNullOrEmptyString(clientId, nameof(clientId));
Ensure.ArgumentNotNullOrEmptyString(clientSecret, nameof(clientSecret));
ClientId = clientId;
ClientSecret = clientSecret;
}
/// <summary>
/// The ClientID, defined in a spotify application in your Spotify Developer Dashboard
/// </summary>
public string ClientId { get; }
/// <summary>
/// The ClientID, defined in a spotify application in your Spotify Developer Dashboard
/// </summary>
public string ClientSecret { get; set; }
public async Task Apply(IRequest request, IAPIConnector apiConnector)
{
Ensure.ArgumentNotNull(request, nameof(request));
if (_token == null || _token.IsExpired)
{
var tokenRequest = new ClientCredentialsRequest(ClientId, ClientSecret);
_token = await OAuthClient.RequestToken(tokenRequest, apiConnector).ConfigureAwait(false);
}
request.Headers["Authorization"] = $"{_token.TokenType} {_token.AccessToken}";
}
}
}

View File

@ -1,3 +1,4 @@
using System;
namespace SpotifyAPI.Web namespace SpotifyAPI.Web
{ {
public class TokenResponse public class TokenResponse
@ -5,5 +6,13 @@ namespace SpotifyAPI.Web
public string AccessToken { get; set; } public string AccessToken { get; set; }
public string TokenType { get; set; } public string TokenType { get; set; }
public int ExpiresIn { get; set; } public int ExpiresIn { get; set; }
/// <summary>
/// Auto-Initalized to UTC Now
/// </summary>
/// <value></value>
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public bool IsExpired { get => CreatedAt.AddSeconds(ExpiresIn) <= DateTime.UtcNow; }
} }
} }