Created
February 25, 2017 19:26
-
-
Save ArtemGr/a5d7be235b573a325e10cef1db778aed to your computer and use it in GitHub Desktop.
Using OpenSSL to verify the JWT RS256 signature in Rust.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use openssl::sign::Verifier; | |
use openssl::rsa::Rsa; | |
use openssl::pkey::PKey; | |
use openssl::hash::MessageDigest; | |
use serde_json::{self as json, Value as Json}; | |
pub fn firebase_id_token (headers: BTreeMap<&str, &str>, mut stream: &mut BufStream<TcpStream>) -> Result<(), String> { | |
#[derive(Deserialize, Debug)] | |
struct Post {firebase_id_token: String} | |
let post: Post = try_s! (read_json (&headers, stream)); | |
log! ([=post]); | |
#[derive(Deserialize, Debug)] struct TokenHeader {alg: String, kid: String} | |
let mut it = post.firebase_id_token.split ('.'); | |
let token_header_base64 = try_s! (it.next().ok_or ("!header")); | |
let token_header = try_s! (token_header_base64.from_base64()); | |
let token_header: TokenHeader = try_s! (json::from_slice (&token_header)); | |
let token_payload_base64 = try_s! (it.next().ok_or ("!body")); | |
let token_payload = try_s! (token_payload_base64.from_base64()); | |
let token_signature = try_s! (it.next().ok_or ("!signature")); | |
let token_signature = try_s! (token_signature.from_base64()); | |
// Try to verify the signature. | |
// cf. https://firebase.google.com/docs/auth/admin/verify-id-tokens#verify_id_tokens_using_a_third-party_jwt_library | |
// Alternative verification using https://github.com/mikkyang/rust-jwt/pull/8: | |
// use jwt::{Token, DefaultHeader, Registered}; | |
// let token = Token::<DefaultHeader, Registered>::parse (&post.firebase_id_token) .expect ("!parse"); | |
// log! ((token.verify (public_key.as_bytes()))); | |
if token_header.alg != "RS256" {return ERR! ("!RS256")} | |
let public_key = try_s! (kid_to_key (&token_header.kid) .ok_or ("!kid")); | |
let rsa = try_s! (Rsa::public_key_from_pem (public_key.as_bytes())); | |
let pkey = try_s! (PKey::from_rsa (rsa)); | |
let mut verifier = try_s! (Verifier::new (MessageDigest::sha256(), &pkey)); | |
try_s! (verifier.update (token_header_base64.as_bytes())); | |
try_s! (verifier.update (b".")); | |
try_s! (verifier.update (token_payload_base64.as_bytes())); | |
let verified = try_s! (verifier.finish (&token_signature)); | |
log! ([=verified]); | |
let token_payload: Json = try_s! (json::from_slice (&token_payload)); | |
log! ([=token_payload]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment