Skip to content

Commit 66b357f

Browse files
committed
[verify] Support iat claims
1 parent 525410a commit 66b357f

File tree

3 files changed

+37
-3
lines changed

3 files changed

+37
-3
lines changed

JWT/JWT.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public enum InvalidToken : Printable {
77
case InvalidIssuer
88
case ExpiredSignature
99
case ImmatureSignature
10+
case InvalidIssuedAt
1011

1112
public var description:String {
1213
switch self {
@@ -18,6 +19,8 @@ public enum InvalidToken : Printable {
1819
return "Expired Signature"
1920
case .ImmatureSignature:
2021
return "The token is not yet valid (not before claim)"
22+
case .InvalidIssuedAt:
23+
return "Issued at claim (iat) is in the future"
2124
}
2225
}
2326
}
@@ -129,13 +132,22 @@ func validateClaims(payload:Payload, audience:String?, issuer:String?) -> Invali
129132
}
130133

131134
if let nbf = payload["nbf"] as? NSTimeInterval {
132-
let expiary = NSDate(timeIntervalSince1970: nbf)
133-
if expiary.compare(NSDate()) == .OrderedDescending {
135+
let date = NSDate(timeIntervalSince1970: nbf)
136+
if date.compare(NSDate()) == .OrderedDescending {
134137
return .ImmatureSignature
135138
}
136139
} else if let nbf:AnyObject = payload["nbf"] {
137140
return .DecodeError("Not before claim (nbf) must be an integer")
138141
}
139142

143+
if let iat = payload["iat"] as? NSTimeInterval {
144+
let date = NSDate(timeIntervalSince1970: iat)
145+
if date.compare(NSDate()) == .OrderedDescending {
146+
return .InvalidIssuedAt
147+
}
148+
} else if let iat:AnyObject = payload["iat"] {
149+
return .DecodeError("Issued at claim (iat) must be an integer")
150+
}
151+
140152
return nil
141153
}

JWTTests/JWTTests.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,27 @@ class JWTDecodeTests : XCTestCase {
7878
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3MjgxODg0OTF9.Tzhu1tu-7BXcF5YEIFFE1Vmg4tEybUnaz58FR4PcblQ"
7979
assertFailure(decode(jwt))
8080
}
81+
82+
// MARK: Issued at claim
83+
84+
func testIssuedAtClaimInThePast() {
85+
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MjgxODk3MjB9.hXBPQvdi9G5Kb5ySZUzAukYsP9wyBF172eTP9gNF9sg"
86+
assertSuccess(decode(jwt)) { payload in
87+
XCTAssertEqual(payload as NSDictionary, ["iat": 1428189720])
88+
}
89+
}
90+
91+
func testIssuedAtClaimInTheFuture() {
92+
// If this just started failing, hello 2024!
93+
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MjgxODg0OTF9.owHiJyJmTcW1lBW5y_Rz3iBfSbcNiXlbZ2fY9qR7-aU"
94+
assertFailure(decode(jwt))
95+
}
96+
97+
func testInvalidIssuedAtClaim() {
98+
// If this just started failing, hello 2024!
99+
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOlsxNzI4MTg4NDkxXX0.ND7QMWtLkXDXH38OaXM3SQgLo3Z5TNgF_pcfWHV_alQ"
100+
assertDecodeError(decode(jwt), "Issued at claim (iat) must be an integer")
101+
}
81102
}
82103

83104
// MARK: Helpers
@@ -114,7 +135,7 @@ func assertDecodeError(result:DecodeResult, error:String) {
114135
XCTFail("Incorrect decode error \(decodeError) != \(error)")
115136
}
116137
default:
117-
XCTFail("Failure for the wrong reason")
138+
XCTFail("Failure for the wrong reason \(failure)")
118139
}
119140
}
120141
}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ JWT.decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E
2727
- Issuer (`iss`) Claim
2828
- Expiration Time (`exp`) Claim
2929
- Not Before (`nbf`) Claim
30+
- Issued At (`iat`) Claim
3031

3132
## License
3233

0 commit comments

Comments
 (0)