rib / jsonwebtokens

A rust implementation of Json Web Tokens
MIT License
43 stars 7 forks source link

Examples broken? #10

Closed jwhance closed 3 years ago

jwhance commented 3 years ago

Relative Rust newcomer but the examples seem to be broken. You have the code:

let alg = Algorithm::new_rsa_pem_signer(AlgorithmID::RS256, pem_data)?;
let header = json!({ "alg": alg.name() });
let claims = json!({ "foo": "bar" });
let token = encode(&header, &claims, &alg)?;

But doing a cargo build on this leads to errors on both lines ending with ?; The errors are:

error[E0277]: the?operator can only be used in a function that returnsResultorOption(or another type that implementsTry)

I had better results doing it like this:

//
// https://github.com/rib/jsonwebtokens
//
use serde_json::json;
use std::fs;

use jsonwebtokens as jwt;
use jwt::{Algorithm, AlgorithmID, Verifier};

fn main() {
    // Read private key from file
    let private_key =
        fs::read_to_string("src/private_key.pem").expect("Something went wrong reading the file");

    let alg = Algorithm::new_rsa_pem_signer(AlgorithmID::RS256, &private_key.as_bytes()).unwrap();
    let header = json!({ "alg": alg.name(), "typ": "JWT" });
    let claims = json!({ "iss": "some-issuer.com", "aud": "some-audience" });
    let token_str = jwt::encode(&header, &claims, &alg).unwrap();

    println!("Token: {0}", token_str);

    // Read public key from file
    let public_key = fs::read_to_string("src/pkcs8_public_key.pem")
        .expect("Something went wrong reading the file");

    let alg = Algorithm::new_rsa_pem_verifier(AlgorithmID::RS256, &public_key.as_bytes()).unwrap();
    let verifier = Verifier::create()
        .issuer("some-issuer.com")
        .audience("some-audience")
        .build()
        .unwrap();

    match verifier.verify(&token_str, &alg) {
        Ok(output) => {
            println!("Verification: {0}", output);
        }
        Err(error) => {
            println!("Error: {:?}", error);
        }
    }
}
rib commented 3 years ago

Hi @jwhance, thanks for testing out jsonwebtokens!

I think the detail missing here is that your main() function doesn't currently return a Result. The '?' operator is really just syntax sugar for checking whether a Result (or Option) is Ok (or Some) and if not it immediately returns from the current function with the Err (or None).

If you were to change how you start your main function from

fn main() {

to

fn main() -> Result<(), jwt::error::Error>{

I think it might then work for you as you were expecting.

Here are some more details about this: https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/question-mark-in-main-and-tests.html

Since returning jwt::error::Error would be quite specific (it would then only work for returning jsonwwebtokens errors) you might want to consider using something like: anyhow for a convenient dynamic error / result type that can be used like this:

use anyhow::Result;

fn main() -> Result<()> {

Hope that helps!

jwhance commented 3 years ago

Yes, that did help thanks! Clearly a Rust noob issue but I don't think I'd have ever made the connection from that error to my main() fn.

rib commented 3 years ago

Cool, no worries!