diff --git a/src/main.rs b/src/main.rs index 5bb6f44..18d5d8d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -246,7 +246,26 @@ fn config_options<'a, 'b>() -> App<'a, 'b> { ), ).subcommand( SubCommand::with_name("decode") - .about("Decode a JWT") + .about("Decode a JWT (no signature check is performed)") + .arg( + Arg::with_name("jwt") + .help("the jwt to decode") + .index(1) + .required(true), + ).arg( + Arg::with_name("iso_dates") + .help("display unix timestamps as ISO 8601 dates") + .takes_value(false) + .long("iso8601") + ).arg( + Arg::with_name("json") + .help("render decoded JWT as JSON") + .long("json") + .short("j"), + ), + ).subcommand( + SubCommand::with_name("verify") + .about("Decode a JWT and validate its signature") .arg( Arg::with_name("jwt") .help("the jwt to decode") @@ -271,7 +290,7 @@ fn config_options<'a, 'b>() -> App<'a, 'b> { .takes_value(true) .long("secret") .short("S") - .default_value(""), + .required(true), ).arg( Arg::with_name("json") .help("render decoded JWT as JSON") @@ -483,20 +502,7 @@ fn encode_token(matches: &ArgMatches) -> JWTResult { .and_then(|secret| encode(&header, &claims, &secret)) } -fn decode_token( - matches: &ArgMatches, -) -> ( - JWTResult>, - JWTResult>, - OutputFormat, -) { - let algorithm = translate_algorithm(SupportedAlgorithms::from_string( - matches.value_of("algorithm").unwrap(), - )); - let secret = match matches.value_of("secret").map(|s| (s, !s.is_empty())) { - Some((secret, true)) => Some(decoding_key_from_secret(&algorithm, secret)), - _ => None, - }; +fn decode_token(matches: &ArgMatches) -> (String, JWTResult>, OutputFormat) { let jwt = matches .value_of("jwt") .map(|value| { @@ -516,13 +522,6 @@ fn decode_token( .trim() .to_owned(); - let secret_validator = Validation { - leeway: 1000, - algorithms: vec![algorithm], - validate_exp: !matches.is_present("ignore_exp"), - ..Default::default() - }; - let token_data = dangerous_insecure_decode::(&jwt).map(|mut token| { if matches.is_present("iso_dates") { token.claims.convert_timestamps(); @@ -532,10 +531,7 @@ fn decode_token( }); ( - match secret { - Some(secret_key) => decode::(&jwt, &secret_key.unwrap(), &secret_validator), - None => dangerous_insecure_decode::(&jwt), - }, + jwt, token_data, if matches.is_present("json") { OutputFormat::Json @@ -545,6 +541,24 @@ fn decode_token( ) } +fn verify_token(jwt: String, matches: &ArgMatches) -> JWTResult> { + let algorithm = translate_algorithm(SupportedAlgorithms::from_string( + matches.value_of("algorithm").unwrap(), + )); + + let secret_validator = Validation { + leeway: 1000, + algorithms: vec![algorithm], + validate_exp: !matches.is_present("ignore_exp"), + ..Default::default() + }; + + let secret = matches.value_of("secret").unwrap(); + let secret_key = decoding_key_from_secret(&algorithm, secret).unwrap(); + + decode::(&jwt, &secret_key, &secret_validator) +} + fn print_encoded_token(token: JWTResult) { match token { Ok(jwt) => { @@ -553,25 +567,24 @@ fn print_encoded_token(token: JWTResult) { } else { print!("{}", jwt); } - exit(0); } Err(err) => { bunt::eprintln!("{$red+bold}Something went awry creating the jwt{/$}\n"); eprintln!("{}", err); - exit(1); } } } fn print_decoded_token( - validated_token: JWTResult>, + validated_token: Option>>, token_data: JWTResult>, + options_algorithm: Option, format: OutputFormat, ) { - if let Err(err) = &validated_token { - match err.kind() { + match validated_token { + Some(Err(ref err)) => match err.kind() { ErrorKind::InvalidToken => { - bunt::println!("{$red+bold}The JWT provided is invalid{/$}") + bunt::eprintln!("{$red+bold}The JWT provided is invalid{/$}") } ErrorKind::InvalidSignature => { bunt::eprintln!("{$red+bold}The JWT provided has an invalid signature{/$}") @@ -586,7 +599,7 @@ fn print_decoded_token( bunt::eprintln!("{$red+bold}The token has expired (or the `exp` claim is not set). This error can be ignored via the `--ignore-exp` parameter.{/$}") } ErrorKind::InvalidIssuer => { - bunt::println!("{$red+bold}The token issuer is invalid{/$}") + bunt::eprintln!("{$red+bold}The token issuer is invalid{/$}") } ErrorKind::InvalidAudience => { bunt::eprintln!("{$red+bold}The token audience doesn't match the subject{/$}") @@ -597,15 +610,32 @@ fn print_decoded_token( ErrorKind::ImmatureSignature => bunt::eprintln!( "{$red+bold}The `nbf` claim is in the future which isn't allowed{/$}" ), - ErrorKind::InvalidAlgorithm => bunt::eprintln!( - "{$red+bold}The JWT provided has a different signing algorithm than the one you \ - provided{/$}", - ), + ErrorKind::InvalidAlgorithm => { + let jwt_algorithm = match token_data { + Ok(ref token) => token.header.alg, + Err(_) => panic!("Error: Invalid token data."), + }; + bunt::eprintln!("{$red+bold}Error: Invalid Signature! The JWT provided has a different signing algorithm ({:?}) than the one selected for validation ({:?}){/$}",jwt_algorithm, options_algorithm.unwrap()) + } _ => bunt::eprintln!( - "{$red+bold}The JWT provided is invalid because{/$} {:?}", + "{$red+bold}The JWT provided is invalid because {:?}{/$}", err ), - }; + }, + Some(Ok(_)) => bunt::eprintln!("{$green+bold}Success! JWT signature is valid!{/$}"), + None => { + // the signature could not be verified + match token_data { + Err(ref err) => match err.kind() { + ErrorKind::InvalidToken => bunt::eprintln!("{$red+bold}Error: The token could not be decoded (invalid token structure).{/$}"), + ErrorKind::Base64(_) => bunt::eprintln!("{$red+bold}Error: The token could not be decoded (invalid Base64 encoding).{/$}"), + ErrorKind::Json(_) => bunt::eprintln!("{$red+bold}Error: The token could not be decoded (error while decoding json).{/$}"), + ErrorKind::Utf8(_) => bunt::eprintln!("{$red+bold}Error: The token could not be decoded (error while decoding UTF8 string).{/$}"), + _ => bunt::eprintln!("{$red+bold}Error: Unexpected error while decoding the token!{/$}"), + } + Ok(_) => bunt::eprintln!("{$red+bold}Warning! JWT signature has not been validated!{/$}"), + } + } } match (format, token_data) { @@ -618,13 +648,8 @@ fn print_decoded_token( bunt::println!("{$bold}Token claims\n------------{/$}"); println!("{}", to_string_pretty(&token.claims).unwrap()); } - (_, Err(_)) => exit(1), + (_, Err(_)) => {} } - - exit(match validated_token { - Err(_) => 1, - Ok(_) => 0, - }) } fn main() { @@ -635,13 +660,43 @@ fn main() { warn_unsupported(encode_matches); let token = encode_token(encode_matches); + let return_code: i32 = match &token { + Ok(_) => 0, // token encoded sucessfully + Err(_) => 1, // token could not be encoded + }; print_encoded_token(token); + exit(return_code) } ("decode", Some(decode_matches)) => { - let (validated_token, token_data, format) = decode_token(decode_matches); - - print_decoded_token(validated_token, token_data, format); + let (_, token_data, format) = decode_token(decode_matches); + let return_code: i32 = match &token_data { + Ok(_) => 0, // token decoded sucessfully + Err(_) => 1, // token could not be decoded + }; + + print_decoded_token(None, token_data, None, format); + exit(return_code) + } + ("verify", Some(decode_matches)) => { + let (jwt, token_data, format) = decode_token(decode_matches); + let validated_token = verify_token(jwt, decode_matches); + let return_code: i32 = match validated_token { + Ok(_) => 0, // successful signature check + Err(_) => 1, // unsuccessful signature check + }; + let options_algorithm = translate_algorithm(SupportedAlgorithms::from_string( + decode_matches.value_of("algorithm").unwrap(), + )); + + print_decoded_token( + Some(validated_token), + token_data, + Some(options_algorithm), + format, + ); + + exit(return_code) } _ => (), } diff --git a/tests/jwt-cli.rs b/tests/jwt-cli.rs index 0f1df2d..1978e3e 100644 --- a/tests/jwt-cli.rs +++ b/tests/jwt-cli.rs @@ -5,7 +5,7 @@ mod tests { use super::{ config_options, create_header, decode_token, decoding_key_from_secret, encode_token, encoding_key_from_secret, is_payload_item, is_timestamp_or_duration, translate_algorithm, - OutputFormat, Payload, PayloadItem, SupportedAlgorithms, + verify_token, OutputFormat, Payload, PayloadItem, SupportedAlgorithms, }; use base64::decode as base64_decode; use chrono::{Duration, TimeZone, Utc}; @@ -248,14 +248,16 @@ mod tests { let encode_matches = encode_matcher.subcommand_matches("encode").unwrap(); let encoded_token = encode_token(&encode_matches).unwrap(); let decode_matcher = config_options() - .get_matches_from_safe(vec!["jwt", "decode", "-S", "1234567890", &encoded_token]) + .get_matches_from_safe(vec!["jwt", "verify", "-S", "1234567890", &encoded_token]) .unwrap(); - let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (decoded_token, _, _) = decode_token(&decode_matches); + let decode_matches = decode_matcher.subcommand_matches("verify").unwrap(); + let (jwt, token_data, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); - assert!(decoded_token.is_ok()); + assert!(token_data.is_ok()); + assert!(validated_token.as_ref().is_ok()); - let TokenData { claims, header } = decoded_token.unwrap(); + let TokenData { claims, header } = validated_token.unwrap(); assert_eq!(header.alg, Algorithm::HS256); assert_eq!(header.kid, Some("1234".to_string())); @@ -282,10 +284,10 @@ mod tests { let encode_matches = encode_matcher.subcommand_matches("encode").unwrap(); let encoded_token = encode_token(&encode_matches).unwrap(); let decode_matcher = config_options() - .get_matches_from_safe(vec!["jwt", "decode", "-S", "1234567890", &encoded_token]) + .get_matches_from_safe(vec!["jwt", "decode", &encoded_token]) .unwrap(); let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (decoded_token, _, _) = decode_token(&decode_matches); + let (_, decoded_token, _) = decode_token(&decode_matches); assert!(decoded_token.is_ok()); @@ -304,14 +306,14 @@ mod tests { let encode_matches = encode_matcher.subcommand_matches("encode").unwrap(); let encoded_token = encode_token(&encode_matches).unwrap(); let decode_matcher = config_options() - .get_matches_from_safe(vec!["jwt", "decode", "-S", "1234567890", &encoded_token]) + .get_matches_from_safe(vec!["jwt", "verify", "-S", "1234567890", &encoded_token]) .unwrap(); - let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (decoded_token, token_data, _) = decode_token(&decode_matches); + let decode_matches = decode_matcher.subcommand_matches("verify").unwrap(); + let (_, decoded_token, _) = decode_token(&decode_matches); - assert!(decoded_token.is_err()); + assert!(decoded_token.is_ok()); - let TokenData { claims, header: _ } = token_data.unwrap(); + let TokenData { claims, header: _ } = decoded_token.unwrap(); assert!(claims.0.get("exp").is_none()); } @@ -324,12 +326,14 @@ mod tests { let encode_matches = encode_matcher.subcommand_matches("encode").unwrap(); let encoded_token = encode_token(&encode_matches).unwrap(); let decode_matcher = config_options() - .get_matches_from_safe(vec!["jwt", "decode", "-S", "1234567890", &encoded_token]) + .get_matches_from_safe(vec!["jwt", "verify", "-S", "1234567890", &encoded_token]) .unwrap(); - let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (decoded_token, _, _) = decode_token(&decode_matches); + let decode_matches = decode_matcher.subcommand_matches("verify").unwrap(); + let (jwt, decoded_token, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); assert!(decoded_token.is_ok()); + assert!(validated_token.is_ok()); let TokenData { claims, header: _ } = decoded_token.unwrap(); let exp = from_value::(claims.0["exp"].clone()); @@ -353,10 +357,10 @@ mod tests { let encode_matches = encode_matcher.subcommand_matches("encode").unwrap(); let encoded_token = encode_token(&encode_matches).unwrap(); let decode_matcher = config_options() - .get_matches_from_safe(vec!["jwt", "decode", "-S", "1234567890", &encoded_token]) + .get_matches_from_safe(vec!["jwt", "decode", &encoded_token]) .unwrap(); let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (decoded_token, _, _) = decode_token(&decode_matches); + let (_, decoded_token, _) = decode_token(&decode_matches); assert!(decoded_token.is_ok()); @@ -381,10 +385,10 @@ mod tests { let encode_matches = encode_matcher.subcommand_matches("encode").unwrap(); let encoded_token = encode_token(&encode_matches).unwrap(); let decode_matcher = config_options() - .get_matches_from_safe(vec!["jwt", "decode", "-S", "1234567890", &encoded_token]) + .get_matches_from_safe(vec!["jwt", "decode", &encoded_token]) .unwrap(); let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (decoded_token, _, _) = decode_token(&decode_matches); + let (_, decoded_token, _) = decode_token(&decode_matches); assert!(decoded_token.is_ok()); @@ -403,12 +407,14 @@ mod tests { let encode_matches = encode_matcher.subcommand_matches("encode").unwrap(); let encoded_token = encode_token(&encode_matches).unwrap(); let decode_matcher = config_options() - .get_matches_from_safe(vec!["jwt", "decode", "-S", "1234567890", &encoded_token]) + .get_matches_from_safe(vec!["jwt", "verify", "-S", "1234567890", &encoded_token]) .unwrap(); - let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (decoded_token, _, _) = decode_token(&decode_matches); + let decode_matches = decode_matcher.subcommand_matches("verify").unwrap(); + let (jwt, decoded_token, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); - assert!(decoded_token.is_err()); + assert!(decoded_token.is_ok()); + assert!(validated_token.is_err()); } #[test] @@ -421,17 +427,19 @@ mod tests { let decode_matcher = config_options() .get_matches_from_safe(vec![ "jwt", - "decode", + "verify", "-S", "1234567890", "--ignore-exp", &encoded_token, ]) .unwrap(); - let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (decoded_token, _, _) = decode_token(&decode_matches); + let decode_matches = decode_matcher.subcommand_matches("verify").unwrap(); + let (jwt, decoded_token, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); assert!(decoded_token.is_ok()); + assert!(validated_token.is_ok()); } #[test] @@ -449,12 +457,14 @@ mod tests { let encode_matches = encode_matcher.subcommand_matches("encode").unwrap(); let encoded_token = encode_token(&encode_matches).unwrap(); let decode_matcher = config_options() - .get_matches_from_safe(vec!["jwt", "decode", "-S", "1234567890", &encoded_token]) + .get_matches_from_safe(vec!["jwt", "verify", "-S", "1234567890", &encoded_token]) .unwrap(); - let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (decoded_token, _, _) = decode_token(&decode_matches); + let decode_matches = decode_matcher.subcommand_matches("verify").unwrap(); + let (jwt, decoded_token, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); assert!(decoded_token.is_ok()); + assert!(validated_token.is_ok()); let TokenData { claims, header: _ } = decoded_token.unwrap(); let exp_claim = from_value::(claims.0["exp"].clone()); @@ -485,12 +495,14 @@ mod tests { let encode_matches = encode_matcher.subcommand_matches("encode").unwrap(); let encoded_token = encode_token(&encode_matches).unwrap(); let decode_matcher = config_options() - .get_matches_from_safe(vec!["jwt", "decode", "-S", "1234567890", &encoded_token]) + .get_matches_from_safe(vec!["jwt", "verify", "-S", "1234567890", &encoded_token]) .unwrap(); - let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (decoded_token, _, _) = decode_token(&decode_matches); + let decode_matches = decode_matcher.subcommand_matches("verify").unwrap(); + let (jwt, decoded_token, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); assert!(decoded_token.is_ok()); + assert!(validated_token.is_ok()); let TokenData { claims, header: _ } = decoded_token.unwrap(); let nbf_claim = from_value::(claims.0["nbf"].clone()); @@ -506,11 +518,11 @@ mod tests { } #[test] - fn decodes_a_token() { + fn validate_a_token() { let matches = config_options() .get_matches_from_safe(vec![ "jwt", - "decode", + "verify", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE4OTM0NTYwMDAsImlhdCI6MTU0MjQ5MjMxMywidGhpcyI6InRoYXQifQ.YTWit46_AEMMVv0P48NeJJIqXmMHarGjfRxtR7jLlxE", "-S", "1234567890", @@ -518,10 +530,12 @@ mod tests { "HS256", ]) .unwrap(); - let decode_matches = matches.subcommand_matches("decode").unwrap(); - let (result, _, _) = decode_token(&decode_matches); + let decode_matches = matches.subcommand_matches("verify").unwrap(); + let (jwt, decoded_token, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); - assert!(result.is_ok()); + assert!(decoded_token.is_ok()); + assert!(validated_token.is_ok()); } #[test] @@ -535,18 +549,18 @@ mod tests { ]) .unwrap(); let decode_matches = matches.subcommand_matches("decode").unwrap(); - let (result, _, format) = decode_token(&decode_matches); + let (_, decoded_token, format) = decode_token(&decode_matches); - assert!(result.is_ok()); + assert!(decoded_token.is_ok()); assert!(format == OutputFormat::Json); } #[test] - fn decodes_a_token_with_invalid_secret() { + fn validates_a_token_with_invalid_secret() { let matches = config_options() .get_matches_from_safe(vec![ "jwt", - "decode", + "verify", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0aGlzIjoidGhhdCJ9.AdAECLE_4iRa0uomMEdsMV2hDXv1vhLpym567-AzhrM", "-S", "yolo", @@ -554,42 +568,12 @@ mod tests { "HS256", ]) .unwrap(); - let decode_matches = matches.subcommand_matches("decode").unwrap(); - let (result, _, _) = decode_token(&decode_matches); - - assert!(result.is_err()); - } - - #[test] - fn decodes_a_token_without_a_secret() { - let matches = config_options() - .get_matches_from_safe(vec![ - "jwt", - "decode", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0aGlzIjoidGhhdCJ9.AdAECLE_4iRa0uomMEdsMV2hDXv1vhLpym567-AzhrM", - "-A", - "HS256", - ]) - .unwrap(); - let decode_matches = matches.subcommand_matches("decode").unwrap(); - let (result, _, _) = decode_token(&decode_matches); - - assert!(result.is_ok()); - } - - #[test] - fn decodes_a_token_without_an_alg() { - let matches = config_options() - .get_matches_from_safe(vec![ - "jwt", - "decode", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0aGlzIjoidGhhdCJ9.AdAECLE_4iRa0uomMEdsMV2hDXv1vhLpym567-AzhrM", - ]) - .unwrap(); - let decode_matches = matches.subcommand_matches("decode").unwrap(); - let (result, _, _) = decode_token(&decode_matches); + let decode_matches = matches.subcommand_matches("verify").unwrap(); + let (jwt, decoded_token, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); - assert!(result.is_ok()); + assert!(decoded_token.is_ok()); + assert!(validated_token.is_err()); } #[test] @@ -602,9 +586,9 @@ mod tests { ]) .unwrap(); let decode_matches = matches.subcommand_matches("decode").unwrap(); - let (result, _, _) = decode_token(&decode_matches); + let (_, decoded_token, _) = decode_token(&decode_matches); - assert!(result.is_ok()); + assert!(decoded_token.is_ok()); } #[test] @@ -617,9 +601,9 @@ mod tests { ]) .unwrap(); let decode_matches = matches.subcommand_matches("decode").unwrap(); - let (result, _, _) = decode_token(&decode_matches); + let (_, decoded_token, _) = decode_token(&decode_matches); - assert!(result.is_ok()); + assert!(decoded_token.is_ok()); } #[test] @@ -642,7 +626,7 @@ mod tests { let decode_matcher = config_options() .get_matches_from_safe(vec![ "jwt", - "decode", + "verify", "-S", "@./tests/public_rsa_key.der", "-A", @@ -650,10 +634,12 @@ mod tests { &encoded_token, ]) .unwrap(); - let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (result, _, _) = decode_token(&decode_matches); + let decode_matches = decode_matcher.subcommand_matches("verify").unwrap(); + let (jwt, decoded_token, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); - assert!(result.is_ok()); + assert!(decoded_token.is_ok()); + assert!(validated_token.is_ok()); } #[test] @@ -689,7 +675,7 @@ mod tests { } #[test] - fn encodes_and_decodes_an_rsa_ssa_pss_token_using_key_from_file() { + fn encodes_and_verifies_an_rsa_ssa_pss_token_using_key_from_file() { let body: String = "{\"field\":\"value\"}".to_string(); let encode_matcher = config_options() .get_matches_from_safe(vec![ @@ -709,7 +695,7 @@ mod tests { let decode_matcher = config_options() .get_matches_from_safe(vec![ "jwt", - "decode", + "verify", "-S", "@./tests/public_rsa_key.der", "-A", @@ -717,19 +703,21 @@ mod tests { &encoded_token, ]) .unwrap(); - let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (result, _, _) = decode_token(&decode_matches); + let decode_matches = decode_matcher.subcommand_matches("verify").unwrap(); + let (jwt, decoded_token, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); - assert!(result.is_ok()); + assert!(decoded_token.is_ok()); + assert!(validated_token.is_ok()); } #[test] - fn decodes_an_rsa_ssa_pss_token_using_key_from_file() { + fn verify_an_rsa_ssa_pss_token_using_key_from_file() { let token: String = "eyJ0eXAiOiJKV1QiLCJhbGciOiJQUzUxMiJ9.eyJmaWVsZCI6InZhbHVlIiwiaWF0IjoxNjI1OTMxNjAwLCJleHAiOjkwMDAwMDAwMDB9.Tt1siDczvVAi89dH8QqTZ_n5Ejz4gAIzVLqucWN5tEqdAVRdWgP8psuRFdC8RKIn1Lp4OsUkAA7NJ79cZt32Eewy84hTYrCgZZ9mcWg5IfXPHcZmTUm6qSyKqANdsnRWThbG3IJSX1D6obI5Y91NhVI5PTRg8sFlDAXaNN9ZVTmAtZXj0b5-MgsjiRqWMW3xi9xQqTxvb5VN37Oot-KDWZXjkO022ixshzFWu8Jt582uMD4qYRp1d0VldgyGO_viDqqk8qTqNA7soUKWyDds0emuecE_bDMeELMfxMR-A1pQeu3FgEhliazIAdXJMNlwRuJG8znLNqCK1nB2Nd8sUQ".to_string(); let decode_matcher = config_options() .get_matches_from_safe(vec![ "jwt", - "decode", + "verify", "-S", "@./tests/public_rsa_key.der", "-A", @@ -737,10 +725,12 @@ mod tests { &token, ]) .unwrap(); - let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (result, _, _) = decode_token(&decode_matches); + let decode_matches = decode_matcher.subcommand_matches("verify").unwrap(); + let (jwt, decoded_token, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); - assert!(result.is_ok()); + assert!(decoded_token.is_ok()); + assert!(validated_token.is_ok()); } #[test] @@ -763,7 +753,7 @@ mod tests { let decode_matcher = config_options() .get_matches_from_safe(vec![ "jwt", - "decode", + "verify", "-S", "@./tests/public_ecdsa_key.pk8", "-A", @@ -771,12 +761,12 @@ mod tests { &encoded_token, ]) .unwrap(); - let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (result, _, _) = decode_token(&decode_matches); + let decode_matches = decode_matcher.subcommand_matches("verify").unwrap(); + let (jwt, decoded_token, _) = decode_token(&decode_matches); + let validated_token = verify_token(jwt, &decode_matches); - dbg!(&result); - - assert!(result.is_ok()); + assert!(decoded_token.is_ok()); + assert!(validated_token.is_ok()); } #[test] @@ -798,21 +788,14 @@ mod tests { let encode_matches = encode_matcher.subcommand_matches("encode").unwrap(); let encoded_token = encode_token(&encode_matches).unwrap(); let decode_matcher = config_options() - .get_matches_from_safe(vec![ - "jwt", - "decode", - "-S", - "1234567890", - "--iso8601", - &encoded_token, - ]) + .get_matches_from_safe(vec!["jwt", "decode", "--iso8601", &encoded_token]) .unwrap(); let decode_matches = decode_matcher.subcommand_matches("decode").unwrap(); - let (decoded_token, token_data, _) = decode_token(&decode_matches); + let (_, decoded_token, _) = decode_token(&decode_matches); assert!(decoded_token.is_ok()); - let TokenData { claims, header: _ } = token_data.unwrap(); + let TokenData { claims, header: _ } = decoded_token.unwrap(); assert!(claims.0.get("iat").is_some()); assert!(claims.0.get("nbf").is_some());