예제 #1
0
        /// <summary>
        /// Defines the JSON as payload.
        /// </summary>
        /// <param name="payload"></param>
        /// <returns></returns>
        public JwtDescriptorBuilder JsonPayload(JwtObject payload)
        {
            EnsurePayloadNotDefined("JSON");

            _jsonPayload = payload;
            return(this);
        }
예제 #2
0
        /// <summary>
        /// Use the <paramref name="reader"/> as JSON input and returns a <see cref="JwtObject"/>.
        /// </summary>
        /// <param name="reader"></param>
        public static JwtObject ReadJsonObject(ref Utf8JsonReader reader)
        {
            var current = new JwtObject();

            while (reader.Read() && reader.TokenType is JsonTokenType.PropertyName)
            {
                var name = reader.ValueSpan /* reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan */;
                reader.Read();
                var type = reader.TokenType;
                switch (type)
                {
                case JsonTokenType.StartObject:
                    current.Add(name, ReadJsonObject(ref reader));
                    break;

                case JsonTokenType.StartArray:
                    current.Add(name, ReadJsonArray(ref reader));
                    break;

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

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

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

                case JsonTokenType.Null:
                    current.Add(name);
                    break;

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

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

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

            return(current);
        }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of <see cref="JwtDescriptor{TPayload}"/>.
        /// </summary>
        /// <param name="header"></param>
        /// <param name="payload"></param>
        protected JwtDescriptor(JwtObject header, TPayload payload)
            : base(header)
        {
            if (payload is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.payload);
            }

            Payload = payload;
        }
예제 #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="JwtValue"/> class.
        /// </summary>
        /// <param name="value"></param>
        public JwtValue(JwtObject value)
        {
            if (value == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
            }

            Type  = JwtTokenType.Object;
            Value = value;
        }
예제 #5
0
        private JwsDescriptor CreateJws(JwtObject header)
        {
            var jws = new JwsDescriptor(header, _jsonPayload !);

            if (_signingKey != null)
            {
                var alg = _signingKey.SignatureAlgorithm ?? _algorithm;
                if (alg is null)
                {
                    throw new InvalidOperationException($"No algorithm is defined for the signature. Set the 'SignatureAlgorithm' property on the signing key, or specify a '{nameof(SignatureAlgorithm)}' to the '{nameof(SignWith)}' method.");
                }

                if (alg == SignatureAlgorithm.None)
                {
                    throw new InvalidOperationException($"The algorithm 'none' defined with a signing key. Specify either a signing with with a {nameof(SignatureAlgorithm)} different of 'none', or specify the {nameof(SignatureAlgorithm)} 'none' without signing key.");
                }

                jws.SigningKey = _signingKey;
                if (_algorithm != null)
                {
                    jws.Algorithm = _algorithm;
                }
            }
            else if (_noSignature)
            {
                jws.Algorithm = SignatureAlgorithm.None;
            }
            else
            {
                ThrowHelper.ThrowInvalidOperationException_NoSigningKeyDefined();
            }

            if (_automaticId)
            {
                jws.JwtId = Guid.NewGuid().ToString("N");
            }

            if (_expireAfter.HasValue)
            {
                jws.ExpirationTime = DateTime.UtcNow.AddSeconds(_expireAfter.Value);
            }

            if (_notBefore.HasValue)
            {
                jws.NotBefore = DateTime.UtcNow.AddSeconds(_notBefore.Value);
            }

            if (_automaticIssuedAt)
            {
                jws.IssuedAt = DateTime.UtcNow;
            }

            return(jws);
        }
예제 #6
0
        private void AddClaim(ReadOnlySpan <byte> utf8Name, JwtProperty value)
        {
            if (_jsonPayload == null)
            {
                _jsonPayload = new JwtObject();
            }

            JwtObject jwtObject;

            if (_jsonPayload.TryGetValue(utf8Name, out JwtProperty property) && property.Type == JwtTokenType.Object && !(property.Value is null))
            {
                jwtObject = (JwtObject)property.Value;
            }
            else
            {
                jwtObject = new JwtObject();
                _jsonPayload.Add(new JwtProperty(utf8Name, jwtObject));
            }

            jwtObject.Add(value);
        }
예제 #7
0
        /// <summary>
        ///  Try to get the header.
        /// </summary>
        /// <param name="header"></param>
        /// <param name="alg"></param>
        /// <param name="base64UrlHeader"></param>
        /// <returns></returns>
        public bool TryGetHeader(JwtObject header, SignatureAlgorithm alg, [NotNullWhen(true)] out byte[]?base64UrlHeader)
        {
            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;
                var keyId = kid.AsSpan();
                var node  = _head;
                while (node != null)
                {
                    if (keyId.SequenceEqual(node.Kid.AsSpan()))
                    {
                        if (node.Entries.TryGetValue(alg.Id, out var entry))
                        {
                            base64UrlHeader = entry;
                            if (node != _head)
                            {
                                MoveToHead(node);
                            }

                            return(true);
                        }

                        goto NotFound;
                    }

                    node = node.Next;
                }
            }

NotFound:
            base64UrlHeader = null;
            return(false);
        }
