I'm working JWT's in Rust and have come across a situation that I'm having some issues navigating. I'm new to both Rust and JWT's, so bare with me.
I'm using the jwt
crate found here.
What I want to do is create a Signed JWT that contains a header and claims. The claims have a single field, issuer
. I'm able to issue a new token with no issue.
fn issue_token(user_id: &str) -> Result<String, &'static str> {
let header: Header = Default::default();
let claims = RegisteredClaims {
issuer: Some("user who issued token".into()),
subject: Some(user_id.into()),
..Default::default()
};
let unsigned_token = Token::new(header, claims);
let key: Hmac<Sha256> =
Hmac::new_from_slice("secret_key".as_bytes()).map_err(|_e| "Invalid key")?;
let signed_token = unsigned_token
.sign_with_key(&key)
.map_err(|_e| "Sign error")?;
Ok(signed_token.into())
}
The issuer
claim is important. As there are different processes that have their own tokens. All of the issuers
have already registered their secret
with the main server. Now, other users will connect to a specific issuer
, validate who the user is, and will issue a JWT that has been signed. The user does not know what the secret
is, that's only known between the issuer
and the server.
What I'm trying to do, on the server-side, is read the claims
to identify who the issuer
is. Once I know who the issuer
is I then know what secret to use to verify the signature.
I have no issues verifying the token, and once I verify the token, I'm able to read the claims. But I need to read the claims first, and then verify the token.
beyond the basic examples for signing and verifying, the documentation is clear to me.
looking at the documentation for the crate, here, I've not been able to figure out how to implement what I'm attempting to do.
I've found what I believe to be what I'm looking for, here, parse_unverified
or Unverified
, but I'm struggling to figure out how to use either.
parse_unverified
looks to be the more promising of the two as the documentation states Not recommended. Parse the header and claims without checking the validity of the signature
Does anyone have any experience with Rust and the jwt
crate?
I believe I've gotten it partially figured out.
it starts with importing the correct crate options
use jwt::{Claims, Error, Header, RegisteredClaims, Token, Unverified, VerifyWithKey};
I can then create a new variable, like
let unverified: Result<Token<Header, Claims, Unverified<'_>>, Error> =
Token::parse_unverified(token);
Now this works, it builds and runs just fine. What I'm having an issue with now is actually parsing unverified
now.
the more that I look at it, I think this might have less to do with JWT and more to do with standard Rust operations. As its returning a Result
.
Any insight?
It's a standard Result
, so you have to unwrap that as usual with ?
to get at the Token
inside. Even though this doesn't verify the signature, it can still fail due to invalid base64/JSON encoding or JWT framing. (If there's an error here the token isn't even structurally valid, so there's no point in going further.)
let unverified: Token<Header, Claims, _> = Token::parse_unverified(token)?;
Now you can use any facilities provided by Token
on unverified
, e.g. unverified.claims()
.
You might want to parse with RegisteredClaims
though, which gives you easier access to the issuer field:
let unverified: Token<Header, RegisteredClaims, _> =
Token::parse_unverified(token)?;
let issuer = unverified.claims().issuer.as_ref()
.ok_or(MissingIssuerError)?;
issuer
will be a &String
. (MissingIssuerError
is a placeholder for an error you can raise if the issuer field is absent.)