Skip to content

Commit 3800149

Browse files
committed
[decode] Support aud claim
1 parent 39322ab commit 3800149

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

JWT/JWT.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public enum InvalidToken : Printable {
88
case ExpiredSignature
99
case ImmatureSignature
1010
case InvalidIssuedAt
11+
case InvalidAudience
1112

1213
public var description:String {
1314
switch self {
@@ -21,6 +22,8 @@ public enum InvalidToken : Printable {
2122
return "The token is not yet valid (not before claim)"
2223
case .InvalidIssuedAt:
2324
return "Issued at claim (iat) is in the future"
25+
case InvalidAudience:
26+
return "Invalid Audience"
2427
}
2528
}
2629
}
@@ -111,6 +114,24 @@ func load(jwt:String) -> LoadResult {
111114

112115
// MARK: Validation
113116

117+
func validateAudience(payload:Payload, audience:String?) -> InvalidToken? {
118+
if let audience = audience {
119+
if let aud = payload["aud"] as? [String] {
120+
if !contains(aud, audience) {
121+
return .InvalidAudience
122+
}
123+
} else if let aud = payload["aud"] as? String {
124+
if aud != audience {
125+
return .InvalidAudience
126+
}
127+
} else {
128+
return .DecodeError("Invalid audience claim, must be a string or an array of strings")
129+
}
130+
}
131+
132+
return nil
133+
}
134+
114135
func validateIssuer(payload:Payload, issuer:String?) -> InvalidToken? {
115136
if let issuer = issuer {
116137
if let iss = payload["iss"] as? String {
@@ -139,7 +160,7 @@ func validateDate(payload:Payload, key:String, comparison:NSComparisonResult, fa
139160
}
140161

141162
func validateClaims(payload:Payload, audience:String?, issuer:String?) -> InvalidToken? {
142-
return validateIssuer(payload, issuer) ??
163+
return validateIssuer(payload, issuer) ?? validateAudience(payload, audience) ??
143164
validateDate(payload, "exp", .OrderedAscending, .ExpiredSignature, "Expiration time claim (exp) must be an integer") ??
144165
validateDate(payload, "nbf", .OrderedDescending, .ImmatureSignature, "Not before claim (nbf) must be an integer") ??
145166
validateDate(payload, "iat", .OrderedDescending, .InvalidIssuedAt, "Issued at claim (iat) must be an integer")

JWTTests/JWTTests.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,32 @@ class JWTDecodeTests : XCTestCase {
9999
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOlsxNzI4MTg4NDkxXX0.ND7QMWtLkXDXH38OaXM3SQgLo3Z5TNgF_pcfWHV_alQ"
100100
assertDecodeError(decode(jwt), "Issued at claim (iat) must be an integer")
101101
}
102+
103+
// MARK: Audience claims
104+
105+
func testAudiencesClaim() {
106+
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibWF4aW5lIiwia2F0aWUiXX0.AlM2nO839pAUU1NiAeRZmMnBDbw53Hc5ElPQJVNyfJY"
107+
assertSuccess(decode(jwt, audience:"maxine")) { payload in
108+
XCTAssertEqual(payload as NSDictionary, ["aud": ["maxine", "katie"]])
109+
}
110+
}
111+
112+
func testAudienceClaim() {
113+
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJreWxlIn0.VEB_n06pTSLlTXPFkc46ARADJ9HXNUBUPo3VhL9RDe4"
114+
assertSuccess(decode(jwt, audience:"kyle")) { payload in
115+
XCTAssertEqual(payload as NSDictionary, ["aud": "kyle"])
116+
}
117+
}
118+
119+
func testMismatchAudienceClaim() {
120+
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJreWxlIn0.VEB_n06pTSLlTXPFkc46ARADJ9HXNUBUPo3VhL9RDe4" // kyle
121+
assertFailure(decode(jwt, audience:"maxine"))
122+
}
123+
124+
func testMissingAudienceClaim() {
125+
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w"
126+
assertFailure(decode(jwt, audience:"kyle"))
127+
}
102128
}
103129

104130
// MARK: Helpers

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ JWT.decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E
2828
- Expiration Time (`exp`) Claim
2929
- Not Before (`nbf`) Claim
3030
- Issued At (`iat`) Claim
31+
- Audience (`aud`) Claim
3132

3233
## License
3334

0 commit comments

Comments
 (0)