I want to generate a JWT token using RS256 algo in Swift. I do not see any support for this in the native libraries, but I am very new to this topic. Is this possible ?
Generate JWT token using RS256 algorithm
@eskimo Is it possible to create a JWT using RS256 on iOS?
See here IBM codebase: https://github.com/Kitura/Swift-JWT JWT.io: https://jwt.io/libraries?language=Swift
iOS has no high-level APIs for generating JWT tokens, so you’ll have to either write or acquire a library to do this based on lower-level security primitives. I don’t have a specific recommendation for you; my job means that I’m not allowed to use third-party code so I’ve never sat down to evaluate the various JWT libraries out there.
Also, in a lot of cases my JWT requirements are sufficiently simple that I just cons up the specific code I need. For example, I wrote the code pasted in below to generate tokens per the spec in Generating Tokens for API Requests.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
// The following is modelled on the C# code in Appendix C of [RFC
// 7515][rfc7515].
//
// [rfc7515]: <https://tools.ietf.org/html/rfc7515>
extension Data {
init?(base64URLEncodedString: String) {
let unpadded = base64URLEncodedString
.replacingOccurrences(of: "-", with: "+")
.replacingOccurrences(of: "_", with: "/")
let padCount: Int
switch unpadded.count % 4 {
case 0: padCount = 0
case 1: return nil
case 2: padCount = 2
case 3: padCount = 1
default: fatalError()
}
self.init(base64Encoded: String(unpadded + String(repeating: "=", count: padCount)))
}
var base64URLEncodedString: String {
let base64 = self.base64EncodedString()
return String(base64.split(separator: "=").first!)
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
}
}
func jwtHeader(kid: String) -> String {
struct Header: Codable {
var alg: String
var kid: String
var typ: String
}
let header = Header(alg: "ES256", kid: kid, typ: "JWT")
return try! JSONEncoder().encode(header).base64URLEncodedString
}
func jwtPayload(iss: String, exp: Date) -> String {
// We round the expiry date up because it’s not clear how servers are going
// to cope with fractional values.
let exp = Date(timeIntervalSinceReferenceDate: exp.timeIntervalSinceReferenceDate.rounded(.up))
struct Payload: Codable {
var iss: String
var exp: Date
var aud: String
}
let payload = Payload(iss: iss, exp: exp, aud: "appstoreconnect-v1")
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .secondsSince1970
return try! encoder.encode(payload).base64URLEncodedString
}
func jwtSignedToken(kid: String, iss: String, exp: Date, ecSECp256rKeyK keyK: Data) throws -> String {
let header = jwtHeader(kid: kid)
let payload = jwtPayload(iss: iss, exp: exp)
let signingInput = "\(header).\(payload)"
let privateKey = try P256.Signing.PrivateKey(rawRepresentation: keyK)
let sig = try privateKey.signature(for: Data(signingInput.utf8)).rawRepresentation
return "\(signingInput).\(sig.base64URLEncodedString)"
}
func jwtSignedToken(kid: String, iss: String, exp: Date, ecSECp256rPrivateKey privateKey: SecKey) throws -> String {
var errorCF: Unmanaged<CFError>? = nil
guard let keyData = SecKeyCopyExternalRepresentation(privateKey, &errorCF) as Data? else {
throw errorCF!.takeRetainedValue()
}
let keyK = keyData.suffix(0x20)
return try jwtSignedToken(kid: kid, iss: iss, exp: exp, ecSECp256rKeyK: keyK)
}
@eskimo this chunk for me has been very good reference for generating JWT. But could you pls elaborate or put up code to generating SecKey parameter for jwtSignedToken( method. from a .p8 file downloaded with apple sign in enabled ? I am trying to use it for generating JWT for POST https://appleid.apple.com/auth/token API call. I am new to this aspect of coding so finding it very difficult to any proper ref on the same.
code to generating
SecKey
parameter forjwtSignedToken
Check out Importing Cryptographic Keys.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"