/// <summary>Configure the signature behavior for a specific <paramref name="issuer"/>.</summary>
        public TokenValidationPolicyBuilder RequireSignature(string issuer, Jwks keys, SignatureAlgorithm defaultAlgorithm)
        {
            if (keys is null)
            {
                throw new ArgumentNullException(nameof(keys));
            }

            return(RequireSignatureByDefault(issuer, new StaticKeyProvider(keys), defaultAlgorithm));
        }
示例#2
0
 internal static Exception CreateNotSupportedException_Algorithm(SignatureAlgorithm algorithm) => new NotSupportedException($"The algorithm '{algorithm}' is not supported for this kind of JWK.");
示例#3
0
 /// <inheritsdoc />
 protected override SignatureVerifier CreateSignatureVerifier(SignatureAlgorithm algorithm) => throw new NotImplementedException();
示例#4
0
 private static Exception CreateArgumentOutOfRangeException_InvalidEcdsaKeySize(Jwk key, SignatureAlgorithm algorithm, int validKeySize, int keySize) => new ArgumentOutOfRangeException(nameof(algorithm), $"Invalid key size for '{key.Kid}'. Valid key size must be '{validKeySize}' bits for the algorithm {algorithm}. Key size: '{keySize}'.");
示例#5
0
 private static Exception CreateNotSupportedException_SignatureAlgorithm(SignatureAlgorithm algorithm, Jwk?key) => new NotSupportedException($"Signature failed. No support for: Algorithm: '{algorithm}', key: '{key?.Kid}'.");
示例#6
0
            /// <summary>Adds a base64-url encoded header to the cache.</summary>
            /// <param name="header"></param>
            /// <param name="alg"></param>
            /// <param name="kid"></param>
            /// <param name="typ"></param>
            /// <param name="base6UrlHeader"></param>
            public void AddHeader(JwtHeader header, SignatureAlgorithm alg, JsonEncodedText kid, string?typ, ReadOnlySpan <byte> base6UrlHeader)
            {
                _firstHeader = new WrappedHeader(header, base6UrlHeader.ToArray());
                if (IsEligibleHeaderForJws(header.Count, kid, typ))
                {
                    int  algorithmId = (int)alg.Id;
                    bool lockTaken   = false;
                    try
                    {
                        _spinLock.Enter(ref lockTaken);
                        if (_count >= MaxSize)
                        {
                            Clear();
                        }

                        var node = _head;
                        while (node != null)
                        {
                            if (algorithmId == node.AlgorithmId)
                            {
                                break;
                            }

                            node = node.Next;
                        }

                        var key = alg.Id;
                        if (node is null)
                        {
                            _count++;
                            node = new Bucket(algorithmId, kid, new CacheEntry(base6UrlHeader.ToArray(), typ))
                            {
                                Next = _head
                            };
                        }
                        else
                        {
                            if (!node.Entries.ContainsKey(kid))
                            {
                                _count++;
                                node.Entries[kid] = new CacheEntry(base6UrlHeader.ToArray(), typ);
                            }
                        }

                        if (!ReferenceEquals(_head, node))
                        {
                            if (_head != null)
                            {
                                _head.Previous = node;
                            }

                            _head = node;
                        }

                        if (_tail is null)
                        {
                            _tail = node;
                        }
                    }
                    finally
                    {
                        if (lockTaken)
                        {
                            _spinLock.Exit();
                        }
                    }
                }
            }
 public void AddHeader(JwtHeader header, SignatureAlgorithm alg, JsonEncodedText kid, string?typ, ReadOnlySpan <byte> base6UrlHeader)
 {
 }
示例#8
0
 public bool TryGetHeader(JwtHeader header, SignatureAlgorithm alg, JsonEncodedText kid, string?typ, [NotNullWhen(true)] out byte[]?base64UrlHeader)
 {
     base64UrlHeader = null;
     return(false);
 }
