Beispiel #1
0
        /// <summary>
        /// Checks if a token is valid and signed by the factory.
        /// </summary>
        /// <param name="Token">JWT token.</param>
        /// <returns>If the token is correctly signed and valid.</returns>
        public bool IsValid(JwtToken Token)
        {
            if (Token.Algorithm != JwtAlgorithm.HS256 || Token.Signature == null)
            {
                return(false);
            }

            if (Token.Expiration != null || Token.NotBefore != null)
            {
                DateTime Now = DateTime.UtcNow;

                if (Token.Expiration != null && Now >= Token.Expiration.Value + this.timeMargin)
                {
                    return(false);
                }

                if (Token.NotBefore != null && Now < Token.NotBefore.Value - this.timeMargin)
                {
                    return(false);
                }
            }

            byte[] Signature = Token.Signature;
            byte[] Hash;
            int    i, c;

            lock (this.hmacSHA256)
            {
                Hash = this.hmacSHA256.ComputeHash(Encoding.ASCII.GetBytes(Token.Header + "." + Token.Payload));
            }

            if ((c = Hash.Length) != Signature.Length)
            {
                return(false);
            }

            for (i = 0; i < c; i++)
            {
                if (Hash[i] != Signature[i])
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #2
0
        /// <summary>
        /// Encodes an object.
        /// </summary>
        /// <param name="Object">Object to encode.</param>
        /// <param name="Encoding">Desired encoding of text. Can be null if no desired encoding is speified.</param>
        /// <param name="ContentType">Content Type of encoding. Includes information about any text encodings used.</param>
        /// <param name="AcceptedContentTypes">Optional array of accepted content types. If array is empty, all content types are accepted.</param>
        /// <returns>Encoded object.</returns>
        /// <exception cref="ArgumentException">If the object cannot be encoded.</exception>
        public byte[] Encode(object Object, Encoding Encoding, out string ContentType, params string[] AcceptedContentTypes)
        {
            JwtToken Token = Object as JwtToken;

            if (Token == null)
            {
                throw new ArgumentException("Object not a JWT token.", nameof(Object));
            }

            ContentType = JwtCodec.ContentType;

            string s = Token.Header + "." + Token.Payload + "." + JwtToken.Base64UrlEncode(Token.Signature);

            if (Encoding == null)
            {
                return(Encoding.ASCII.GetBytes(s));
            }
            else
            {
                return(Encoding.GetBytes(s));
            }
        }
Beispiel #3
0
        /// <summary>
        /// Checks if the request is authorized.
        /// </summary>
        /// <param name="Request">Request object.</param>
        /// <returns>User object, if authenticated, or null otherwise.</returns>
        public override async Task <IUser> IsAuthenticated(HttpRequest Request)
        {
            HttpFieldAuthorization Authorization = Request.Header.Authorization;

            if (Authorization != null && Authorization.Value.StartsWith("Bearer ", StringComparison.CurrentCultureIgnoreCase))
            {
                try
                {
                    string   TokenStr = Authorization.Value.Substring(7).Trim();
                    JwtToken Token    = new JwtToken(TokenStr);
                    string   UserName = Token.Subject;

                    if (!this.factory.IsValid(Token) || UserName is null)
                    {
                        LoginAuditor.Fail("Login attempt failed.", UserName ?? string.Empty, Request.RemoteEndPoint, "HTTP");
                        return(null);
                    }

                    IUser User = await this.users.TryGetUser(UserName);

                    if (User is null)
                    {
                        LoginAuditor.Fail("Login attempt failed.", UserName, Request.RemoteEndPoint, "HTTP");
                        return(null);
                    }
                    else
                    {
                        LoginAuditor.Success("Login successful.", UserName, Request.RemoteEndPoint, "HTTP");
                        return(User);
                    }
                }
                catch (Exception)
                {
                    return(null);
                }
            }

            return(null);
        }
Beispiel #4
0
        /// <summary>
        /// Checks if a token is valid and signed by the factory.
        /// </summary>
        /// <param name="Token">JWT token.</param>
        /// <returns>If the token is correctly signed and valid.</returns>
        public bool IsValid(JwtToken Token)
        {
            if (Token.Algorithm == null || !(Token.Algorithm is HmacSha256) || Token.Signature == null)
            {
                return(false);
            }

            if (Token.Expiration != null || Token.NotBefore != null)
            {
                DateTime Now = DateTime.UtcNow;

                if (Token.Expiration != null && Now >= Token.Expiration.Value + this.timeMargin)
                {
                    return(false);
                }

                if (Token.NotBefore != null && Now < Token.NotBefore.Value - this.timeMargin)
                {
                    return(false);
                }
            }

            return(this.algorithm.IsValid(Token.Header, Token.Payload, Token.Signature));
        }
Beispiel #5
0
        /// <summary>
        /// Creates a new JWT token.
        /// </summary>
        /// <param name="Claims">Claims to include in token.
        ///
        /// For a list of public claim names, see:
        /// https://www.iana.org/assignments/jwt/jwt.xhtml</param>
        /// <returns>JWT token.</returns>
        public string Create(params KeyValuePair <string, object>[] Claims)
        {
            StringBuilder Json  = new StringBuilder("{");
            bool          First = true;

            foreach (KeyValuePair <string, object> Claim in Claims)
            {
                if (First)
                {
                    First = false;
                }
                else
                {
                    Json.Append(',');
                }

                Json.Append('"');
                Json.Append(JSON.Encode(Claim.Key));
                Json.Append("\":");

                if (Claim.Value == null)
                {
                    Json.Append("null");
                }
                else if (Claim.Value is string s)
                {
                    Json.Append('"');
                    Json.Append(JSON.Encode(s));
                    Json.Append('"');
                }
                else if (Claim.Value is bool b)
                {
                    if (b)
                    {
                        Json.Append("true");
                    }
                    else
                    {
                        Json.Append("false");
                    }
                }
                else if (Claim.Value is DateTime TP)
                {
                    Json.Append(((int)((TP.ToUniversalTime() - JwtToken.epoch).TotalSeconds)).ToString());
                }
                else if (Claim.Value is int i)
                {
                    Json.Append(i.ToString());
                }
                else if (Claim.Value is long l)
                {
                    Json.Append(l.ToString());
                }
                else if (Claim.Value is short sh)
                {
                    Json.Append(sh.ToString());
                }
                else if (Claim.Value is byte bt)
                {
                    Json.Append(bt.ToString());
                }
                else
                {
                    Json.Append('"');
                    Json.Append(JSON.Encode(Claim.Value.ToString()));
                    Json.Append('"');
                }
            }

            Json.Append('}');

            string PayloadStr = Json.ToString();

            byte[] PayloadBin = Encoding.UTF8.GetBytes(PayloadStr);
            string Payload    = JwtToken.Base64UrlEncode(PayloadBin);

            byte[] Signature;
            string Token = this.header + "." + Payload;

            lock (this.hmacSHA256)
            {
                Signature = this.hmacSHA256.ComputeHash(Encoding.ASCII.GetBytes(Token));
            }

            Token += "." + JwtToken.Base64UrlEncode(Signature);

            return(Token);
        }