Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking if Auth0 idToken has expired

Tags:

ios

swift

auth0

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.

like image 283
Alienbash Avatar asked Oct 31 '25 06:10

Alienbash


1 Answers

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
like image 110
Ben Scheirman Avatar answered Nov 01 '25 21:11

Ben Scheirman