using Microsoft.AspNetCore.Authentication.OAuth; using Npgsql; namespace IOL.GreatOffice.Api.Utilities; public static class GithubAuthenticationHelpers { public static async Task HandleGithubTicketCreation(OAuthCreatingTicketContext context, IConfiguration configuration) { var githubId = context.Identity?.FindFirst(p => p.Type == ClaimTypes.NameIdentifier)?.Value; var githubUsername = context.Identity?.FindFirst(p => p.Type == ClaimTypes.Name)?.Value; var githubEmail = context.Identity?.FindFirst(p => p.Type == ClaimTypes.Email)?.Value; if (githubId.IsNullOrWhiteSpace() || githubUsername.IsNullOrWhiteSpace() || context.Identity == default) { return; } var claims = context.Identity.Claims.ToList(); foreach (var claim in claims) { context.Identity.RemoveClaim(claim); } var connstring = configuration.GetAppDatabaseConnectionString(); var connection = new NpgsqlConnection(connstring); Log.Information($"Getting user mappings for github user: {githubId}"); var getMappedUserQuery = @$"SELECT u.id,u.username FROM github_user_mappings INNER JOIN users u on u.id = github_user_mappings.user_id WHERE github_id='{githubId}'"; await connection.OpenAsync(); await using var getMappedUserCommand = new NpgsqlCommand(getMappedUserQuery, connection); await using var reader = await getMappedUserCommand.ExecuteReaderAsync(); var handled = false; while (await reader.ReadAsync()) { try { var userId = reader.GetGuid(0); var username = reader.GetString(1); context.Identity.AddClaim(new Claim(AppClaims.USER_ID, userId.ToString())); context.Identity.AddClaim(new Claim(AppClaims.NAME, username)); if (context.AccessToken != default) { context.Identity.AddClaim(new Claim(AppClaims.GITHUB_ACCESS_TOKEN, context.AccessToken ?? "")); } Log.Information($"Found mapping for github id {githubId} mapped to user id {userId}"); handled = true; } catch (Exception e) { Log.Error(e, "An exception occured when handling github user mappings"); handled = false; } } await connection.CloseAsync(); if (!handled) { var userId = Guid.NewGuid(); var insertUserQuery = $@"INSERT INTO users VALUES ('{userId}', '{githubUsername}', '', '{DateTime.UtcNow}')"; await connection.OpenAsync(); await using var insertUserCommand = new NpgsqlCommand(insertUserQuery, connection); await insertUserCommand.ExecuteNonQueryAsync(); await connection.CloseAsync(); var refreshTokenEncryptionKey = configuration.GetValue(AppEnvironmentVariables.APP_AES_KEY); string insertMappingQuery; if (context.RefreshToken.HasValue() && refreshTokenEncryptionKey.HasValue()) { var encryptedRefreshToken = context.RefreshToken.EncryptWithAes(refreshTokenEncryptionKey); insertMappingQuery = $@"INSERT INTO github_user_mappings VALUES ('{githubId}', '{userId}', '{githubEmail}', '{encryptedRefreshToken}')"; } else { insertMappingQuery = $@"INSERT INTO github_user_mappings VALUES ('{githubId}', '{userId}', '{githubEmail}', '')"; } await connection.OpenAsync(); await using var insertMappingCommand = new NpgsqlCommand(insertMappingQuery, connection); await insertMappingCommand.ExecuteNonQueryAsync(); await connection.CloseAsync(); context.Identity.AddClaim(new Claim(AppClaims.USER_ID, userId.ToString())); context.Identity.AddClaim(new Claim(AppClaims.NAME, githubUsername)); if (context.AccessToken != default) { context.Identity.AddClaim(new Claim(AppClaims.GITHUB_ACCESS_TOKEN, context.AccessToken ?? "")); } Log.Information($"Created mapping for github id {githubId} mapped to user id {userId}"); } } }