/// <summary> /// Contains information about a Java Web Token (JWT). JWT is defined in RFC 7519: /// https://tools.ietf.org/html/rfc7519 /// /// JWT are based on JSON Web Signature (JWS), defined in RFC 7515: /// https://tools.ietf.org/html/rfc7515 /// /// Signature algorithms are defined in RFC 7518: /// https://tools.ietf.org/html/rfc7518 /// </summary> public JwtToken(string Token) { this.token = Token; try { string[] Parts = Token.Split('.'); byte[] HeaderBin = Base64Url.Decode(this.header = Parts[0]); string HeaderString = Encoding.UTF8.GetString(HeaderBin); if (JSON.Parse(HeaderString) is Dictionary <string, object> Header) { if (Header.TryGetValue("typ", out object Typ)) { this.type = Typ as string; } if (!Header.TryGetValue("alg", out object Alg) || !(Alg is string AlgStr)) { throw new ArgumentException("Invalid alg header field.", nameof(Token)); } if (string.IsNullOrEmpty(AlgStr) || AlgStr.ToLower() == "none") { this.algorithm = null; } else if (!JwsAlgorithm.TryGetAlgorithm(AlgStr, out this.algorithm)) { throw new ArgumentException("Unrecognized algorithm reference in header field.", nameof(Token)); } } else { throw new Exception("Invalid JSON header."); } if (Parts.Length < 2) { throw new Exception("Claims set missing."); } byte[] ClaimsBin = Base64Url.Decode(this.payload = Parts[1]); string ClaimsString = Encoding.UTF8.GetString(ClaimsBin); if (JSON.Parse(ClaimsString) is Dictionary <string, object> Claims) { this.claims = Claims; foreach (KeyValuePair <string, object> P in Claims) { switch (P.Key) { case "iss": this.issuer = P.Value as string; break; case "sub": this.subject = P.Value as string; break; case "jti": this.id = P.Value as string; break; case "aud": if (P.Value is string AudStr) { this.audience = AudStr.Split(','); } else if (P.Value is Array) { List <string> Audience = new List <string>(); foreach (object Item in (Array)P.Value) { Audience.Add(Item.ToString()); } this.audience = Audience.ToArray(); } break; case "exp": if (P.Value is int ExpInt) { this.expiration = JSON.UnixEpoch.AddSeconds(ExpInt); } break; case "nbf": if (P.Value is int NbfInt) { this.notBefore = JSON.UnixEpoch.AddSeconds(NbfInt); } break; case "iat": if (P.Value is int IatInt) { this.issuedAt = JSON.UnixEpoch.AddSeconds(IatInt); } break; case "expires": break; } } } else { throw new Exception("Invalid JSON claims set."); } if (Parts.Length < 3) { throw new Exception("Signature missing."); } this.signature = Parts[2]; } catch (Exception ex) { throw new Exception("Unable to parse JWT token.", ex); } }