| | | 1 | | namespace ArturRios.Jwt; |
| | | 2 | | |
| | | 3 | | /// <summary> |
| | | 4 | | /// Configuration used to create and validate JSON Web Tokens. |
| | | 5 | | /// </summary> |
| | | 6 | | /// <remarks> |
| | | 7 | | /// <para> |
| | | 8 | | /// There are two ways to supply key material, and the second is a superset of the first. |
| | | 9 | | /// <see cref="Secret"/> alone signs and validates with one key, which is all a deployment that never |
| | | 10 | | /// rotates needs. <see cref="Keys"/> with <see cref="SigningKeyId"/> signs with one key and accepts |
| | | 11 | | /// several, which is what makes a rotation possible: add the new key everywhere, switch the signing |
| | | 12 | | /// key, then drop the old one once no token signed with it can still be alive. |
| | | 13 | | /// </para> |
| | | 14 | | /// <para> |
| | | 15 | | /// Leaving <see cref="Keys"/> empty behaves exactly as it did before the property existed, so |
| | | 16 | | /// nothing changes for a configuration that does not use it. |
| | | 17 | | /// </para> |
| | | 18 | | /// <para> |
| | | 19 | | /// <see cref="Algorithm"/> pins one algorithm per configuration. An HS256 configuration holds secrets; |
| | | 20 | | /// an ES256 one holds EC P-256 keys, named by their thumbprints, and signs with one that has its private half. |
| | | 21 | | /// </para> |
| | | 22 | | /// </remarks> |
| | | 23 | | /// <param name="ExpirationInSeconds">The number of seconds after creation for which the token remains valid.</param> |
| | | 24 | | /// <param name="Issuer">The party that issues the token.</param> |
| | | 25 | | /// <param name="Audience">The intended recipient of the token.</param> |
| | | 26 | | /// <param name="Secret">The secret key used to sign and validate the token. Ignored when <see cref="SigningKeyId"/> nam |
| | | 27 | | /// <param name="Claims">The claims, as key/value pairs, to embed in the token.</param> |
| | 582 | 28 | | public record JwtConfiguration(double ExpirationInSeconds, string Issuer, string Audience, string Secret, Dictionary<str |
| | | 29 | | { |
| | | 30 | | /// <summary> |
| | | 31 | | /// Initializes a new instance of the <see cref="JwtConfiguration"/> record with empty default values. |
| | | 32 | | /// </summary> |
| | 2 | 33 | | public JwtConfiguration() : this(0, string.Empty, string.Empty, string.Empty, new Dictionary<string, string>()) { } |
| | | 34 | | |
| | | 35 | | /// <summary> |
| | | 36 | | /// Every key whose signature is accepted when validating. Empty by default, which keeps |
| | | 37 | | /// <see cref="Secret"/> as the only key. |
| | | 38 | | /// </summary> |
| | | 39 | | /// <remarks> |
| | | 40 | | /// A key stays here for as long as tokens it signed may still be alive — one token lifetime after |
| | | 41 | | /// it stops being the signing key. Removing it earlier invalidates those tokens immediately, |
| | | 42 | | /// which is the right thing to do when a key has leaked and the wrong thing to do when it is |
| | | 43 | | /// merely being replaced. |
| | | 44 | | /// </remarks> |
| | 627 | 45 | | public IReadOnlyCollection<JwtKey> Keys { get; init; } = []; |
| | | 46 | | |
| | | 47 | | /// <summary> |
| | | 48 | | /// The <see cref="JwtKey.Id"/> of the key in <see cref="Keys"/> that signs new tokens, written to |
| | | 49 | | /// each token's <c>kid</c> header. When empty, tokens are signed with <see cref="Secret"/> and |
| | | 50 | | /// carry no <c>kid</c> — so with <see cref="Keys"/> set, <see cref="Secret"/> must be the secret of |
| | | 51 | | /// one of them, or nothing validating against <see cref="Keys"/> accepts the tokens. |
| | | 52 | | /// </summary> |
| | | 53 | | /// <remarks> |
| | | 54 | | /// Rotating is a change to this property alone: the key it names must already be in |
| | | 55 | | /// <see cref="Keys"/> — <see cref="JwtConfigurationValidator"/> requires it — so the new key is |
| | | 56 | | /// accepted everywhere before anything starts signing with it. |
| | | 57 | | /// </remarks> |
| | 289 | 58 | | public string? SigningKeyId { get; init; } |
| | | 59 | | |
| | | 60 | | /// <summary> |
| | | 61 | | /// The algorithm tokens are signed with, and the only one the configuration's keys may hold: |
| | | 62 | | /// <see cref="JwtAlgorithms.HS256"/>, the default, or <see cref="JwtAlgorithms.ES256"/>. |
| | | 63 | | /// </summary> |
| | | 64 | | /// <remarks> |
| | | 65 | | /// An ES256 configuration signs with the private key <see cref="SigningKeyId"/> names in |
| | | 66 | | /// <see cref="Keys"/>, and leaves <see cref="Secret"/> empty. Leaving this property alone keeps a |
| | | 67 | | /// configuration exactly as it was before ES256 existed. |
| | | 68 | | /// </remarks> |
| | 327 | 69 | | public string Algorithm { get; init; } = JwtAlgorithms.HS256; |
| | | 70 | | } |