kreactive / JSONWebToken

Swift lib for decoding, validating, signing and verifying JWT
MIT License
36 stars 25 forks source link

Trying to sign a JWT Token with RSA256 #4

Closed Headstock67 closed 7 years ago

Headstock67 commented 7 years ago

Hi there

I need to mint a JWT using RS256 to use to validate a connection to a Google Firebase database via my app.

I have a Private Key from Firebase that looks something like:

"-----BEGIN PRIVATE KEY-----\nMIIEvQIBADds4tTHG53.........................................oBDP6N8=\n-----END PRIVATE KEY-----\n"

This is supplied in a string format and there are around 1600 characters in the key.

I can create the payload with the required claims, however I am struggling with taking the payload and creating a signed token using RSA256.

From your instructions I determined that I might need to do the following:

Use RSAPKCS1Signer to generate signed token:

let payload : JSONWebToken.Payload
let privateKey : RSAKey

let signer = RSAPKCS1Signer(hashFunction: .SHA256, key: privateKey) 
let jwt = try JSONWebToken(payload : payload, signer : signer)
let rawJWT : String = jwt.rawString

The two issues I have is that the privateKey won't accept the Private Key string I have, I believe it is looking for a DER certificate format.

I also cannot see how to set it to use RSA256, which is a requirement for the Firebase Database.

Can you please help shed some light on how best to approach this?

Thanks for any help you can provide.

antoinepalazzolo commented 7 years ago

This kind of private key should work (you can look at the tests for exemples) but the newline characters should not be escaped (no \n). How do you create the RSAKey and what is the error ?

Headstock67 commented 7 years ago

Thanks for taking a look at this.

I removed the newline characters.

I set a variable privateKey to the string:

privateKey = "-----BEGIN PRIVATE KEY-----MIIEvQIBAD............etc etc......END PRIVATEKEY-----"`

Then I get the error at line:

let signer = RSAPKCS1Signer(hashFunction: .SHA256, key: privateKey)

The error is "cannot convert value of type 'String' to expected argument type 'RSAKey'

The privateKey was provided by Google Firebase in the form of a text file. I have copied the private_key from this file. The file comes in the following format:

{ "type": "service_account", "project_id": "myappname", "private_key_id": "private_key_id goes here................", "private_key": "-----BEGIN PRIVATE KEY-----MIIEvQIBADANBgk..........etc.etc.etc.-----END PRIVATE KEY-----", "client_email": "firebase-adminsdk-ah123@myappname.iam.gserviceaccount.com", "client_id": "client_id goes here..", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://accounts.google.com/o/oauth2/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-ah123%40myappname.iam.gserviceaccount.com" }

antoinepalazzolo commented 7 years ago

The security framework do not support importing this kind of private key (only public). One solution is to generate a p12 identity file :

Use the p12 to sign JWTs :

let p12Url =   Bundle.main.url(forResource: "identity", withExtension: ".p12")
let p12Data = try! Data(contentsOf: p12Url)
let keys = try RSAKey.keysFromPkcs12Identity(p12Data, passphrase : <p12 pass>) 
let signer = RSAPKCS1Signer(hashFunction: .sha256, key: keys.private)
let jwt = try JSONWebToken(payload : <payload>, signer : signer)

One last thing : I don't know how firebase work, but if you include the private key or the p12 in the app bundle, anyone will have access to the key and it may not be something you want.