I have a Swift App, which implements the web login for Auth0. On successful login, i receive an access token and and idToken, which i both store locally in my Keychain. Upon next login, i first check, if the access token (stored in keychain) is still valid by
Auth0
.authentication()
.userInfo(withAccessToken: accessToken)
.start { result in
switch result {
case .success(result: let profile):
print("access token still valid")
On success does not have to login again. The issue i'm having however, is, that my idToken might be expired already, even though my access token is still valid, which leads to errors when i request my (GraphQL) backend with this idToken. So how do i solve this? Is there a way to check, if my idToken has expired in Swift? Because if there is no way to check, i would have to ask for login, even with potentially not expired tokens. That wouldn't make sense.
An idToken is a JSON Web Token (JWT), so the metadata is readable. To see what this looks like, paste your token into jwt.io and see what the format is.
For example, take this JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZXhwIjoiMTUwNDc1MzQ0NSIsImFkbWluIjp0cnVlfQ.ggeW2vGcdWKNWmICRfTZ8qcBOQlu38DzaO8t_6aNuHQ
It is broken into 3 parts: the header, the payload, and the signature. The expiration is in the payload section.
We just need to base64 decode this.
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvbiBTbm93IiwiZXhwIjoiMTUwNDc1MzQ0NSIsImFkbWluIjp0cnVlfQ.aCiqyVAAmHizPshrcdy8jwgHvBg4Diz2YY2e1INjoPg"
// get the payload part of it
var payload64 = jwt.components(separatedBy: ".")[1]
// need to pad the string with = to make it divisible by 4,
// otherwise Data won't be able to decode it
while payload64.count % 4 != 0 {
payload64 += "="
}
print("base64 encoded payload: \(payload64)")
let payloadData = Data(base64Encoded: payload64,
options:.ignoreUnknownCharacters)!
let payload = String(data: payloadData, encoding: .utf8)!
print(payload)
This prints out:
{"sub":"1234567890","name":"Jon Snow","exp":"1504753445","admin":true}
The exp is your expiration date. You can pass this off to a JSON serializer to get the date:
let json = try! JSONSerialization.jsonObject(with: payloadData, options: []) as! [String:Any]
let exp = json["exp"] as! Int
let expDate = Date(timeIntervalSince1970: TimeInterval(exp))
let isValid = expDate.compare(Date()) == .orderedDescending
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With