Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions examples/auth0.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/// Example for the backend to backend implementation
use std::collections::HashMap;
use std::str::FromStr;

use jsonwebtoken::jwk::AlgorithmParameters;
use jsonwebtoken::{decode, decode_header, jwk, DecodingKey, Validation};
use jsonwebtoken::{decode, decode_header, jwk, Algorithm, DecodingKey, Validation};

const TOKEN: &str = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjFaNTdkX2k3VEU2S1RZNTdwS3pEeSJ9.eyJpc3MiOiJodHRwczovL2Rldi1kdXp5YXlrNC5ldS5hdXRoMC5jb20vIiwic3ViIjoiNDNxbW44c281R3VFU0U1N0Fkb3BhN09jYTZXeVNidmRAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vZGV2LWR1enlheWs0LmV1LmF1dGgwLmNvbS9hcGkvdjIvIiwiaWF0IjoxNjIzNTg1MzAxLCJleHAiOjE2MjM2NzE3MDEsImF6cCI6IjQzcW1uOHNvNUd1RVNFNTdBZG9wYTdPY2E2V3lTYnZkIiwic2NvcGUiOiJyZWFkOnVzZXJzIiwiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIn0.0MpewU1GgvRqn4F8fK_-Eu70cUgWA5JJrdbJhkCPCxXP-8WwfI-qx1ZQg2a7nbjXICYAEl-Z6z4opgy-H5fn35wGP0wywDqZpqL35IPqx6d0wRvpPMjJM75zVXuIjk7cEhDr2kaf1LOY9auWUwGzPiDB_wM-R0uvUMeRPMfrHaVN73xhAuQWVjCRBHvNscYS5-i6qBQKDMsql87dwR72DgHzMlaC8NnaGREBC-xiSamesqhKPVyGzSkFSaF3ZKpGrSDapqmHkNW9RDBE3GQ9OHM33vzUdVKOjU1g9Leb9PDt0o1U4p3NQoGJPShQ6zgWSUEaqvUZTfkbpD_DoYDRxA";
const JWKS_REPLY: &str = r#"
Expand All @@ -21,7 +22,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
match &j.algorithm {
AlgorithmParameters::RSA(rsa) => {
let decoding_key = DecodingKey::from_rsa_components(&rsa.n, &rsa.e).unwrap();
let mut validation = Validation::new(j.common.algorithm.unwrap());

let mut validation = Validation::new(
Algorithm::from_str(j.common.key_algorithm.unwrap().to_string().as_str())
.unwrap(),
);
validation.validate_exp = false;
let decoded_token =
decode::<HashMap<String, serde_json::Value>>(TOKEN, &decoding_key, &validation)
Expand Down
2 changes: 2 additions & 0 deletions src/algorithms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ impl Algorithm {

#[cfg(test)]
mod tests {
use crate::jwk::KeyAlgorithm;

use super::*;

#[test]
Expand Down
112 changes: 103 additions & 9 deletions src/jwk.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
#![allow(missing_docs)]
//! This crate contains types only for working JWK and JWK Sets
//! This is only meant to be used to deal with public JWK, not generate ones.
//! Most of the code in this file is taken from https://github.com/lawliet89/biscuit but
//! tweaked to remove the private bits as it's not the goal for this crate currently.
use crate::Algorithm;
///! This crate contains types only for working JWK and JWK Sets
///! This is only meant to be used to deal with public JWK, not generate ones.
///! Most of the code in this file is taken from https://github.com/lawliet89/biscuit but
/// tweaked to remove the private bits as it's not the goal for this crate currently.
///!
use crate::{
errors::{self, Error, ErrorKind},
Algorithm,
};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
use std::{fmt, str::FromStr};

/// The intended usage of the public `KeyType`. This enum is serialized `untagged`
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
Expand Down Expand Up @@ -141,6 +145,87 @@ impl<'de> Deserialize<'de> for KeyOperations {
}
}

/// The algorithms of the keys
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)]
pub enum KeyAlgorithm {
/// HMAC using SHA-256
HS256,
/// HMAC using SHA-384
HS384,
/// HMAC using SHA-512
HS512,

/// ECDSA using SHA-256
ES256,
/// ECDSA using SHA-384
ES384,

/// RSASSA-PKCS1-v1_5 using SHA-256
RS256,
/// RSASSA-PKCS1-v1_5 using SHA-384
RS384,
/// RSASSA-PKCS1-v1_5 using SHA-512
RS512,

/// RSASSA-PSS using SHA-256
PS256,
/// RSASSA-PSS using SHA-384
PS384,
/// RSASSA-PSS using SHA-512
PS512,

/// Edwards-curve Digital Signature Algorithm (EdDSA)
EdDSA,

/// RSAES-PKCS1-V1_5
RSA1_5,

/// RSAES-OAEP using SHA-1
#[serde(rename = "RSA-OAEP")]
RSA_OAEP,

/// RSAES-OAEP-256 using SHA-2
#[serde(rename = "RSA-OAEP-256")]
RSA_OAEP_256,
}

impl FromStr for KeyAlgorithm {
type Err = Error;
fn from_str(s: &str) -> errors::Result<Self> {
match s {
"HS256" => Ok(KeyAlgorithm::HS256),
"HS384" => Ok(KeyAlgorithm::HS384),
"HS512" => Ok(KeyAlgorithm::HS512),
"ES256" => Ok(KeyAlgorithm::ES256),
"ES384" => Ok(KeyAlgorithm::ES384),
"RS256" => Ok(KeyAlgorithm::RS256),
"RS384" => Ok(KeyAlgorithm::RS384),
"PS256" => Ok(KeyAlgorithm::PS256),
"PS384" => Ok(KeyAlgorithm::PS384),
"PS512" => Ok(KeyAlgorithm::PS512),
"RS512" => Ok(KeyAlgorithm::RS512),
"EdDSA" => Ok(KeyAlgorithm::EdDSA),
"RSA1_5" => Ok(KeyAlgorithm::RSA1_5),
"RSA-OAEP" => Ok(KeyAlgorithm::RSA_OAEP),
"RSA-OAEP-256" => Ok(KeyAlgorithm::RSA_OAEP_256),
_ => Err(ErrorKind::InvalidAlgorithmName.into()),
}
}
}

impl fmt::Display for KeyAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}

