Updates /tg/ forums OAuth support

This commit is contained in:
Jordan Brown
2021-10-31 01:29:14 -04:00
parent af3420e5eb
commit effa2d93d4
@@ -19,20 +19,16 @@ namespace Tgstation.Server.Host.Security.OAuth
/// <summary>
/// <see cref="IOAuthValidator"/> for /tg/ forums.
/// </summary>
sealed class TGForumsOAuthValidator : BaseOAuthValidator
sealed class TGForumsOAuthValidator : GenericOAuthValidator
{
/// <summary>
/// Amount of minutes until unused sessions that were created are forgotten.
/// </summary>
const uint SessionRetentionMinutes = 10;
/// <inheritdoc />
public override OAuthProvider Provider => OAuthProvider.TGForums;
/// <summary>
/// The active session.
/// </summary>
readonly List<Tuple<TGCreateSessionResponse, DateTimeOffset>> sessions;
/// <inheritdoc />
protected override Uri TokenUrl => new Uri("https://tgstation13.org/phpBB/app.php/tgapi/oauth/token");
/// <inheritdoc />
protected override Uri UserInformationUrl => new Uri("https://tgstation13.org/phpBB/app.php/tgapi/user/me");
/// <summary>
/// Initializes a new instance of the <see cref="TGForumsOAuthValidator"/> class.
@@ -52,98 +48,18 @@ namespace Tgstation.Server.Host.Security.OAuth
logger,
oAuthConfiguration)
{
sessions = new List<Tuple<TGCreateSessionResponse, DateTimeOffset>>();
}
/// <inheritdoc />
public override async Task<OAuthProviderInfo> GetProviderInfo(CancellationToken cancellationToken)
protected override string DecodeTokenPayload(dynamic responseJson)
{
var expiredSessions = sessions.RemoveAll(x => x.Item2.AddMinutes(SessionRetentionMinutes) < DateTimeOffset.UtcNow);
if (expiredSessions > 0)
Logger.LogTrace("Expired {0} sessions", expiredSessions);
Logger.LogTrace("Creating new session...");
try
{
UriBuilder builder = new UriBuilder("https://tgstation13.org/phpBB/oauth_create_session.php")
{
Query = $"site_private_token={HttpUtility.UrlEncode(Convert.ToBase64String(Encoding.UTF8.GetBytes(OAuthConfiguration.ClientSecret)))}&return_uri={HttpUtility.UrlEncode(OAuthConfiguration.RedirectUrl.ToString())}",
};
using var request = new HttpRequestMessage(HttpMethod.Get, builder.Uri);
using var httpClient = CreateHttpClient();
using var response = await httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var newSession = JsonConvert.DeserializeObject<TGCreateSessionResponse>(json, SerializerSettings());
if (newSession.Status != TGBaseResponse.OkStatus)
{
Logger.LogWarning("Invalid status from /tg/ API! Status: {0}, Error: {1}", newSession.Status, newSession.Error);
return null;
}
sessions.Add(
Tuple.Create(
newSession,
DateTimeOffset.UtcNow));
return new OAuthProviderInfo
{
ClientId = newSession.SessionPublicToken,
RedirectUri = OAuthConfiguration.RedirectUrl,
};
}
catch (Exception ex)
{
Logger.LogWarning(ex, "Failed to create TG Forums session!");
return null;
}
throw new NotImplementedException();
}
/// <inheritdoc />
public override async Task<string> ValidateResponseCode(string code, CancellationToken cancellationToken)
{
try
{
var sessionTuple = sessions.FirstOrDefault(x => x.Item1.SessionPublicToken == code);
if (sessionTuple == null)
{
Logger.LogWarning("No known session with this code active!");
return null;
}
protected override string DecodeUserInformationPayload(dynamic responseJson) => responseJson.phpbb_username;
Logger.LogTrace("Validating session...");
UriBuilder builder = new UriBuilder("https://tgstation13.org/phpBB/oauth_get_session_info.php")
{
Query = $"site_private_token={HttpUtility.UrlEncode(Convert.ToBase64String(Encoding.UTF8.GetBytes(OAuthConfiguration.ClientSecret)))}&session_private_token={HttpUtility.UrlEncode(sessionTuple.Item1.SessionPrivateToken)}",
};
using var request = new HttpRequestMessage(HttpMethod.Get, builder.Uri);
using var httpClient = CreateHttpClient();
using var response = await httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var sessionInfo = JsonConvert.DeserializeObject<TGGetSessionInfoResponse>(json, SerializerSettings());
if (sessionInfo.Status != TGBaseResponse.OkStatus)
{
Logger.LogWarning("Invalid status from /tg/ API! Status: {0}, Error: {1}", sessionInfo.Status, sessionInfo.Error);
return null;
}
sessions.Remove(sessionTuple);
return sessionInfo.PhpbbUsername;
}
catch (Exception ex)
{
Logger.LogWarning(ex, "Failed to create TG Forums session!");
return null;
}
}
/// <inheritdoc />
protected override OAuthTokenRequest CreateTokenRequest(string code) => new OAuthTokenRequest(OAuthConfiguration, code, "user");
}
}