-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
165 additions
and
185 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,92 +1,93 @@ | ||
namespace Snyk.Common.Authentication; | ||
using System; | ||
|
||
using System; | ||
|
||
public delegate string TokenRefresher(); | ||
|
||
/// <summary> | ||
/// Util for AuthenticationToken strings. | ||
/// </summary> | ||
public class AuthenticationToken | ||
namespace Snyk.Common.Authentication | ||
{ | ||
public static readonly AuthenticationToken EmptyToken = new(AuthenticationType.Token, string.Empty); | ||
public delegate string TokenRefresher(); | ||
|
||
public TokenRefresher TokenRefresher; | ||
/// <summary> | ||
/// Util for AuthenticationToken strings. | ||
/// </summary> | ||
public class AuthenticationToken | ||
{ | ||
public static readonly AuthenticationToken EmptyToken = new(AuthenticationType.Token, string.Empty); | ||
|
||
private string value; | ||
public TokenRefresher TokenRefresher; | ||
|
||
public AuthenticationToken(AuthenticationType type, string value) | ||
{ | ||
this.value = value; | ||
Type = type; | ||
this.TokenRefresher = null; | ||
} | ||
private string value; | ||
|
||
public AuthenticationType Type { get; } | ||
public AuthenticationToken(AuthenticationType type, string value) | ||
{ | ||
this.value = value; | ||
Type = type; | ||
this.TokenRefresher = null; | ||
} | ||
|
||
public override string ToString() | ||
{ | ||
// if possible and required, update the token before using it | ||
if (this.TokenRefresher != null && Type == AuthenticationType.OAuth) | ||
public AuthenticationType Type { get; } | ||
|
||
public override string ToString() | ||
{ | ||
var oauthToken = OAuthToken.FromJson(this.value); | ||
if (oauthToken != null) | ||
// if possible and required, update the token before using it | ||
if (this.TokenRefresher != null && Type == AuthenticationType.OAuth) | ||
{ | ||
var expired = oauthToken.IsExpired(); | ||
if (expired) | ||
var oauthToken = OAuthToken.FromJson(this.value); | ||
if (oauthToken != null) | ||
{ | ||
this.value = this.TokenRefresher(); | ||
var expired = oauthToken.IsExpired(); | ||
if (expired) | ||
{ | ||
this.value = this.TokenRefresher(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return this.value; | ||
} | ||
|
||
public bool IsValid() | ||
{ | ||
if (string.IsNullOrWhiteSpace(this.value)) | ||
{ | ||
return false; | ||
return this.value; | ||
} | ||
|
||
switch (Type) | ||
public bool IsValid() | ||
{ | ||
case AuthenticationType.Token: | ||
return Guid.TryParse(this.value, out _); | ||
case AuthenticationType.OAuth: | ||
if (string.IsNullOrWhiteSpace(this.value)) | ||
{ | ||
var tokenState = GetTokenState(this.value); | ||
if (tokenState == OAuthTokenState.Expired) | ||
{ | ||
this.value = this.TokenRefresher(); | ||
tokenState = GetTokenState(this.value); | ||
} | ||
return false; | ||
} | ||
|
||
switch (Type) | ||
{ | ||
case AuthenticationType.Token: | ||
return Guid.TryParse(this.value, out _); | ||
case AuthenticationType.OAuth: | ||
{ | ||
var tokenState = GetTokenState(this.value); | ||
if (tokenState == OAuthTokenState.Expired) | ||
{ | ||
this.value = this.TokenRefresher(); | ||
tokenState = GetTokenState(this.value); | ||
} | ||
|
||
return tokenState == OAuthTokenState.Valid; | ||
return tokenState == OAuthTokenState.Valid; | ||
} | ||
default: | ||
throw new ArgumentOutOfRangeException(); | ||
} | ||
default: | ||
throw new ArgumentOutOfRangeException(); | ||
} | ||
} | ||
|
||
private static OAuthTokenState GetTokenState(string value) | ||
{ | ||
var oauthToken = OAuthToken.FromJson(value); | ||
var expired = oauthToken?.IsExpired() == true; | ||
|
||
return (oauthToken, expired) switch | ||
private static OAuthTokenState GetTokenState(string value) | ||
{ | ||
(null, _) => OAuthTokenState.Invalid, | ||
(_, true) => OAuthTokenState.Expired, | ||
(_, false) => OAuthTokenState.Valid | ||
}; | ||
} | ||
var oauthToken = OAuthToken.FromJson(value); | ||
var expired = oauthToken?.IsExpired() == true; | ||
|
||
private enum OAuthTokenState | ||
{ | ||
Invalid, | ||
Expired, | ||
Valid | ||
return (oauthToken, expired) switch | ||
{ | ||
(null, _) => OAuthTokenState.Invalid, | ||
(_, true) => OAuthTokenState.Expired, | ||
(_, false) => OAuthTokenState.Valid | ||
}; | ||
} | ||
|
||
private enum OAuthTokenState | ||
{ | ||
Invalid, | ||
Expired, | ||
Valid | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,40 @@ | ||
namespace Snyk.Common.Authentication; | ||
|
||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Serialization; | ||
using System; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
|
||
public class OAuthToken | ||
namespace Snyk.Common.Authentication | ||
{ | ||
[JsonPropertyName("access_token")] | ||
public string AccessToken { get; set; } | ||
|
||
[JsonPropertyName("token_type")] | ||
public string TokenType { get; set; } | ||
[JsonObject(NamingStrategyType = typeof(SnakeCaseNamingStrategy))] | ||
public class OAuthToken | ||
{ | ||
public string AccessToken { get; set; } | ||
|
||
[JsonPropertyName("refresh_token")] | ||
public string RefreshToken { get; set; } | ||
public string TokenType { get; set; } | ||
|
||
[JsonPropertyName("expiry")] | ||
public string Expiry { get; set; } | ||
public string RefreshToken { get; set; } | ||
|
||
public static OAuthToken FromJson(string token) | ||
{ | ||
OAuthToken result = null; | ||
public string Expiry { get; set; } | ||
|
||
try | ||
public static OAuthToken FromJson(string token) | ||
{ | ||
result = JsonSerializer.Deserialize<OAuthToken>(token); | ||
OAuthToken result = null; | ||
|
||
try | ||
{ | ||
result = JsonConvert.DeserializeObject<OAuthToken>(token); | ||
} | ||
catch (Exception) | ||
{ | ||
// nothing | ||
} | ||
|
||
return result; | ||
} | ||
catch (Exception) | ||
|
||
public bool IsExpired() | ||
{ | ||
// nothing | ||
var expiryDate = DateTime.Parse(Expiry).ToUniversalTime(); | ||
expiryDate = expiryDate.AddSeconds(10); | ||
return expiryDate < DateTime.UtcNow; | ||
} | ||
|
||
return result; | ||
} | ||
|
||
public bool IsExpired() | ||
{ | ||
var expiryDate = DateTime.Parse(Expiry).ToUniversalTime(); | ||
expiryDate = expiryDate.AddSeconds(10); | ||
return expiryDate < DateTime.UtcNow; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,70 @@ | ||
namespace Snyk.Common; | ||
|
||
using System; | ||
using System; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Net.Http.Headers; | ||
using System.Runtime.InteropServices; | ||
using global::Sentry; | ||
using Snyk.Common.Authentication; | ||
|
||
/// <summary> | ||
/// Factory for <see cref="HttpClient"/>. | ||
/// </summary> | ||
public static class HttpClientFactory | ||
namespace Snyk.Common | ||
{ | ||
/// <summary> | ||
/// Create new <see cref="HttpClient"/> by base URL and API token. | ||
/// Factory for <see cref="HttpClient"/>. | ||
/// </summary> | ||
/// <param name="token">User API token.</param> | ||
/// <param name="baseUrl">Base URL.</param> | ||
/// <returns>New HttpClient instance.</returns> | ||
public static HttpClient NewHttpClient(AuthenticationToken token, string baseUrl = null) | ||
public static class HttpClientFactory | ||
{ | ||
var httpClient = new HttpClient(new HttpClientHandler | ||
/// <summary> | ||
/// Create new <see cref="HttpClient"/> by base URL and API token. | ||
/// </summary> | ||
/// <param name="token">User API token.</param> | ||
/// <param name="baseUrl">Base URL.</param> | ||
/// <returns>New HttpClient instance.</returns> | ||
public static HttpClient NewHttpClient(AuthenticationToken token, string baseUrl = null) | ||
{ | ||
AutomaticDecompression = DecompressionMethods.GZip | ||
}); | ||
var httpClient = new HttpClient(new HttpClientHandler | ||
{ | ||
AutomaticDecompression = DecompressionMethods.GZip | ||
}); | ||
|
||
httpClient.DefaultRequestHeaders.ExpectContinue = false; | ||
httpClient.DefaultRequestHeaders.ExpectContinue = false; | ||
|
||
httpClient.Timeout = TimeSpan.FromMinutes(30); | ||
httpClient.Timeout = TimeSpan.FromMinutes(30); | ||
|
||
if (!string.IsNullOrEmpty(baseUrl)) | ||
{ | ||
httpClient.BaseAddress = new Uri(baseUrl); | ||
} | ||
if (!string.IsNullOrEmpty(baseUrl)) | ||
{ | ||
httpClient.BaseAddress = new Uri(baseUrl); | ||
} | ||
|
||
var authorizationString = "token " + token; | ||
if (token.Type == AuthenticationType.OAuth) | ||
{ | ||
var rawToken = token.ToString(); | ||
var oauthToken = OAuthToken.FromJson(rawToken); | ||
var accessToken = oauthToken?.AccessToken; | ||
authorizationString = "bearer " + accessToken; | ||
} | ||
|
||
httpClient.DefaultRequestHeaders.Add("Authorization", authorizationString); | ||
var authorizationString = "token " + token; | ||
if (token.Type == AuthenticationType.OAuth) | ||
{ | ||
var rawToken = token.ToString(); | ||
var oauthToken = OAuthToken.FromJson(rawToken); | ||
var accessToken = oauthToken?.AccessToken; | ||
authorizationString = "bearer " + accessToken; | ||
} | ||
|
||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); | ||
httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); | ||
httpClient.DefaultRequestHeaders.Add("Authorization", authorizationString); | ||
|
||
return httpClient; | ||
} | ||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); | ||
httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); | ||
|
||
public static HttpClient WithUserAgent(this HttpClient httpClient, string ideVersion, string pluginVersionString) | ||
{ | ||
if (string.IsNullOrEmpty(ideVersion) || string.IsNullOrEmpty(pluginVersionString)) | ||
{ | ||
return httpClient; | ||
} | ||
|
||
var os = RuntimeInformation.OSDescription; | ||
var arch = RuntimeInformation.ProcessArchitecture.ToString(); | ||
|
||
var header = $"VISUAL_STUDIO/{ideVersion} ({os};{arch}) VISUAL_STUDIO/{pluginVersionString} (VISUAL_STUDIO/{ideVersion})"; | ||
public static HttpClient WithUserAgent(this HttpClient httpClient, string ideVersion, string pluginVersionString) | ||
{ | ||
if (string.IsNullOrEmpty(ideVersion) || string.IsNullOrEmpty(pluginVersionString)) | ||
{ | ||
return httpClient; | ||
} | ||
|
||
var os = RuntimeInformation.OSDescription; | ||
var arch = RuntimeInformation.ProcessArchitecture.ToString(); | ||
|
||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(header); | ||
return httpClient; | ||
var header = $"VISUAL_STUDIO/{ideVersion} ({os};{arch}) VISUAL_STUDIO/{pluginVersionString} (VISUAL_STUDIO/{ideVersion})"; | ||
|
||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(header); | ||
return httpClient; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.