| | | 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), the <c>nonce</c> a client's |
| | | 6 | | /// own sign-in attempt is checked against (FR-GO-20), and the token's identifier and expiry its |
| | | 7 | | /// single use is recorded by (FR-GO-21) — nothing else on the token is read, so the application |
| | | 8 | | /// layer never sees an unverified claim. |
| | | 9 | | /// </summary> |
| | | 10 | | /// <param name="Subject">Google's stable <c>sub</c> claim, stored as the Google User's <c>GoogleId</c>.</param> |
| | | 11 | | /// <param name="Email">The <c>email</c> claim.</param> |
| | | 12 | | /// <param name="EmailVerified"> |
| | | 13 | | /// The <c>email_verified</c> claim, or <c>null</c> when the token carries no such claim — a |
| | | 14 | | /// client that obtained its token without the <c>email</c> scope gets one. Nullable so that |
| | | 15 | | /// "Google says the address is unverified" stays distinguishable from "Google said nothing": |
| | | 16 | | /// FR-GO-19's refresh only runs on the former, so an absent claim cannot downgrade a stored |
| | | 17 | | /// <c>true</c>. |
| | | 18 | | /// </param> |
| | | 19 | | /// <param name="Name">The <c>name</c> claim, absent on tokens whose issuer withheld the profile scope.</param> |
| | | 20 | | /// <param name="PictureUrl">The <c>picture</c> claim; optional, as the Google User field is.</param> |
| | | 21 | | /// <param name="Nonce"> |
| | | 22 | | /// The <c>nonce</c> claim, or <c>null</c> when the token carries none: Google copies it from |
| | | 23 | | /// the authentication request the client made, so it is present only when the client sent one. |
| | | 24 | | /// </param> |
| | | 25 | | /// <param name="TokenId"> |
| | | 26 | | /// The <c>jti</c> claim, which identifies this one token (FR-GO-21), or <c>null</c> when it |
| | | 27 | | /// carries none; the token is then identified by its signed part, the <c>header.payload</c> |
| | | 28 | | /// its signature covers (<c>GoogleIdTokenUse.KeyOf</c>). |
| | | 29 | | /// </param> |
| | | 30 | | /// <param name="ExpiresAt"> |
| | | 31 | | /// When the token expires, its <c>exp</c> claim, or <c>null</c> when a verifier could not read |
| | | 32 | | /// one. Its use is recorded until then (FR-GO-21). |
| | | 33 | | /// </param> |
| | 97 | 34 | | public record GoogleIdTokenPayload( |
| | 84 | 35 | | string Subject, |
| | 108 | 36 | | string Email, |
| | 85 | 37 | | bool? EmailVerified, |
| | 28 | 38 | | string? Name, |
| | 28 | 39 | | string? PictureUrl, |
| | 18 | 40 | | string? Nonce = null, |
| | 88 | 41 | | string? TokenId = null, |
| | 185 | 42 | | DateTime? ExpiresAt = null); |
| | | 43 | | |
| | | 44 | | /// <summary> |
| | | 45 | | /// Verifies a Google ID token and returns the claims it carries (UC-25 step 3, FR-GO-11, |
| | | 46 | | /// NFR-13). The signing scheme, the trusted issuers, and the accepted audiences belong to the |
| | | 47 | | /// presentation layer, so the application layer only says which token it wants checked. |
| | | 48 | | /// </summary> |
| | | 49 | | /// <remarks> |
| | | 50 | | /// The same arrangement as <see cref="IAuthTokenIssuer" />, and for the same reason: UC-25's |
| | | 51 | | /// handler is a use case, not a JWT library, and stays unit-testable without one. |
| | | 52 | | /// </remarks> |
| | | 53 | | public interface IGoogleIdTokenVerifier |
| | | 54 | | { |
| | | 55 | | /// <param name="idToken">The raw ID token the caller presented.</param> |
| | | 56 | | /// <returns> |
| | | 57 | | /// The verified claims, or <c>null</c> if the token is absent, malformed, expired, signed by |
| | | 58 | | /// someone else, or issued for another audience. A single <c>null</c> for every failure |
| | | 59 | | /// because AF-25a treats them alike — the handler has no decision to make between them. |
| | | 60 | | /// </returns> |
| | | 61 | | Task<GoogleIdTokenPayload?> VerifyAsync(string idToken); |
| | | 62 | | } |