Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I decode JWT (JSON web token) token in Swift?

Tags:

I have a JWT token like this

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

How can I decode this so that I can get the payload like this

{ "sub": "1234567890", "name": "John Doe", "admin": true }

like image 714
Siddhartha Chikatamalla Avatar asked Dec 01 '16 16:12

Siddhartha Chikatamalla


People also ask

Can I decode a JWT token?

By design, anyone can decode a JWT and read the contents of the header and payload sections. But we need access to the secret key used to create the signature to verify a token's integrity.

How do I read JWT token payload?

Each JWT contains a payload. The payload is a base64 encoded JSON object that sits between the two periods in the token. We can decode this payload by using atob() to decode the payload to a JSON string and use JSON. parse() to parse the string into an object.


2 Answers

If you are okay with using a library i would suggest this https://github.com/auth0/JWTDecode.swift

and then import the library import JWTDecode and execute.

let jwt = try decode(jwt: token) 

Since you didn't want to include this library i brought out the needed parts to make it work.

func decode(jwtToken jwt: String) -> [String: Any] {   let segments = jwt.components(separatedBy: ".")   return decodeJWTPart(segments[1]) ?? [:] }  func base64UrlDecode(_ value: String) -> Data? {   var base64 = value     .replacingOccurrences(of: "-", with: "+")     .replacingOccurrences(of: "_", with: "/")    let length = Double(base64.lengthOfBytes(using: String.Encoding.utf8))   let requiredLength = 4 * ceil(length / 4.0)   let paddingLength = requiredLength - length   if paddingLength > 0 {     let padding = "".padding(toLength: Int(paddingLength), withPad: "=", startingAt: 0)     base64 = base64 + padding   }   return Data(base64Encoded: base64, options: .ignoreUnknownCharacters) }  func decodeJWTPart(_ value: String) -> [String: Any]? {   guard let bodyData = base64UrlDecode(value),     let json = try? JSONSerialization.jsonObject(with: bodyData, options: []), let payload = json as? [String: Any] else {       return nil   }    return payload } 

Call it like this:

decode(jwtToken: TOKEN) 
like image 112
Viktor Gardart Avatar answered Sep 21 '22 14:09

Viktor Gardart


Iterating on Viktor's code:

  • Use nested functions to keep more modular
  • Utilize exceptions if bad token passed or other errors.
  • Simpler calculation of padding and utilization of padding function.

Hope it is useful:

func decode(jwtToken jwt: String) throws -> [String: Any] {      enum DecodeErrors: Error {         case badToken         case other     }      func base64Decode(_ base64: String) throws -> Data {         let base64 = base64             .replacingOccurrences(of: "-", with: "+")             .replacingOccurrences(of: "_", with: "/")         let padded = base64.padding(toLength: ((base64.count + 3) / 4) * 4, withPad: "=", startingAt: 0)         guard let decoded = Data(base64Encoded: padded) else {             throw DecodeErrors.badToken         }         return decoded     }      func decodeJWTPart(_ value: String) throws -> [String: Any] {         let bodyData = try base64Decode(value)         let json = try JSONSerialization.jsonObject(with: bodyData, options: [])         guard let payload = json as? [String: Any] else {             throw DecodeErrors.other         }         return payload     }      let segments = jwt.components(separatedBy: ".")     return try decodeJWTPart(segments[1]) } 
like image 36
possen Avatar answered Sep 18 '22 14:09

possen