Validate JWT token with RS256 or RS512 with Swift

2020-07-18 07:18发布

问题:

I am building an iOS application in Swift that needs to be able to validate a JWT token signature with a public key certificate using either RS256 or RS512.

I've been trying to find libraries that support such functionalities but have had issues implementing the ones I have found.

My question is therefore what the recommended way to implement such functionality for a Swift iOS app is?

The ideal scenario is to be able to use one of the recognized frameworks on JWT.io. The only Swift library on JWT.io that supports RS256 or RS512 is the following library: https://github.com/vapor/jwt

The functionalities this library supports are ideal, but it however requires implementation through Swift Package Manager, and is built using Vapor. Swift Package manager is currently not supported for iOS, but I've read that there are workarounds to get the swift package manager to work with iOS apps. These are workarounds is willing to take if the Library could function on the the iOS application. However as the library is built for Vapor, my question is if it is even possible to get the library to function on the iOS app I'm building?

If it is not possible use this Library, are there any other libraries that are recommended to use? If not, what is the recommended way to implement this requested functionality? Are there recommended Objective-C libraries that could function on the application?

Thanks in Advance!

Edit: By validating I mean that I would like to verify that the signature in the token is correct, meaning that the JWT token has been signed with a private key on the server that the public key cert on the application is corresponding to. Not just decode the Base64Check payload.

Edit 2: What I'm trying to achieve is functionality that supports asymmetric keys, meaning that the secret must not be stored on both the server and the client application. I'm trying to achieve that the application is only containing non secret information, hence a public key certificate.

回答1:

Not sure if you are still stuck on this, but I was in the exact same situation and it took a while to figure out. I ended up using the JWT pod and was pushed in the right direction by this article. I'll summarize my findings.

Due to Apple dropping OpenSSL in favor of their own Security libs the input has to be a self signed certificate containing the public key. With OpenSSL do something like this using your private key as input:

openssl req -key private_key.pem -new -x509 -days 3650 -out selfsigned_cert.pem

Then convert the PEM format to DER, which is basically removing the b64 armoring:

openssl x509 -outform der -in selfsigned_cert.pem -out selfsigned_cert.der

Add the .der file to Supporting Files in your Xcode project and then read the certificate data from disk and base64 encode it:

NSURL *fileURL = [NSURL fileURLWithPath:[bundle pathForResource: @"selfsigned_cert" ofType:@"der"]];
NSData *certificateData = [NSData dataWithContentsOfURL:fileURL];
// Probably want to do a nil-check on certificateData here
NSString *certificateStr = [JWTBase64Coder base64UrlEncodedStringWithData:certificateData];

And then plug it into the JWT decoder:

JWTBuilder *decodeBuilder = [JWTBuilder decodeMessage:token] // your JWT
  .secret(certificateStr)
  .algorithmName(algorithmName); // From your token or a predefined string
NSDictionary *payload = decodeBuilder.decode;

You can check if the decoding/verification was successful or not by checking for an error in the builder:

if(decodeBuilder.jwtError != nil) { /* do stuff */ }

Edit: As a side note. Converting to DER and then b64 encode it might seem redundant, it basically just removes the anchor lines from the PEM format. The reason why I have a .der file on disk is because that's what we can use directly with the Security libs if we need to.