/// <summary> /// Validation logic for registered claim: JWT ID. /// Successful if claim is present and resolves to true when passed through the provided validator. /// </summary> /// <param name="claims"></param> /// <param name="variables"></param> /// <returns></returns> public bool Check(JObject claims, ClaimsCheckerVariables variables) { var jsonJti = claims[RegisteredClaimNames.JwtId]; if (jsonJti == null) return false; return JwtIdValidator(jsonJti.ToString()); }
/// <summary> /// Validation logic for registered claim: Not Before. /// Successful if claim is present and current time is at or after the claim value, using leeway period if provided. /// </summary> /// <param name="claims"></param> /// <param name="variables"></param> /// <returns></returns> public bool Check(JObject claims, ClaimsCheckerVariables variables) { var jsonNotBefore = claims[RegisteredClaimNames.NotBefore]; if (jsonNotBefore == null) return false; return jsonNotBefore.ToObject<int>() <= UnixTimeConvert.FromDateTime(DateTime.UtcNow + Leeway); }
/// <summary> /// Validation logic for registered claim: Subject. /// Successful if the claim is not present or the Subject property value in the checker variables equals to the claim value. /// </summary> /// <param name="claims"></param> /// <param name="variables"></param> /// <returns></returns> public bool Check(JObject claims, ClaimsCheckerVariables variables) { var jsonSubject = claims[RegisteredClaimNames.Subject]; if (jsonSubject == null) return true; if (string.IsNullOrEmpty(variables.Subject)) return false; return jsonSubject.ToString() == variables.Subject; }
/// <summary> /// Validation logic for AuthorizeAttribute 'User' claim. /// Successful if the Users property is not set in the checker variables or Users property values contain the claim value. /// </summary> /// <param name="claims"></param> /// <param name="variables"></param> /// <returns></returns> public bool Check(JObject claims, ClaimsCheckerVariables variables) { if (string.IsNullOrEmpty(variables.Users)) return true; var users = variables.Users.Split(',').Select(Q => Q.Trim()).Where(Q => !string.IsNullOrEmpty(Q)).ToList(); if (!users.Any()) throw new Exception("No Users can be inferred from the AuthorizeAttribute property value."); var jsonUser = claims[this.ClaimName]; if (jsonUser == null) return false; var user = jsonUser.ToString().Trim(); return users.Where(Q => Q.Equals(user, StringComparison.InvariantCultureIgnoreCase)).Any(); }
/// <summary> /// Validation logic for registered claim: Audience. /// Successful if the claim is not present or the claim values contain the Audience property value in the checker variables. /// </summary> /// <param name="claims"></param> /// <param name="variables"></param> /// <returns></returns> public bool Check(JObject claims, ClaimsCheckerVariables variables) { //https://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#rfc.section.4.1.3 //4.1.3. "aud" (Audience) Claim //Each principal intended to process the JWT MUST identify itself with a value in the audience claim. //If the principal processing the claim does not identify itself with a value in the aud claim //when this claim is present, then the JWT MUST be rejected. Use of this claim is OPTIONAL. //So, basically it's like a reverse Role. var jsonAudience = claims[RegisteredClaimNames.Audience]; if (jsonAudience == null) return true; if (string.IsNullOrEmpty(variables.Audience)) return false; var audiences = jsonAudience.ToObject<List<string>>(); return audiences.Where(Q => Q == variables.Audience).Any(); }
public void NoClaims() { var jwtCodec = new JwtCodec(new JwtConfig { KeyConfig = new KeyConfig { Value = new byte[] { 237, 77, 131, 121, 90, 110, 35, 231, 70, 26, 39, 55, 158, 159, 179, 231 } }, Signer = new HS256Signer() }); var token = jwtCodec.Encode(new { UserId = 1, Username = "******" }); var variables = new ClaimsCheckerVariables(); variables.Roles = "Admin, Customer"; var success = jwtCodec.Decode(token, new List<IClaimsChecker> { new RoleChecker() }, variables); Assert.False(success); }
public void Fail2() { var jwtCodec = new JwtCodec(new JwtConfig { KeyConfig = new KeyConfig { Value = new byte[] { 237, 77, 131, 121, 90, 110, 35, 231, 70, 26, 39, 55, 158, 159, 179, 231 } }, Signer = new HS256Signer() }); var token = jwtCodec.Encode(new { UserId = 1, Username = "******" }, Audience: new List<string> { "UserPanel", "ShoppingCart", "CustomerService" }); var variables = new ClaimsCheckerVariables(); variables.Audience = null; var success = jwtCodec.Decode(token, new List<IClaimsChecker> { new AudienceChecker() }, variables); Assert.False(success); }
/// <summary> /// Validates a JWT using the helper configuration. /// If successful, run claims check against the token using Roles and checker variables. /// </summary> /// <param name="token"></param> /// <param name="claimsCheckers"></param> /// <param name="variables"></param> /// <returns></returns> public bool Decode(string token, IEnumerable<IClaimsChecker> claimsCheckers, ClaimsCheckerVariables variables) { if (!Decode(token)) return false; if (claimsCheckers == null) return true; if (!claimsCheckers.Any()) return true; try { var jwt = JwtObject.Parse(token); var claims = JObject.Parse(jwt.ClaimsAsJson()); foreach (var checker in claimsCheckers) { if (!checker.Check(claims, variables)) return false; } return true; } catch { return false; } }
/// <summary> /// Validation logic for registered claim: Issued At. /// Successful if claim is present. /// </summary> /// <param name="claims"></param> /// <param name="variables"></param> /// <returns></returns> public bool Check(JObject claims, ClaimsCheckerVariables variables) { var jsonIssuedAt = claims[RegisteredClaimNames.IssuedAt]; return (jsonIssuedAt != null); }
public void Sample() { var jwtConfig = new JwtConfig { KeyConfig = new KeyConfig { Value = new byte[] { 237, 77, 131, 121, 90, 110, 35, 231, 70, 26, 39, 55, 158, 159, 179, 231 } }, Signer = new HS256Signer() }; var jwtCodec = new JwtCodec(jwtConfig); var claims = new { UserId = 1, Username = "******", Role = "Admin" }; string token1 = jwtCodec.Encode(claims); //eyJVc2VySWQiOjEsIlVzZXJuYW1lIjoiamFja2FudG9ubyIsIlJvbGUiOiJBZG1pbiJ9.yCY897l0Qt4pNWAMkLebcwjygiqbkQcFMfNW+BZjCUo= output.WriteLine(token1); bool isValid = jwtCodec.Decode(token1); //True output.WriteLine(isValid.ToString()); var now = new DateTime(2015, 11, 23, 14, 0, 0, DateTimeKind.Utc); var token2 = jwtCodec.Encode(claims, Issuer: "accelist.com", Subject: "Authentication", Audience: new List<string> { "EmployeePortal", "SecurityCenter" }, ExpirationTime: now.AddHours(12), NotBefore: now, IssuedAt: now, JwtId: Guid.Parse("2628850a-e1a9-4897-bf78-355fa5367ca1").ToString() ); //eyJVc2VySWQiOjEsIlVzZXJuYW1lIjoiamFja2FudG9ubyIsIlJvbGUiOiJBZG1pbiIsImlzcyI6ImFjY2VsaXN0LmNvbSIsInN1YiI6IkF1dGhlbnRpY2F0aW9uIiwiYXVkIjpbIkVtcGxveWVlUG9ydGFsIiwiU2VjdXJpdHlDZW50ZXIiXSwiZXhwIjoxNDQ4MzMwNDAwLCJuYmYiOjE0NDgyODcyMDAsImlhdCI6MTQ0ODI4NzIwMCwianRpIjoiMjYyODg1MGEtZTFhOS00ODk3LWJmNzgtMzU1ZmE1MzY3Y2ExIn0=.d/ON3EdLGOC0VPcKwiLE15WZKoM9Mwx+3P2QQIhSP8U= output.WriteLine(token2); /// Validation logic for registered claim: Issuer. /// Successful if the Issuer property value equals the claim or claim is not provided. var issChecker = new IssuerChecker(); /// Validation logic for registered claim: Subject. /// Successful if the Subject property value equals the claim or claim is not provided. var subChecker = new SubjectChecker(); /// Validation logic for registered claim: Audience. /// Successful if the claim is not present or the Audience property value is in the said claim. var audChecker = new AudienceChecker(); var leeway = new TimeSpan(0, 5, 0); /// Validation logic for registered claim: Expiration Time. /// Successful if claim exists and current time is at or before the said claim, using leeway period if provided. var expChecker = new ExpirationTimeChecker(leeway); /// Authorization logic for registered claim: Not Before. /// Successful if claim exists and current time is at or after the said claim, using leeway period if provided. var nbfChecker = new NotBeforeChecker(leeway); /// Authorization logic for registered claim: Issued At. /// Successful if claim exists. var iatChecker = new IssuedAtChecker(); /// Validation logic for registered claim: JWT ID. /// Successful if claims exist and resolves to true when passed through the validator. Func<string, bool> jtiValidator = (jti) => { return true; }; var jtiChecker = new JwtIdChecker(jtiValidator); /// Validation logic for AuthorizeAttribute 'Role' claim. /// Successful if the Roles property is not set or the claim is in the Roles property value. var roleChecker = new RoleChecker("Role"); /// Validation logic for AuthorizeAttribute 'User' claim. /// Successful if the User property is not set or the claim is in the Users property value. var userChecker = new UserChecker("Username"); var claimsCheckers = new List<IClaimsChecker> { issChecker, subChecker, audChecker, expChecker, nbfChecker, iatChecker, jtiChecker, roleChecker, userChecker }; var variables = new ClaimsCheckerVariables { Issuer = "accelist.com", Subject = "Administration", Roles = "Admin", Audience = "EmployeePortal", Users = "jackantono, ryanelian", }; jwtCodec.Decode(token2, claimsCheckers, variables); var jwtObj = JwtObject.Parse(token2); var extractClaims = jwtObj.ClaimsAsObject<ClaimsTest>(); output.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(extractClaims, Newtonsoft.Json.Formatting.Indented)); }