Migrate GitHubOAuthValidator to IGitHubService

This commit is contained in:
Dominion
2023-06-04 01:02:22 -04:00
parent 97d5f58fd5
commit 7f4c30650d
4 changed files with 67 additions and 27 deletions
@@ -21,9 +21,9 @@ namespace Tgstation.Server.Host.Security.OAuth
public OAuthProvider Provider => OAuthProvider.GitHub;
/// <summary>
/// The <see cref="IGitHubClientFactory"/> for the <see cref="GitHubOAuthValidator"/>.
/// The <see cref="IGitHubServiceFactory"/> for the <see cref="GitHubOAuthValidator"/>.
/// </summary>
readonly IGitHubClientFactory gitHubClientFactory;
readonly IGitHubServiceFactory gitHubServiceFactory;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="GitHubOAuthValidator"/>.
@@ -38,15 +38,15 @@ namespace Tgstation.Server.Host.Security.OAuth
/// <summary>
/// Initializes a new instance of the <see cref="GitHubOAuthValidator"/> class.
/// </summary>
/// <param name="gitHubClientFactory">The value of <see cref="gitHubClientFactory"/>.</param>
/// <param name="gitHubServiceFactory">The value of <see cref="gitHubServiceFactory"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
/// <param name="oAuthConfiguration">The value of <see cref="oAuthConfiguration"/>.</param>
public GitHubOAuthValidator(
IGitHubClientFactory gitHubClientFactory,
IGitHubServiceFactory gitHubServiceFactory,
ILogger<GitHubOAuthValidator> logger,
OAuthConfiguration oAuthConfiguration)
{
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
this.gitHubServiceFactory = gitHubServiceFactory ?? throw new ArgumentNullException(nameof(gitHubServiceFactory));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
this.oAuthConfiguration = oAuthConfiguration ?? throw new ArgumentNullException(nameof(oAuthConfiguration));
}
@@ -57,35 +57,21 @@ namespace Tgstation.Server.Host.Security.OAuth
if (code == null)
throw new ArgumentNullException(nameof(code));
var client = gitHubClientFactory.CreateClient();
try
{
logger.LogTrace("Validating response code...");
var response = await client
.Oauth
.CreateAccessToken(
new OauthTokenRequest(
oAuthConfiguration.ClientId,
oAuthConfiguration.ClientSecret,
code)
{
RedirectUri = oAuthConfiguration.RedirectUrl,
})
;
var token = response.AccessToken;
var gitHubService = gitHubServiceFactory.CreateService();
var token = await gitHubService.CreateOAuthAccessToken(oAuthConfiguration, code, cancellationToken);
if (token == null)
return null;
var authenticatedClient = gitHubClientFactory.CreateClient(token);
var authenticatedClient = gitHubServiceFactory.CreateService(token);
logger.LogTrace("Getting user details...");
var userDetails = await authenticatedClient
.User
.Current()
;
var userId = await authenticatedClient.GetCurrentUserId(cancellationToken);
return userDetails.Id.ToString(CultureInfo.InvariantCulture);
return userId.ToString(CultureInfo.InvariantCulture);
}
catch (RateLimitExceededException)
{
@@ -25,12 +25,12 @@ namespace Tgstation.Server.Host.Security.OAuth
/// <summary>
/// Initializes a new instance of the <see cref="OAuthProviders"/> class.
/// </summary>
/// <param name="gitHubClientFactory">The <see cref="IGitHubClientFactory"/> to use.</param>
/// <param name="gitHubServiceFactory">The <see cref="IGitHubServiceFactory"/> to use.</param>
/// <param name="httpClientFactory">The <see cref="IAbstractHttpClientFactory"/> to use.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> to use.</param>
/// <param name="securityConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the <see cref="SecurityConfiguration"/> to use.</param>
public OAuthProviders(
IGitHubClientFactory gitHubClientFactory,
IGitHubServiceFactory gitHubServiceFactory,
IAbstractHttpClientFactory httpClientFactory,
ILoggerFactory loggerFactory,
IOptions<SecurityConfiguration> securityConfigurationOptions)
@@ -49,7 +49,7 @@ namespace Tgstation.Server.Host.Security.OAuth
if (securityConfiguration.OAuth.TryGetValue(OAuthProvider.GitHub, out var gitHubConfig))
validatorsBuilder.Add(
new GitHubOAuthValidator(
gitHubClientFactory,
gitHubServiceFactory,
loggerFactory.CreateLogger<GitHubOAuthValidator>(),
gitHubConfig));
@@ -44,6 +44,33 @@ namespace Tgstation.Server.Host.Utils.GitHub
this.updatesConfiguration = updatesConfiguration ?? throw new ArgumentNullException(nameof(updatesConfiguration));
}
/// <inheritdoc />
public async Task<string> CreateOAuthAccessToken(OAuthConfiguration oAuthConfiguration, string code, CancellationToken cancellationToken)
{
if (oAuthConfiguration == null)
throw new ArgumentNullException(nameof(oAuthConfiguration));
if (code == null)
throw new ArgumentNullException(nameof(code));
logger.LogTrace("CreateOAuthAccessToken");
var response = await gitHubClient
.Oauth
.CreateAccessToken(
new OauthTokenRequest(
oAuthConfiguration.ClientId,
oAuthConfiguration.ClientSecret,
code)
{
RedirectUri = oAuthConfiguration.RedirectUrl,
})
.WithToken(cancellationToken);
var token = response.AccessToken;
return token;
}
/// <inheritdoc />
public async Task<Dictionary<Version, Release>> GetTgsReleases(CancellationToken cancellationToken)
{
@@ -90,5 +117,14 @@ namespace Tgstation.Server.Host.Utils.GitHub
return repoUrl;
}
/// <inheritdoc />
public async Task<int> GetCurrentUserId(CancellationToken cancellationToken)
{
logger.LogTrace("CreateOAuthAccessToken");
var userDetails = await gitHubClient.User.Current().WithToken(cancellationToken);
return userDetails.Id;
}
}
}
@@ -5,6 +5,8 @@ using System.Threading.Tasks;
using Octokit;
using Tgstation.Server.Host.Configuration;
namespace Tgstation.Server.Host.Utils.GitHub
{
/// <summary>
@@ -26,5 +28,21 @@ namespace Tgstation.Server.Host.Utils.GitHub
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="Dictionary{TKey, TValue}"/> of TGS <see cref="Release"/>s keyed by their <see cref="Version"/>.</returns>
/// <remarks>GitHub has been known to return incomplete results from the API with this call.</remarks>
Task<Dictionary<Version, Release>> GetTgsReleases(CancellationToken cancellationToken);
/// <summary>
/// Attempt to get an OAuth token from a given <paramref name="code"/>.
/// </summary>
/// <param name="oAuthConfiguration">The <see cref="OAuthConfiguration"/>. Must have <see cref="OAuthConfiguration.RedirectUrl"/>, <see cref="OAuthConfigurationBase.ClientId"/> and <see cref="OAuthConfigurationBase.ClientSecret"/> set.</param>
/// <param name="code">The OAuth response code.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="string"/> representing the returned OAuth code from GitHub on success, <see langword="null"/> otherwise.</returns>
Task<string> CreateOAuthAccessToken(OAuthConfiguration oAuthConfiguration, string code, CancellationToken cancellationToken);
/// <summary>
/// Get the current user's ID.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the current user's ID.</returns>
Task<int> GetCurrentUserId(CancellationToken cancellationToken);
}
}