예제 #8
0
        private JwtDescriptorBuilder AddClaim(ReadOnlySpan <byte> utf8Name, JwtObject value)
        {
            if (_jsonPayload == null)
            {
                _jsonPayload = new JwtObject();
            }

            if (_jsonPayload.TryGetValue(utf8Name, out var property))
            {
                if (property.Type != JwtTokenType.Object)
                {
                    ThrowHelper.ThrowJwtDescriptorException_ClaimMustBeOfType(utf8Name, JwtTokenType.Object);
                }

                ((JwtObject)property.Value !).Merge(value);
            }
            else
            {
                property = new JwtProperty(utf8Name, value);
                _jsonPayload.Add(property);
            }

            return(this);
        }
예제 #9
0
 public ClientAssertionDescriptor(JwtObject header, JwtObject payload)
     : base(header, payload)
 {
 }
예제 #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="BinaryJweDescriptor"/> class.
 /// </summary>
 /// <param name="header"></param>
 /// <param name="payload"></param>
 public BinaryJweDescriptor(JwtObject header, byte[] payload)
     : base(header, payload)
 {
 }
예제 #11
0
 /// <summary>
 /// Adds a <see cref="JwtObject"/> property to the end of the <see cref="JwtObject"/>.
 /// </summary>
 /// <param name="name"></param>
 /// <param name="value"></param>
 public void Add(string name, JwtObject value) => Add(new JwtProperty(name, value));
예제 #12
0
 /// <summary>
 /// Initializes a new instance of <see cref="JwtDescriptor"/>.
 /// </summary>
 /// <param name="header"></param>
 protected JwtDescriptor(JwtObject header)
 {
     Header = header;
 }
예제 #13
0
 public void AddEvent(ReadOnlySpan <byte> utf8EventName, JwtObject @event)
 {
     AddEvent(new JwtProperty(utf8EventName, @event));
 }
예제 #14
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();
                    }
                }
            }
        }
예제 #15
0
 /// <summary>
 /// Adds a claim.
 /// </summary>
 /// <param name="name"></param>
 /// <param name="value"></param>
 /// <returns></returns>
 public JwtDescriptorBuilder AddClaim(string name, JwtObject value)
 => AddClaim(Utf8.GetBytes(name), value);
예제 #16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="JwtPayload"/> class.
 /// </summary>
 /// <param name="inner"></param>
 public JwtPayload(JwtObject inner)
 {
     _inner = inner;
 }
예제 #17
0
 public SecurityEventTokenDescriptor(JwtObject payload)
     : base(new JwtObject(), payload)
 {
 }
예제 #18
0
 /// <summary>
 /// Wrap a key.
 /// </summary>
 /// <param name="staticKey">The key to be wrapped. If <c>null</c>, the key will be ephemeral and generated within this method.</param>
 /// <param name="header">The key-values representing the JWT header.</param>
 /// <param name="destination">The destination span.</param>
 public abstract Jwk WrapKey(Jwk?staticKey, JwtObject header, Span <byte> destination);
예제 #19
0
 /// <summary>
 /// Initializes a new instance of <see cref="EncryptedJwtDescriptor{TPayload}"/>.
 /// </summary>
 /// <param name="header"></param>
 /// <param name="payload"></param>
 protected EncryptedJwtDescriptor(JwtObject header, TPayload payload)
     : base(header, payload)
 {
 }
예제 #20
0
 /// <summary>
 /// Initializes a new instance of <see cref="PlaintextJweDescriptor"/>.
 /// </summary>
 /// <param name="header"></param>
 /// <param name="payload"></param>
 public PlaintextJweDescriptor(JwtObject header, string payload)
     : base(header, payload)
 {
 }
예제 #21
0
 public SoftwareStatementDescriptor(JwtObject payload)
     : base(new JwtObject(), payload)
 {
 }
예제 #22
0
 public void AddEvent(string eventName, JwtObject @event)
 {
     AddEvent(Encoding.UTF8.GetBytes(eventName), @event);
 }
예제 #23
0
 /// <summary>
 /// Initializes a new instance of the <see cref="JwtHeader"/> class.
 /// </summary>
 /// <param name="inner"></param>
 public JwtHeader(JwtObject inner)
 {
     _inner = inner;
 }
예제 #24
0
 /// <summary>
 /// Adds an <see cref="JwtObject"/> to the end of the <see cref="JwtArray"/>.
 /// </summary>
 /// <param name="value"></param>
 public void Add(JwtObject value) => _inner.Add(new JwtValue(value));
예제 #25
0
 public IdTokenDescriptor(JwtObject header, JwtObject payload)
     : base(header, payload)
 {
 }
예제 #26
0
 public IdTokenDescriptor(JwtObject payload)
     : base(new JwtObject(), payload)
 {
 }
예제 #27
0
 /// <summary>
 /// Adds a <see cref="JwtObject"/> property to the end of the <see cref="JwtObject"/>.
 /// </summary>
 /// <param name="name"></param>
 /// <param name="value"></param>
 public void Add(ReadOnlySpan <byte> name, JwtObject value) => Add(new JwtProperty(name, value));
예제 #28
0
 public ClientAssertionDescriptor(JwtObject payload)
     : base(new JwtObject(), payload)
 {
 }
예제 #29
0
 /// <summary>
 /// Initializes an new instance of <see cref="JweDescriptor{TDescriptor}"/>.
 /// </summary>
 /// <param name="header"></param>
 /// <param name="payload"></param>
 public JweDescriptor(JwtObject header, JwsDescriptor payload)
     : base(header, payload)
 {
 }
예제 #30
0
 public StateDescriptor(JwtObject header, JwtObject payload)
     : base(header, payload)
 {
 }