示例#9
0
 /// <summary>Initializes a new instance of <see cref="EncryptionAlgorithm"/>.</summary>
 public EncryptionAlgorithm(AlgorithmId id, string name, ushort requiredKeySizeInBytes, SignatureAlgorithm signatureAlgorithm, ushort requiredKeyWrappedSizeInBytes, EncryptionType category)
 {
     _id       = id;
     _utf8Name = JsonEncodedText.Encode(name);
     _requiredKeySizeInBytes = requiredKeySizeInBytes;
     _signatureAlgorithm     = signatureAlgorithm;
     _keyWrappedSizeInBytes  = requiredKeyWrappedSizeInBytes;
     _category  = category;
     _encryptor = CreateAuthenticatedEncryptor(this);
     _decryptor = CreateAuthenticatedDecryptor(this);
 }
 /// <summary>Configure the signature behavior for a specific <paramref name="issuer"/>.</summary>
 public TokenValidationPolicyBuilder RequireSignature(string issuer, string jwksUrl, SignatureAlgorithm defaultAlgorithm, HttpMessageHandler?handler = null)
 => RequireSignatureByDefault(issuer, new JwksHttpKeyProvider(issuer, jwksUrl, handler), defaultAlgorithm);
示例#11
0
 private static Exception CreateNotSupportedException_KeyedHashAlgorithm(SignatureAlgorithm algorithm) => new NotSupportedException($"Unable to create hash algorithm for algorithm '{algorithm}'.");
        /// <summary>Configure the <see cref="TokenValidationPolicy"/> based on the <paramref name="metadataUri"/>
        /// as defined by https://tools.ietf.org/html/rfc8414 and https://openid.net/specs/openid-connect-discovery-1_0.html.</summary>
        public TokenValidationPolicyBuilder RequireMetadataConfiguration(string metadataUri, SignatureAlgorithm defaultAlgorithm, HttpMessageHandler?handler = null)
        {
            if (!Uri.IsWellFormedUriString(metadataUri, UriKind.Absolute))
            {
                throw new InvalidOperationException($"'{metadataUri}' is not a valid URL.");
            }

            var keyProvider = new JwksHttpKeyProvider(metadataUri, handler);

            return(RequireSignatureByDefault(keyProvider.Issuer !, keyProvider, defaultAlgorithm));
        }
        /// <summary>Configure the signature behavior for a specific <paramref name="issuer"/>.</summary>
        public TokenValidationPolicyBuilder RequireSignatureByDefault(string issuer, IKeyProvider keyProvider, SignatureAlgorithm defaultAlgorithm)
        {
            if (issuer is null)
            {
                throw new ArgumentNullException(nameof(issuer));
            }

            if (keyProvider is null)
            {
                throw new ArgumentNullException(nameof(keyProvider));
            }

            if (defaultAlgorithm is null)
            {
                throw new ArgumentNullException(nameof(defaultAlgorithm));
            }

            if (defaultAlgorithm == SignatureAlgorithm.None)
            {
                throw new ArgumentException($"The algorithm 'none' is not valid with the method {nameof(RequireSignature)}. Use the method {nameof(AcceptUnsecureToken)} instead.", nameof(defaultAlgorithm));
            }

            _hasSignatureValidation = true;
            var policy = SignatureValidationPolicy.Create(keyProvider, defaultAlgorithm);

            _signaturePolicies[issuer] = policy;
            return(this);
        }
 /// <summary>Configure the signature behavior for a specific <paramref name="issuer"/>.</summary>
 public TokenValidationPolicyBuilder RequireSignature(string issuer, IList <Jwk> keys, SignatureAlgorithm defaultAlgorithm)
 => RequireSignature(issuer, new Jwks(keys), defaultAlgorithm);
示例#15
0
 /// <inheritsdoc />
 public override bool SupportSignature(SignatureAlgorithm algorithm)
 => false;
示例#16
0
 /// <summary>Initializes a new instance of the <see cref="EllipticalCurve"/> struct.</summary>
 public EllipticalCurve(byte id, ECCurve namedCurve, JsonEncodedText name, int keySizeInBits, int hashSize, SignatureAlgorithm supportedSignatureAlgorithm)
 {
     Id                          = id;
     KeySizeInBits               = keySizeInBits;
     Name                        = name;
     CurveParameters             = namedCurve;
     HashSize                    = hashSize;
     SupportedSignatureAlgorithm = supportedSignatureAlgorithm;
 }
