huntapi/Services/ExternalTokenValidator.cs
Finn Skov Henriksen d7479db902
Some checks failed
Build / Restore, build and publish (push) Failing after 2m7s
first commit
2026-08-31 12:29:23 +02:00

37 lines
1.6 KiB
C#

using HuntingAppApi.Models;
using Newtonsoft.Json.Linq;
namespace HuntingAppApi.Services;
public sealed class ExternalTokenValidator(HttpClient httpClient)
{
public async Task<ExternalUserInfo> ValidateAsync(string provider, string idToken, CancellationToken ct)
{
provider = provider.ToLowerInvariant();
// Production note: This is intentionally simple. For stricter production validation,
// validate issuer, audience/client_id and signature using OIDC metadata/JWKS.
var url = provider switch
{
"google" => $"https://oauth2.googleapis.com/tokeninfo?id_token={Uri.EscapeDataString(idToken)}",
"microsoft" => $"https://login.microsoftonline.com/common/oauth2/v2.0/tokeninfo?id_token={Uri.EscapeDataString(idToken)}",
_ => throw new ArgumentException("Unsupported provider")
};
var json = await httpClient.GetStringAsync(url, ct);
var obj = JObject.Parse(json);
var sub = obj.Value<string>("sub") ?? throw new InvalidOperationException("Token has no sub claim");
var name = obj.Value<string>("name") ?? obj.Value<string>("preferred_username") ?? obj.Value<string>("email") ?? "User";
return new ExternalUserInfo
{
Provider = provider,
Subject = sub,
Email = obj.Value<string>("email") ?? obj.Value<string>("preferred_username"),
EmailVerified = obj.Value<string>("email_verified") == "true" || obj.Value<bool?>("email_verified") == true,
DisplayName = name,
AvatarUrl = obj.Value<string>("picture")
};
}
}