using Google.Apis.Auth; using Google.Apis.Auth.OAuth2.Flows; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Options; using System.Security.Claims; using System.Text.Encodings.Web; namespace Core.Thalos.BFF.Api.Services { public class GoogleAccessTokenAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, IConfiguration config) : AuthenticationHandler(options, logger, encoder) { protected override async Task HandleAuthenticateAsync() { if (!Request.Headers.ContainsKey("Authorization")) return AuthenticateResult.Fail("Missing Authorization header"); var authHeader = Request.Headers.Authorization.ToString(); if (!authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) return AuthenticateResult.Fail("Invalid Authorization header"); var idToken = authHeader["Bearer ".Length..].Trim(); GoogleJsonWebSignature.Payload payload; try { payload = await GoogleJsonWebSignature.ValidateAsync( idToken, new GoogleJsonWebSignature.ValidationSettings { Audience = new[] { config["Authentication:Google:ClientId"]! } }); } catch (InvalidJwtException) { return AuthenticateResult.Fail("Invalid Google token"); } var claims = new List { new Claim(ClaimTypes.NameIdentifier, payload.Subject), new Claim(ClaimTypes.Email, payload.Email), new Claim(ClaimTypes.Name, payload.Name ?? "") }; var identity = new ClaimsIdentity(claims, Constant.Scheme); var principal = new ClaimsPrincipal(identity); var userEmail = principal.FindFirst(ClaimTypes.Email)?.Value; if (string.IsNullOrEmpty(userEmail) || !userEmail.EndsWith("@agilewebs.com", StringComparison.OrdinalIgnoreCase)) return AuthenticateResult.Fail("Unauthorized Access"); var ticket = new AuthenticationTicket(principal, Constant.Scheme); return AuthenticateResult.Success(ticket); } } }