示例#17
0
 public bool TryGetHeader(JwtHeader header, SignatureAlgorithm alg, JsonEncodedText kid, string?typ, [NotNullWhen(true)] out byte[]?base64UrlHeader)
 {
     return(_jwsCache.TryGetHeader(header, alg, kid, typ, out base64UrlHeader));
 }
示例#18
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Jwk"/> class.
 /// </summary>
 /// <param name="alg"></param>
 protected Jwk(SignatureAlgorithm alg)
 {
     Alg = alg.Utf8Name;
     _signatureAlgorithm = alg;
 }
示例#19
0
 public void AddHeader(JwtHeader header, SignatureAlgorithm alg, JsonEncodedText kid, string?typ, ReadOnlySpan <byte> base64UrlHeader)
 {
     _jwsCache.AddHeader(header, alg, kid, typ, base64UrlHeader);
 }
示例#20
0
 /// <summary>Configure the signature behavior with Key Vault for a specific <paramref name="vaultUri"/>.</summary>
 public static TokenValidationPolicyBuilder RequireSignatureWithKeyVault(this TokenValidationPolicyBuilder builder, string vaultUri, TokenCredential credentials, SignatureAlgorithm algorithm, long minimumRefreshInterval = CachedKeyProvider.DefaultMinimumRefreshInterval, long automaticRefreshInterval = CachedKeyProvider.DefaultAutomaticRefreshInterval)
 => builder.RequireSignature(vaultUri, new KeyVaultKeyProvider(vaultUri, credentials, minimumRefreshInterval, automaticRefreshInterval), algorithm);
示例#21
0
 internal static void ThrowArgumentOutOfRangeException_InvalidEcdsaKeySize(Jwk key, SignatureAlgorithm algorithm, int validKeySize, int keySize) => throw CreateArgumentOutOfRangeException_InvalidEcdsaKeySize(key, algorithm, validKeySize, keySize);
示例#22
0
 /// <summary>Configure the signature behavior with Key Vault for a specific <paramref name="client"/>.</summary>
 public static TokenValidationPolicyBuilder RequireSignatureWithKeyVault(this TokenValidationPolicyBuilder builder, KeyClient client, SignatureAlgorithm algorithm, long minimumRefreshInterval = CachedKeyProvider.DefaultMinimumRefreshInterval, long automaticRefreshInterval = CachedKeyProvider.DefaultAutomaticRefreshInterval)
 => builder.RequireSignature(client.VaultUri.ToString(), new KeyVaultKeyProvider(client, minimumRefreshInterval, automaticRefreshInterval), algorithm);
示例#23
0
 internal static void ThrowNotSupportedException_SignatureAlgorithm(SignatureAlgorithm algorithm, Jwk?key) => throw CreateNotSupportedException_SignatureAlgorithm(algorithm, key);
示例#24
0
        /// <summary>
        /// Adds a base64url encoded header to the cache.
        /// </summary>
        /// <param name="header"></param>
        /// <param name="alg"></param>
        /// <param name="base6UrlHeader"></param>
        public void AddHeader(JwtObject header, SignatureAlgorithm alg, ReadOnlySpan <byte> base6UrlHeader)
        {
            if (header.TryGetValue(HeaderParameters.KidUtf8, out var kidProperty) &&
                kidProperty.Type == JwtTokenType.String &&
                !(kidProperty.Value is null) &&
                !(alg is null) &&
                header.Count == 2)
            {
                var  kid       = (string)kidProperty.Value;
                bool lockTaken = false;
                try
                {
                    _spinLock.Enter(ref lockTaken);

                    var node = _head;
                    while (node != null)
                    {
                        if (string.Equals(node.Kid, kid, StringComparison.Ordinal))
                        {
                            break;
                        }

                        node = node.Next;
                    }

                    var key = alg.Id;

                    if (node is null)
                    {
                        node = new Bucket(kid, new Dictionary <long, byte[]>(1)
                        {
                            { key, base6UrlHeader.ToArray() }
                        })
                        {
                            Next = _head
                        };
                    }
                    else
                    {
                        if (node.Entries.ContainsKey(key))
                        {
                            node.Entries[key] = base6UrlHeader.ToArray();
                        }
                    }

                    if (_count >= MaxSize)
                    {
                        RemoveLeastRecentlyUsed();
                    }
                    else
                    {
                        _count++;
                    }

                    if (_head != null)
                    {
                        _head.Previous = node;
                    }

                    _head = node;
                    if (_tail is null)
                    {
                        _tail = node;
                    }
                }
                finally
                {
                    if (lockTaken)
                    {
                        _spinLock.Exit();
                    }
                }
            }
        }
