| | | 1 | | namespace ArturRios.Heimdall.Command.Services; |
| | | 2 | | |
| | | 3 | | /// <summary> |
| | | 4 | | /// The claims UC-25 trusts once a Google ID token has been verified (UC-25 step 3, FR-GO-11). |
| | | 5 | | /// The five fields a Google User is populated from (FR-GO-05), and the <c>nonce</c> a client's |
| | | 6 | | /// own sign-in attempt is checked against (FR-GO-20) — nothing else on the token is read, so the application layer |
| | | 7 | | /// never sees an unverified claim. |
| | | 8 | | /// </summary> |
| | | 9 | | /// <param name="Subject">Google's stable <c>sub</c> claim, stored as the Google User's <c>GoogleId</c>.</param> |
| | | 10 | | /// <param name="Email">The <c>email</c> claim.</param> |
| | | 11 | | /// <param name="EmailVerified"> |
| | | 12 | | /// The <c>email_verified</c> claim, or <c>null</c> when the token carries no such claim — a |
| | | 13 | | /// client that obtained its token without the <c>email</c> scope gets one. Nullable so that |
| | | 14 | | /// "Google says the address is unverified" stays distinguishable from "Google said nothing": |
| | | 15 | | /// FR-GO-19's refresh only runs on the former, so an absent claim cannot downgrade a stored |
| | | 16 | | /// <c>true</c>. |
| | | 17 | | /// </param> |
| | | 18 | | /// <param name="Name">The <c>name</c> claim, absent on tokens whose issuer withheld the profile scope.</param> |
| | | 19 | | /// <param name="PictureUrl">The <c>picture</c> claim; optional, as the Google User field is.</param> |
| | | 20 | | /// <param name="Nonce"> |
| | | 21 | | /// The <c>nonce</c> claim, or <c>null</c> when the token carries none: Google copies it from |
| | | 22 | | /// the authentication request the client made, so it is present only when the client sent one. |
| | | 23 | | /// </param> |
| | 72 | 24 | | public record GoogleIdTokenPayload( |
| | 62 | 25 | | string Subject, |
| | 46 | 26 | | string Email, |
| | 64 | 27 | | bool? EmailVerified, |
| | 19 | 28 | | string? Name, |
| | 19 | 29 | | string? PictureUrl, |
| | 89 | 30 | | string? Nonce = null); |
| | | 31 | | |
| | | 32 | | /// <summary> |
| | | 33 | | /// Verifies a Google ID token and returns the claims it carries (UC-25 step 3, FR-GO-11, |
| | | 34 | | /// NFR-13). The signing scheme, the trusted issuers, and the accepted audiences belong to the |
| | | 35 | | /// presentation layer, so the application layer only says which token it wants checked. |
| | | 36 | | /// </summary> |
| | | 37 | | /// <remarks> |
| | | 38 | | /// The same arrangement as <see cref="IAuthTokenIssuer" />, and for the same reason: UC-25's |
| | | 39 | | /// handler is a use case, not a JWT library, and stays unit-testable without one. |
| | | 40 | | /// </remarks> |
| | | 41 | | public interface IGoogleIdTokenVerifier |
| | | 42 | | { |
| | | 43 | | /// <param name="idToken">The raw ID token the caller presented.</param> |
| | | 44 | | /// <returns> |
| | | 45 | | /// The verified claims, or <c>null</c> if the token is absent, malformed, expired, signed by |
| | | 46 | | /// someone else, or issued for another audience. A single <c>null</c> for every failure |
| | | 47 | | /// because AF-25a treats them alike — the handler has no decision to make between them. |
| | | 48 | | /// </returns> |
| | | 49 | | Task<GoogleIdTokenPayload?> VerifyAsync(string idToken); |
| | | 50 | | } |