mirror of
https://github.com/Sarsoo/Spotify.NET.git
synced 2024-12-24 15:06:26 +00:00
Added support for proxy configs in auth flows, closes #360
This commit is contained in:
parent
0a9499c7d1
commit
4933deaf26
@ -16,6 +16,8 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
{
|
{
|
||||||
public string SecretId { get; set; }
|
public string SecretId { get; set; }
|
||||||
|
|
||||||
|
public ProxyConfig ProxyConfig { get; set; }
|
||||||
|
|
||||||
public AuthorizationCodeAuth(string redirectUri, string serverUri, Scope scope = Scope.None, string state = "")
|
public AuthorizationCodeAuth(string redirectUri, string serverUri, Scope scope = Scope.None, string state = "")
|
||||||
: base("code", "AuthorizationCodeAuth", redirectUri, serverUri, scope, state)
|
: base("code", "AuthorizationCodeAuth", redirectUri, serverUri, scope, state)
|
||||||
{
|
{
|
||||||
@ -53,7 +55,8 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
new KeyValuePair<string, string>("refresh_token", refreshToken)
|
new KeyValuePair<string, string>("refresh_token", refreshToken)
|
||||||
};
|
};
|
||||||
|
|
||||||
HttpClient client = new HttpClient();
|
HttpClientHandler handler = ProxyConfig.CreateClientHandler(ProxyConfig);
|
||||||
|
HttpClient client = new HttpClient(handler);
|
||||||
client.DefaultRequestHeaders.Add("Authorization", GetAuthHeader());
|
client.DefaultRequestHeaders.Add("Authorization", GetAuthHeader());
|
||||||
HttpContent content = new FormUrlEncodedContent(args);
|
HttpContent content = new FormUrlEncodedContent(args);
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
|
|
||||||
public string ClientId { get; set; }
|
public string ClientId { get; set; }
|
||||||
|
|
||||||
|
public ProxyConfig ProxyConfig { get; set; }
|
||||||
|
|
||||||
public CredentialsAuth(string clientId, string clientSecret)
|
public CredentialsAuth(string clientId, string clientSecret)
|
||||||
{
|
{
|
||||||
ClientId = clientId;
|
ClientId = clientId;
|
||||||
@ -29,7 +31,8 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
new KeyValuePair<string, string>("grant_type", "client_credentials")
|
new KeyValuePair<string, string>("grant_type", "client_credentials")
|
||||||
};
|
};
|
||||||
|
|
||||||
HttpClient client = new HttpClient();
|
HttpClientHandler handler = ProxyConfig.CreateClientHandler(ProxyConfig);
|
||||||
|
HttpClient client = new HttpClient(handler);
|
||||||
client.DefaultRequestHeaders.Add("Authorization", $"Basic {auth}");
|
client.DefaultRequestHeaders.Add("Authorization", $"Basic {auth}");
|
||||||
HttpContent content = new FormUrlEncodedContent(args);
|
HttpContent content = new FormUrlEncodedContent(args);
|
||||||
|
|
||||||
|
@ -22,30 +22,34 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class TokenSwapAuth : SpotifyAuthServer<AuthorizationCode>
|
public class TokenSwapAuth : SpotifyAuthServer<AuthorizationCode>
|
||||||
{
|
{
|
||||||
string exchangeServerUri;
|
readonly string _exchangeServerUri;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The HTML to respond with when the callback server (serverUri) is reached. The default value will close the window on arrival.
|
/// The HTML to respond with when the callback server (serverUri) is reached. The default value will close the window on arrival.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string HtmlResponse { get; set; } = "<script>window.close();</script>";
|
public string HtmlResponse { get; set; } = "<script>window.close();</script>";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, will time how long it takes for access to expire. On expiry, the <see cref="OnAccessTokenExpired"/> event fires.
|
/// If true, will time how long it takes for access to expire. On expiry, the <see cref="OnAccessTokenExpired"/> event fires.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TimeAccessExpiry { get; set; }
|
public bool TimeAccessExpiry { get; set; }
|
||||||
|
|
||||||
|
public ProxyConfig ProxyConfig { get; set; }
|
||||||
|
|
||||||
/// <param name="exchangeServerUri">The URI to an exchange server that will perform the key exchange.</param>
|
/// <param name="exchangeServerUri">The URI to an exchange server that will perform the key exchange.</param>
|
||||||
/// <param name="serverUri">The URI to host the server at that your exchange server should return the authorization code to by GET request. (e.g. http://localhost:4002)</param>
|
/// <param name="serverUri">The URI to host the server at that your exchange server should return the authorization code to by GET request. (e.g. http://localhost:4002)</param>
|
||||||
/// <param name="scope"></param>
|
/// <param name="scope"></param>
|
||||||
/// <param name="state">Stating none will randomly generate a state parameter.</param>
|
/// <param name="state">Stating none will randomly generate a state parameter.</param>
|
||||||
/// <param name="htmlResponse">The HTML to respond with when the callback server (serverUri) is reached. The default value will close the window on arrival.</param>
|
/// <param name="htmlResponse">The HTML to respond with when the callback server (serverUri) is reached. The default value will close the window on arrival.</param>
|
||||||
public TokenSwapAuth(string exchangeServerUri, string serverUri, Scope scope = Scope.None, string state = "", string htmlResponse = "") : base("code", "", "", serverUri, scope, state)
|
public TokenSwapAuth(string exchangeServerUri, string serverUri, Scope scope = Scope.None, string state = "",
|
||||||
|
string htmlResponse = "") : base("code", "", "", serverUri, scope, state)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(htmlResponse))
|
if (!string.IsNullOrEmpty(htmlResponse))
|
||||||
{
|
{
|
||||||
HtmlResponse = htmlResponse;
|
HtmlResponse = htmlResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.exchangeServerUri = exchangeServerUri;
|
_exchangeServerUri = exchangeServerUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AdaptWebServer(WebServer webServer)
|
protected override void AdaptWebServer(WebServer webServer)
|
||||||
@ -55,7 +59,7 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
|
|
||||||
public override string GetUri()
|
public override string GetUri()
|
||||||
{
|
{
|
||||||
StringBuilder builder = new StringBuilder(exchangeServerUri);
|
StringBuilder builder = new StringBuilder(_exchangeServerUri);
|
||||||
builder.Append("?");
|
builder.Append("?");
|
||||||
builder.Append("response_type=code");
|
builder.Append("response_type=code");
|
||||||
builder.Append("&state=" + State);
|
builder.Append("&state=" + State);
|
||||||
@ -64,8 +68,6 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
return Uri.EscapeUriString(builder.ToString());
|
return Uri.EscapeUriString(builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly HttpClient httpClient = new HttpClient();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum amount of times to retry getting a token.
|
/// The maximum amount of times to retry getting a token.
|
||||||
/// <para/>
|
/// <para/>
|
||||||
@ -85,9 +87,10 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
/// <param name="refreshToken">This needs to be defined if "grantType" is "refresh_token".</param>
|
/// <param name="refreshToken">This needs to be defined if "grantType" is "refresh_token".</param>
|
||||||
/// <param name="currentRetries">Does not need to be defined. Used internally for retry attempt recursion.</param>
|
/// <param name="currentRetries">Does not need to be defined. Used internally for retry attempt recursion.</param>
|
||||||
/// <returns>Attempts to return a full <see cref="Token"/>, but after retry attempts, may return a <see cref="Token"/> with no <see cref="Token.AccessToken"/>, or null.</returns>
|
/// <returns>Attempts to return a full <see cref="Token"/>, but after retry attempts, may return a <see cref="Token"/> with no <see cref="Token.AccessToken"/>, or null.</returns>
|
||||||
async Task<Token> GetToken(string grantType, string authorizationCode = "", string refreshToken = "", int currentRetries = 0)
|
async Task<Token> GetToken(string grantType, string authorizationCode = "", string refreshToken = "",
|
||||||
|
int currentRetries = 0)
|
||||||
{
|
{
|
||||||
var content = new FormUrlEncodedContent(new Dictionary<string, string>
|
FormUrlEncodedContent content = new FormUrlEncodedContent(new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
{"grant_type", grantType},
|
{"grant_type", grantType},
|
||||||
{"code", authorizationCode},
|
{"code", authorizationCode},
|
||||||
@ -96,7 +99,10 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var siteResponse = await httpClient.PostAsync(exchangeServerUri, content);
|
HttpClientHandler handler = ProxyConfig.CreateClientHandler(ProxyConfig);
|
||||||
|
HttpClient client = new HttpClient(handler);
|
||||||
|
HttpResponseMessage siteResponse = await client.PostAsync(_exchangeServerUri, content);
|
||||||
|
|
||||||
Token token = JsonConvert.DeserializeObject<Token>(await siteResponse.Content.ReadAsStringAsync());
|
Token token = JsonConvert.DeserializeObject<Token>(await siteResponse.Content.ReadAsStringAsync());
|
||||||
// Don't need to check if it was null - if it is, it will resort to the catch block.
|
// Don't need to check if it was null - if it is, it will resort to the catch block.
|
||||||
if (!token.HasError() && !string.IsNullOrEmpty(token.AccessToken))
|
if (!token.HasError() && !string.IsNullOrEmpty(token.AccessToken))
|
||||||
@ -104,7 +110,9 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
if (currentRetries >= MaxGetTokenRetries)
|
if (currentRetries >= MaxGetTokenRetries)
|
||||||
{
|
{
|
||||||
@ -120,7 +128,8 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.Timers.Timer accessTokenExpireTimer;
|
System.Timers.Timer _accessTokenExpireTimer;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When Spotify authorization has expired. Will only trigger if <see cref="TimeAccessExpiry"/> is true.
|
/// When Spotify authorization has expired. Will only trigger if <see cref="TimeAccessExpiry"/> is true.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -134,19 +143,19 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
{
|
{
|
||||||
if (!TimeAccessExpiry) return;
|
if (!TimeAccessExpiry) return;
|
||||||
|
|
||||||
if (accessTokenExpireTimer != null)
|
if (_accessTokenExpireTimer != null)
|
||||||
{
|
{
|
||||||
accessTokenExpireTimer.Stop();
|
_accessTokenExpireTimer.Stop();
|
||||||
accessTokenExpireTimer.Dispose();
|
_accessTokenExpireTimer.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
accessTokenExpireTimer = new System.Timers.Timer
|
_accessTokenExpireTimer = new System.Timers.Timer
|
||||||
{
|
{
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
Interval = token.ExpiresIn * 1000,
|
Interval = token.ExpiresIn * 1000,
|
||||||
AutoReset = false
|
AutoReset = false
|
||||||
};
|
};
|
||||||
accessTokenExpireTimer.Elapsed += (sender, e) => OnAccessTokenExpired?.Invoke(this, EventArgs.Empty);
|
_accessTokenExpireTimer.Elapsed += (sender, e) => OnAccessTokenExpired?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -161,6 +170,7 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
{
|
{
|
||||||
SetAccessExpireTimer(token);
|
SetAccessExpireTimer(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,6 +186,7 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
{
|
{
|
||||||
SetAccessExpireTimer(token);
|
SetAccessExpireTimer(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace SpotifyAPI.Web
|
namespace SpotifyAPI.Web
|
||||||
{
|
{
|
||||||
@ -73,5 +74,24 @@ namespace SpotifyAPI.Web
|
|||||||
|
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static HttpClientHandler CreateClientHandler(ProxyConfig proxyConfig = null)
|
||||||
|
{
|
||||||
|
HttpClientHandler clientHandler = new HttpClientHandler
|
||||||
|
{
|
||||||
|
PreAuthenticate = false,
|
||||||
|
UseDefaultCredentials = true,
|
||||||
|
UseProxy = false
|
||||||
|
};
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(proxyConfig?.Host)) return clientHandler;
|
||||||
|
WebProxy proxy = proxyConfig.CreateWebProxy();
|
||||||
|
clientHandler.UseProxy = true;
|
||||||
|
clientHandler.Proxy = proxy;
|
||||||
|
clientHandler.UseDefaultCredentials = proxy.UseDefaultCredentials;
|
||||||
|
clientHandler.PreAuthenticate = proxy.UseDefaultCredentials;
|
||||||
|
|
||||||
|
return clientHandler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,7 +20,7 @@ namespace SpotifyAPI.Web
|
|||||||
|
|
||||||
public SpotifyWebClient(ProxyConfig proxyConfig = null)
|
public SpotifyWebClient(ProxyConfig proxyConfig = null)
|
||||||
{
|
{
|
||||||
HttpClientHandler clientHandler = CreateClientHandler(proxyConfig);
|
HttpClientHandler clientHandler = ProxyConfig.CreateClientHandler(proxyConfig);
|
||||||
_client = new HttpClient(clientHandler);
|
_client = new HttpClient(clientHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,24 +200,5 @@ namespace SpotifyAPI.Web
|
|||||||
_client.DefaultRequestHeaders.TryAddWithoutValidation(headerPair.Key, headerPair.Value);
|
_client.DefaultRequestHeaders.TryAddWithoutValidation(headerPair.Key, headerPair.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HttpClientHandler CreateClientHandler(ProxyConfig proxyConfig = null)
|
|
||||||
{
|
|
||||||
HttpClientHandler clientHandler = new HttpClientHandler
|
|
||||||
{
|
|
||||||
PreAuthenticate = false,
|
|
||||||
UseDefaultCredentials = true,
|
|
||||||
UseProxy = false
|
|
||||||
};
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(proxyConfig?.Host)) return clientHandler;
|
|
||||||
WebProxy proxy = proxyConfig.CreateWebProxy();
|
|
||||||
clientHandler.UseProxy = true;
|
|
||||||
clientHandler.Proxy = proxy;
|
|
||||||
clientHandler.UseDefaultCredentials = proxy.UseDefaultCredentials;
|
|
||||||
clientHandler.PreAuthenticate = proxy.UseDefaultCredentials;
|
|
||||||
|
|
||||||
return clientHandler;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user