示例#25
0
 internal static void ThrowNotSupportedException_Algorithm(SignatureAlgorithm algorithm) => throw CreateNotSupportedException_Algorithm(algorithm);
 public TokenValidationPolicyBuilder RequireSignature(string jwksUrl, SignatureAlgorithm algorithm)
 => throw new NotSupportedException();
示例#27
0
        /// <inheritsdoc />

        /// <inheritsdoc />
        public override bool SupportSignature(SignatureAlgorithm algorithm) => throw new NotImplementedException();
示例#28
0
 /// <inheritdoc />
 protected override SignatureVerifier CreateSignatureVerifier(SignatureAlgorithm algorithm)
 => throw ThrowHelper.CreateNotSupportedException_Algorithm(algorithm);
示例#29
0
 /// <summary>
 /// Initializes a new instance of the <see cref="AsymmetricJwk"/> class.
 /// </summary>
 protected AsymmetricJwk(SignatureAlgorithm alg)
     : base(alg)
 {
 }
示例#30
0
        /// <summary>
        /// Parses the UTF-8 <paramref name="buffer"/> as JSON and returns a <see cref="JwtHeader"/>.
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="policy"></param>
        public static JwtHeader ParseHeader(ReadOnlySpan <byte> buffer, TokenValidationPolicy policy)
        {
            Utf8JsonReader reader = new Utf8JsonReader(buffer, isFinalBlock: true, state: default);

            if (!reader.Read() || reader.TokenType != JsonTokenType.StartObject)
            {
                ThrowHelper.ThrowFormatException_MalformedJson();
            }

            var header = new JwtHeader();

            while (reader.Read())
            {
                if (!(reader.TokenType is JsonTokenType.PropertyName))
                {
                    break;
                }

                var name = reader.ValueSpan /* reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan */;
                reader.Read();
                var type = reader.TokenType;


                if (name.Length == 3)
                {
                    if (reader.TokenType == JsonTokenType.String)
                    {
                        var refName = IntegerMarshal.ReadUInt24(name);
                        switch (refName)
                        {
                        case Alg:
                            var alg = reader.ValueSpan /* reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan */;
                            if (SignatureAlgorithm.TryParse(alg, out var signatureAlgorithm))
                            {
                                header.SignatureAlgorithm = signatureAlgorithm;
                            }
                            else if (KeyManagementAlgorithm.TryParse(alg, out var keyManagementAlgorithm))
                            {
                                header.KeyManagementAlgorithm = keyManagementAlgorithm;
                            }
                            else if (SignatureAlgorithm.TryParseSlow(ref reader, out signatureAlgorithm))
                            {
                                header.SignatureAlgorithm = signatureAlgorithm;
                            }
                            else if (KeyManagementAlgorithm.TryParseSlow(ref reader, out keyManagementAlgorithm))
                            {
                                header.KeyManagementAlgorithm = keyManagementAlgorithm;
                            }
                            else
                            {
                                header.SignatureAlgorithm = SignatureAlgorithm.Create(reader.GetString());
                            }

                            continue;

                        case Enc:
                            var enc = reader.ValueSpan /* reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan */;
                            if (EncryptionAlgorithm.TryParse(enc, out var encryptionAlgorithm))
                            {
                                header.EncryptionAlgorithm = encryptionAlgorithm;
                            }
                            else if (EncryptionAlgorithm.TryParseSlow(ref reader, out encryptionAlgorithm))
                            {
                                header.EncryptionAlgorithm = encryptionAlgorithm;
                            }
                            else
                            {
                                header.EncryptionAlgorithm = EncryptionAlgorithm.Create(reader.GetString());
                            }

                            continue;

                        case Zip:
                            var zip = reader.ValueSpan /* reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan */;
                            if (CompressionAlgorithm.TryParse(zip, out var compressionAlgorithm))
                            {
                                header.CompressionAlgorithm = compressionAlgorithm;
                            }
                            else if (CompressionAlgorithm.TryParseSlow(ref reader, out compressionAlgorithm))
                            {
                                header.CompressionAlgorithm = compressionAlgorithm;
                            }
                            else
                            {
                                header.CompressionAlgorithm = CompressionAlgorithm.Create(reader.GetString());
                            }

                            continue;

                        case Cty:
                            header.Cty = reader.GetString();
                            continue;

                        case Typ:
                            header.Typ = reader.GetString();
                            continue;

                        case Kid:
                            header.Kid = reader.GetString();
                            continue;
                        }
                    }
                }
                else if (name.Length == 4)
                {
                    if (reader.TokenType == JsonTokenType.StartArray && IntegerMarshal.ReadUInt32(name) == Crit)
                    {
                        var handlers = policy.CriticalHandlers;
                        if (handlers.Count != 0)
                        {
                            var criticalHeaderHandlers = new List <KeyValuePair <string, ICriticalHeaderHandler> >(handlers.Count);
                            var criticals = new List <JwtValue>();
                            while (reader.Read() && reader.TokenType == JsonTokenType.String)
                            {
                                string criticalHeader = reader.GetString();
                                criticals.Add(new JwtValue(criticalHeader));
                                if (handlers.TryGetValue(criticalHeader, out var handler))
                                {
                                    criticalHeaderHandlers.Add(new KeyValuePair <string, ICriticalHeaderHandler>(criticalHeader, handler));
                                }
                                else
                                {
                                    criticalHeaderHandlers.Add(new KeyValuePair <string, ICriticalHeaderHandler>(criticalHeader, null !));
                                }
                            }

                            header.CriticalHeaderHandlers = criticalHeaderHandlers;

                            if (reader.TokenType != JsonTokenType.EndArray)
                            {
                                ThrowHelper.ThrowFormatException_MalformedJson("The 'crit' header parameter must be an array of string.");
                            }

                            header.Inner.Add(name, new JwtArray(criticals));
                        }
                        else
                        {
                            var criticals = new List <JwtValue>();
                            while (reader.Read() && reader.TokenType == JsonTokenType.String)
                            {
                                string criticalHeader = reader.GetString();
                                criticals.Add(new JwtValue(criticalHeader));
                            }

                            if (reader.TokenType != JsonTokenType.EndArray)
                            {
                                ThrowHelper.ThrowFormatException_MalformedJson("The 'crit' header parameter must be an array of string.");
                            }

                            header.Inner.Add(name, new JwtArray(criticals));
                        }

                        continue;
                    }
                }


                switch (type)
                {
                case JsonTokenType.StartObject:
                    header.Inner.Add(name, JsonParser.ReadJsonObject(ref reader));
                    break;

                case JsonTokenType.StartArray:
                    header.Inner.Add(name, JsonParser.ReadJsonArray(ref reader));
                    break;

                case JsonTokenType.String:
                    header.Inner.Add(name, reader.GetString());
                    break;

                case JsonTokenType.True:
                    header.Inner.Add(name, true);
                    break;

                case JsonTokenType.False:
                    header.Inner.Add(name, false);
                    break;

                case JsonTokenType.Null:
                    header.Inner.Add(name);
                    break;

                case JsonTokenType.Number:
                    if (reader.TryGetInt64(out long longValue))
                    {
                        header.Inner.Add(name, longValue);
                    }
                    else
                    {
                        header.Inner.Add(name, reader.GetDouble());
                    }
                    break;

                default:
                    ThrowHelper.ThrowFormatException_MalformedJson();
                    break;
                }
            }

            if (!(reader.TokenType is JsonTokenType.EndObject))
            {
                ThrowHelper.ThrowFormatException_MalformedJson();
            }

            return(header);
        }