Skip to content

Instantly share code, notes, and snippets.

@ArtemGr
Created February 25, 2017 19:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ArtemGr/a5d7be235b573a325e10cef1db778aed to your computer and use it in GitHub Desktop.
Save ArtemGr/a5d7be235b573a325e10cef1db778aed to your computer and use it in GitHub Desktop.
Using OpenSSL to verify the JWT RS256 signature in Rust.
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