Skip to content

Commit

Permalink
[decode] Support aud claim
Browse files Browse the repository at this point in the history
  • Loading branch information
kylef committed Apr 4, 2015
1 parent 39322ab commit 3800149
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 1 deletion.
23 changes: 22 additions & 1 deletion JWT/JWT.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public enum InvalidToken : Printable {
case ExpiredSignature
case ImmatureSignature
case InvalidIssuedAt
case InvalidAudience

public var description:String {
switch self {
Expand All @@ -21,6 +22,8 @@ public enum InvalidToken : Printable {
return "The token is not yet valid (not before claim)"
case .InvalidIssuedAt:
return "Issued at claim (iat) is in the future"
case InvalidAudience:
return "Invalid Audience"
}
}
}
Expand Down Expand Up @@ -111,6 +114,24 @@ func load(jwt:String) -> LoadResult {

// MARK: Validation

func validateAudience(payload:Payload, audience:String?) -> InvalidToken? {
if let audience = audience {
if let aud = payload["aud"] as? [String] {
if !contains(aud, audience) {
return .InvalidAudience
}
} else if let aud = payload["aud"] as? String {
if aud != audience {
return .InvalidAudience
}
} else {
return .DecodeError("Invalid audience claim, must be a string or an array of strings")
}
}

return nil
}

func validateIssuer(payload:Payload, issuer:String?) -> InvalidToken? {
if let issuer = issuer {
if let iss = payload["iss"] as? String {
Expand Down Expand Up @@ -139,7 +160,7 @@ func validateDate(payload:Payload, key:String, comparison:NSComparisonResult, fa
}

func validateClaims(payload:Payload, audience:String?, issuer:String?) -> InvalidToken? {
return validateIssuer(payload, issuer) ??
return validateIssuer(payload, issuer) ?? validateAudience(payload, audience) ??
validateDate(payload, "exp", .OrderedAscending, .ExpiredSignature, "Expiration time claim (exp) must be an integer") ??
validateDate(payload, "nbf", .OrderedDescending, .ImmatureSignature, "Not before claim (nbf) must be an integer") ??
validateDate(payload, "iat", .OrderedDescending, .InvalidIssuedAt, "Issued at claim (iat) must be an integer")
Expand Down
26 changes: 26 additions & 0 deletions JWTTests/JWTTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,32 @@ class JWTDecodeTests : XCTestCase {
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOlsxNzI4MTg4NDkxXX0.ND7QMWtLkXDXH38OaXM3SQgLo3Z5TNgF_pcfWHV_alQ"
assertDecodeError(decode(jwt), "Issued at claim (iat) must be an integer")
}

// MARK: Audience claims

func testAudiencesClaim() {
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibWF4aW5lIiwia2F0aWUiXX0.AlM2nO839pAUU1NiAeRZmMnBDbw53Hc5ElPQJVNyfJY"
assertSuccess(decode(jwt, audience:"maxine")) { payload in
XCTAssertEqual(payload as NSDictionary, ["aud": ["maxine", "katie"]])
}
}

func testAudienceClaim() {
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJreWxlIn0.VEB_n06pTSLlTXPFkc46ARADJ9HXNUBUPo3VhL9RDe4"
assertSuccess(decode(jwt, audience:"kyle")) { payload in
XCTAssertEqual(payload as NSDictionary, ["aud": "kyle"])
}
}

func testMismatchAudienceClaim() {
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJreWxlIn0.VEB_n06pTSLlTXPFkc46ARADJ9HXNUBUPo3VhL9RDe4" // kyle
assertFailure(decode(jwt, audience:"maxine"))
}

func testMissingAudienceClaim() {
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w"
assertFailure(decode(jwt, audience:"kyle"))
}
}

// MARK: Helpers
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ JWT.decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E
- Expiration Time (`exp`) Claim
- Not Before (`nbf`) Claim
- Issued At (`iat`) Claim
- Audience (`aud`) Claim

## License

Expand Down

0 comments on commit 3800149

Please sign in to comment.