impl KeyAlgorithm {
fn to_algorithm(self) -> errors::Result<Algorithm> {
Algorithm::from_str(self.to_string().as_str())
}
}

/// Common JWK parameters
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
pub struct CommonParameters {
Expand All @@ -158,9 +243,9 @@ pub struct CommonParameters {
#[serde(rename = "key_ops", skip_serializing_if = "Option::is_none", default)]
pub key_operations: Option<Vec<KeyOperations>>,

/// The algorithm intended for use with the key
/// The algorithm keys intended for use with the key.
#[serde(rename = "alg", skip_serializing_if = "Option::is_none", default)]
pub algorithm: Option<Algorithm>,
pub key_algorithm: Option<KeyAlgorithm>,

/// The case sensitive Key ID for the key
#[serde(rename = "kid", skip_serializing_if = "Option::is_none", default)]
Expand Down Expand Up @@ -326,6 +411,13 @@ pub struct Jwk {
pub algorithm: AlgorithmParameters,
}

impl Jwk {
/// Find whether the Algorithm is implmented and supported
pub fn is_supported(&self) -> bool {
self.common.key_algorithm.unwrap().to_algorithm().is_ok()
}
}

/// A JWK set
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct JwkSet {
Expand Down Expand Up @@ -366,7 +458,9 @@ mod tests {
assert_eq!(set.keys.len(), 1);
let key = &set.keys[0];
assert_eq!(key.common.key_id, Some("abc123".to_string()));
assert_eq!(key.common.algorithm, Some(Algorithm::HS256));
let algorithm = key.common.key_algorithm.unwrap().to_algorithm().unwrap();
assert_eq!(algorithm, Algorithm::HS256);

match &key.algorithm {
AlgorithmParameters::OctetKey(key) => {
assert_eq!(key.key_type, OctetKeyType::Octet);
Expand Down