Closed dakom closed 2 years ago
x509
are not supported currently.
@dakom I ran into the same issue and was able to create a key from the Firebase RSA components. I wrote an article about this, since I found multiple people asking similar questions: https://medium.com/@maylukas/firebase-token-authentication-in-rust-a1885f0982df
@Keats If you have some time to review my solution I would be very happy :)
There's a typo in the code example: UnkownKeyAlgorithm
Overall JwkVerifier
is something I thought adding to jsonwebtoken but wasn't sure on the best way to implement it. If we can find a generic enough struct/impl, it could be added directly in the lib.
The jsonwebtoken library only verifies the expiry date and signature, so we need to check the audience, and the issue matches afterward.
You can check it with jsonwebtoken automatically: https://docs.rs/jsonwebtoken/7.1.1/jsonwebtoken/struct.Validation.html
Great article otherwise!
@Keats Oh thanks. Did not see it. I will change it to use jsonwebtoken to verify the issuer and audience. I won't have time today but some day next week. Thanks for checking the article 😊
@Keats: Okay. I updated the post and the example on Github. Bit late but still 😆
Overall JwkVerifier is something I thought adding to jsonwebtoken but wasn't sure on the best way to implement it. If we can find a generic enough struct/impl, it could be added directly in the lib.
Maybe it would be possible to add a key_id parameter to the DecodingKey struct. Then it would be possible to select the proper key from a list of provided keys based on the specified key id in the token header. The JwkVerifier struct could then have a generic parameter for the claims to deserialize and could be initialized with the verification parameters.
Regarding verification: Does it maybe make sense to make the DecodingKey aware of its algorithm? Currently, it is set in the Verification struct but I think it might be better to move it to the DecodingKey. Then a token can just be verified with a DecodingKey and no further information is required by the verifying component as the key will already provide the proper algorithm. So the DecodingKey could receive a "verify_signature" method and the Verification would then just validate metadata (expiry, issuer, audience, ...).
If no key id is provided which might be the case if a shared secret is used, the verifier would just use the first one.
Just some random ideas 😁 I don't know if any of these suggestions are worth anything since I don't know your library in detail but maybe it helps.
FWIW, you can simply use the openssl crate to extract the public key from the x509:
let certificate = openssl::x509::X509::from_pem(v.as_bytes())?;
let pem_bytes = certificate.public_key()?.rsa()?.public_key_to_pem()?;
However, for some reason, I couldn't get this to work with der, and had to go through pem.
@FrancoisChabot this is exactly what I needed, thanks!
@FrancoisChabot dude, you made my day ! thanks !! 👍 @maylukas your article on Medium is dope too
Instead of using the openssl crate, you can also use the command line to extract the public key from the pem certificate file:
openssl x509 -pubkey -noout -in certificate.pem
This will output something like:
-----BEGIN PUBLIC KEY-----
xxx
-----END PUBLIC KEY-----
Then use it in your code like:
let public_key = b"-----BEGIN PUBLIC KEY-----
xxx
-----END PUBLIC KEY-----";
DecodingKey::from_rsa_pem(public_key).unwrap()
FWIW, you can simply use the openssl crate to extract the public key from the x509:
let certificate = openssl::x509::X509::from_pem(v.as_bytes())?; let pem_bytes = certificate.public_key()?.rsa()?.public_key_to_pem()?;
However, for some reason, I couldn't get this to work with der, and had to go through pem.
@FrancoisChabot You are a lifesaver!
The docs at https://firebase.google.com/docs/auth/admin/verify-id-tokens suggest getting the public key via https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com
I tried loading this in via
DecodingKey::from_rsa_pem
but no luck so far.Does the
x509
string need to be converted to something else before loading?