1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-28 11:02:02 +03:00

Add variants for unknown values on mas-iana types

Remove the Copy derive and mark enums as non-exhaustive.
This commit is contained in:
Kévin Commaille
2022-09-13 18:32:56 +02:00
committed by Quentin Gliech
parent 9e3b3567b2
commit 80d317f23c
25 changed files with 414 additions and 292 deletions

2
Cargo.lock generated
View File

@ -2519,7 +2519,7 @@ version = "0.1.0"
dependencies = [
"parse-display",
"schemars",
"serde",
"serde_with",
]
[[package]]

View File

@ -92,7 +92,7 @@ impl Credentials {
pub async fn verify<S: StorageBackend>(
&self,
encrypter: &Encrypter,
method: OAuthClientAuthenticationMethod,
method: &OAuthClientAuthenticationMethod,
client: &Client<S>,
) -> Result<(), CredentialsVerificationError> {
match (self, method) {

View File

@ -162,7 +162,7 @@ pub(crate) async fn post(
let client = client_authorization.credentials.fetch(&mut conn).await?;
let method = match client.token_endpoint_auth_method {
let method = match &client.token_endpoint_auth_method {
None | Some(OAuthClientAuthenticationMethod::None) => {
return Err(RouteError::NotAllowed);
}

View File

@ -151,10 +151,10 @@ pub(crate) async fn post(
metadata.tos_uri.as_ref().map(Localized::non_localized),
metadata.jwks_uri.as_ref(),
metadata.jwks.as_ref(),
metadata.id_token_signed_response_alg,
metadata.userinfo_signed_response_alg,
metadata.token_endpoint_auth_method,
metadata.token_endpoint_auth_signing_alg,
metadata.id_token_signed_response_alg.as_ref(),
metadata.userinfo_signed_response_alg.as_ref(),
metadata.token_endpoint_auth_method.as_ref(),
metadata.token_endpoint_auth_signing_alg.as_ref(),
metadata.initiate_login_uri.as_ref(),
)
.await?;

View File

@ -198,6 +198,7 @@ pub(crate) async fn post(
let method = client
.token_endpoint_auth_method
.as_ref()
.ok_or(RouteError::ClientNotAllowed)?;
client_authorization
@ -333,17 +334,18 @@ async fn authorization_code_grant(
let alg = client
.id_token_signed_response_alg
.clone()
.unwrap_or(JsonWebSignatureAlg::Rs256);
let key = key_store
.signing_key_for_algorithm(alg)
.signing_key_for_algorithm(&alg)
.context("no suitable key found")?;
claims::AT_HASH.insert(&mut claims, hash_token(alg, &access_token_str)?)?;
claims::C_HASH.insert(&mut claims, hash_token(alg, &grant.code)?)?;
claims::AT_HASH.insert(&mut claims, hash_token(&alg, &access_token_str)?)?;
claims::C_HASH.insert(&mut claims, hash_token(&alg, &grant.code)?)?;
let signer = key.params().signing_key_for_alg(&alg)?;
let header = JsonWebSignatureHeader::new(alg)
.with_kid(key.kid().context("key has no `kid` for some reason")?);
let signer = key.params().signing_key_for_alg(alg)?;
let id_token = Jwt::sign(header, claims, &signer)?;
Some(id_token.as_str().to_owned())

View File

@ -75,12 +75,12 @@ pub async fn get(
if let Some(alg) = session.client.userinfo_signed_response_alg {
let key = key_store
.signing_key_for_algorithm(alg)
.signing_key_for_algorithm(&alg)
.context("no suitable key found")?;
let signer = key.params().signing_key_for_alg(&alg)?;
let header = JsonWebSignatureHeader::new(alg)
.with_kid(key.kid().context("key has no `kid` for some reason")?);
let signer = key.params().signing_key_for_alg(alg)?;
let user_info = SignedUserInfo {
iss: url_builder.oidc_issuer().to_string(),

View File

@ -105,7 +105,7 @@ impl Display for File {
use parse_display::{{Display, FromStr}};
use schemars::JsonSchema;
use serde::{{Deserialize, Serialize}};"#,
use serde_with::{{DeserializeFromStr, SerializeDisplay}};"#,
self.registry_name, self.registry_url,
)?;
@ -116,6 +116,14 @@ use serde::{{Deserialize, Serialize}};"#,
continue;
};
let is_exhaustive = section.key == "OAuthAuthorizationEndpointResponseType";
let non_exhaustive_attr = if is_exhaustive {
""
} else {
"\n#[non_exhaustive]"
};
write!(
f,
r#"
@ -125,7 +133,6 @@ use serde::{{Deserialize, Serialize}};"#,
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -133,13 +140,14 @@ use serde::{{Deserialize, Serialize}};"#,
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
)]{}
pub enum {} {{"#,
section.doc,
section.url.unwrap(),
non_exhaustive_attr,
section.key,
)?;
for member in list {
@ -149,10 +157,20 @@ pub enum {} {{"#,
} else {
writeln!(f, " /// `{}`", member.value)?;
}
writeln!(f, " #[serde(rename = \"{}\")]", member.value)?;
writeln!(f, " #[schemars(rename = \"{}\")]", member.value)?;
writeln!(f, " #[display(\"{}\")]", member.value)?;
writeln!(f, " {},", member.enum_name)?;
}
if !is_exhaustive {
// Add a variant for custom enums
writeln!(f)?;
writeln!(f, " /// An unknown value.")?;
writeln!(f, " #[display(\"{{0}}\")]")?;
writeln!(f, " #[schemars(skip)]")?;
writeln!(f, " Unknown(String),")?;
}
writeln!(f, "}}")?;
}

View File

@ -6,6 +6,6 @@ edition = "2021"
license = "Apache-2.0"
[dependencies]
serde = "1.0.145"
serde_with = "2.0.0"
schemars = "0.8.10"
parse-display = "0.6.0"

View File

@ -19,7 +19,7 @@
use parse_display::{Display, FromStr};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_with::{DeserializeFromStr, SerializeDisplay};
/// JSON Web Signature "alg" parameter
///
@ -27,7 +27,6 @@ use serde::{Deserialize, Serialize};
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -35,85 +34,91 @@ use serde::{Deserialize, Serialize};
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum JsonWebSignatureAlg {
/// HMAC using SHA-256
#[serde(rename = "HS256")]
#[schemars(rename = "HS256")]
#[display("HS256")]
Hs256,
/// HMAC using SHA-384
#[serde(rename = "HS384")]
#[schemars(rename = "HS384")]
#[display("HS384")]
Hs384,
/// HMAC using SHA-512
#[serde(rename = "HS512")]
#[schemars(rename = "HS512")]
#[display("HS512")]
Hs512,
/// RSASSA-PKCS1-v1_5 using SHA-256
#[serde(rename = "RS256")]
#[schemars(rename = "RS256")]
#[display("RS256")]
Rs256,
/// RSASSA-PKCS1-v1_5 using SHA-384
#[serde(rename = "RS384")]
#[schemars(rename = "RS384")]
#[display("RS384")]
Rs384,
/// RSASSA-PKCS1-v1_5 using SHA-512
#[serde(rename = "RS512")]
#[schemars(rename = "RS512")]
#[display("RS512")]
Rs512,
/// ECDSA using P-256 and SHA-256
#[serde(rename = "ES256")]
#[schemars(rename = "ES256")]
#[display("ES256")]
Es256,
/// ECDSA using P-384 and SHA-384
#[serde(rename = "ES384")]
#[schemars(rename = "ES384")]
#[display("ES384")]
Es384,
/// ECDSA using P-521 and SHA-512
#[serde(rename = "ES512")]
#[schemars(rename = "ES512")]
#[display("ES512")]
Es512,
/// RSASSA-PSS using SHA-256 and MGF1 with SHA-256
#[serde(rename = "PS256")]
#[schemars(rename = "PS256")]
#[display("PS256")]
Ps256,
/// RSASSA-PSS using SHA-384 and MGF1 with SHA-384
#[serde(rename = "PS384")]
#[schemars(rename = "PS384")]
#[display("PS384")]
Ps384,
/// RSASSA-PSS using SHA-512 and MGF1 with SHA-512
#[serde(rename = "PS512")]
#[schemars(rename = "PS512")]
#[display("PS512")]
Ps512,
/// No digital signature or MAC performed
#[serde(rename = "none")]
#[schemars(rename = "none")]
#[display("none")]
None,
/// EdDSA signature algorithms
#[serde(rename = "EdDSA")]
#[schemars(rename = "EdDSA")]
#[display("EdDSA")]
EdDsa,
/// ECDSA using secp256k1 curve and SHA-256
#[serde(rename = "ES256K")]
#[schemars(rename = "ES256K")]
#[display("ES256K")]
Es256K,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}
/// JSON Web Encryption "alg" parameter
@ -122,7 +127,6 @@ pub enum JsonWebSignatureAlg {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -130,105 +134,111 @@ pub enum JsonWebSignatureAlg {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum JsonWebEncryptionAlg {
/// RSAES-PKCS1-v1_5
#[serde(rename = "RSA1_5")]
#[schemars(rename = "RSA1_5")]
#[display("RSA1_5")]
Rsa15,
/// RSAES OAEP using default parameters
#[serde(rename = "RSA-OAEP")]
#[schemars(rename = "RSA-OAEP")]
#[display("RSA-OAEP")]
RsaOaep,
/// RSAES OAEP using SHA-256 and MGF1 with SHA-256
#[serde(rename = "RSA-OAEP-256")]
#[schemars(rename = "RSA-OAEP-256")]
#[display("RSA-OAEP-256")]
RsaOaep256,
/// AES Key Wrap using 128-bit key
#[serde(rename = "A128KW")]
#[schemars(rename = "A128KW")]
#[display("A128KW")]
A128Kw,
/// AES Key Wrap using 192-bit key
#[serde(rename = "A192KW")]
#[schemars(rename = "A192KW")]
#[display("A192KW")]
A192Kw,
/// AES Key Wrap using 256-bit key
#[serde(rename = "A256KW")]
#[schemars(rename = "A256KW")]
#[display("A256KW")]
A256Kw,
/// Direct use of a shared symmetric key
#[serde(rename = "dir")]
#[schemars(rename = "dir")]
#[display("dir")]
Dir,
/// ECDH-ES using Concat KDF
#[serde(rename = "ECDH-ES")]
#[schemars(rename = "ECDH-ES")]
#[display("ECDH-ES")]
EcdhEs,
/// ECDH-ES using Concat KDF and "A128KW" wrapping
#[serde(rename = "ECDH-ES+A128KW")]
#[schemars(rename = "ECDH-ES+A128KW")]
#[display("ECDH-ES+A128KW")]
EcdhEsA128Kw,
/// ECDH-ES using Concat KDF and "A192KW" wrapping
#[serde(rename = "ECDH-ES+A192KW")]
#[schemars(rename = "ECDH-ES+A192KW")]
#[display("ECDH-ES+A192KW")]
EcdhEsA192Kw,
/// ECDH-ES using Concat KDF and "A256KW" wrapping
#[serde(rename = "ECDH-ES+A256KW")]
#[schemars(rename = "ECDH-ES+A256KW")]
#[display("ECDH-ES+A256KW")]
EcdhEsA256Kw,
/// Key wrapping with AES GCM using 128-bit key
#[serde(rename = "A128GCMKW")]
#[schemars(rename = "A128GCMKW")]
#[display("A128GCMKW")]
A128Gcmkw,
/// Key wrapping with AES GCM using 192-bit key
#[serde(rename = "A192GCMKW")]
#[schemars(rename = "A192GCMKW")]
#[display("A192GCMKW")]
A192Gcmkw,
/// Key wrapping with AES GCM using 256-bit key
#[serde(rename = "A256GCMKW")]
#[schemars(rename = "A256GCMKW")]
#[display("A256GCMKW")]
A256Gcmkw,
/// PBES2 with HMAC SHA-256 and "A128KW" wrapping
#[serde(rename = "PBES2-HS256+A128KW")]
#[schemars(rename = "PBES2-HS256+A128KW")]
#[display("PBES2-HS256+A128KW")]
Pbes2Hs256A128Kw,
/// PBES2 with HMAC SHA-384 and "A192KW" wrapping
#[serde(rename = "PBES2-HS384+A192KW")]
#[schemars(rename = "PBES2-HS384+A192KW")]
#[display("PBES2-HS384+A192KW")]
Pbes2Hs384A192Kw,
/// PBES2 with HMAC SHA-512 and "A256KW" wrapping
#[serde(rename = "PBES2-HS512+A256KW")]
#[schemars(rename = "PBES2-HS512+A256KW")]
#[display("PBES2-HS512+A256KW")]
Pbes2Hs512A256Kw,
/// RSA-OAEP using SHA-384 and MGF1 with SHA-384
#[serde(rename = "RSA-OAEP-384")]
#[schemars(rename = "RSA-OAEP-384")]
#[display("RSA-OAEP-384")]
RsaOaep384,
/// RSA-OAEP using SHA-512 and MGF1 with SHA-512
#[serde(rename = "RSA-OAEP-512")]
#[schemars(rename = "RSA-OAEP-512")]
#[display("RSA-OAEP-512")]
RsaOaep512,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}
/// JSON Web Encryption "enc" parameter
@ -237,7 +247,6 @@ pub enum JsonWebEncryptionAlg {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -245,40 +254,46 @@ pub enum JsonWebEncryptionAlg {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum JsonWebEncryptionEnc {
/// AES_128_CBC_HMAC_SHA_256 authenticated encryption algorithm
#[serde(rename = "A128CBC-HS256")]
#[schemars(rename = "A128CBC-HS256")]
#[display("A128CBC-HS256")]
A128CbcHs256,
/// AES_192_CBC_HMAC_SHA_384 authenticated encryption algorithm
#[serde(rename = "A192CBC-HS384")]
#[schemars(rename = "A192CBC-HS384")]
#[display("A192CBC-HS384")]
A192CbcHs384,
/// AES_256_CBC_HMAC_SHA_512 authenticated encryption algorithm
#[serde(rename = "A256CBC-HS512")]
#[schemars(rename = "A256CBC-HS512")]
#[display("A256CBC-HS512")]
A256CbcHs512,
/// AES GCM using 128-bit key
#[serde(rename = "A128GCM")]
#[schemars(rename = "A128GCM")]
#[display("A128GCM")]
A128Gcm,
/// AES GCM using 192-bit key
#[serde(rename = "A192GCM")]
#[schemars(rename = "A192GCM")]
#[display("A192GCM")]
A192Gcm,
/// AES GCM using 256-bit key
#[serde(rename = "A256GCM")]
#[schemars(rename = "A256GCM")]
#[display("A256GCM")]
A256Gcm,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}
/// JSON Web Encryption Compression Algorithm
@ -287,7 +302,6 @@ pub enum JsonWebEncryptionEnc {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -295,15 +309,21 @@ pub enum JsonWebEncryptionEnc {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum JsonWebEncryptionCompressionAlgorithm {
/// DEFLATE
#[serde(rename = "DEF")]
#[schemars(rename = "DEF")]
#[display("DEF")]
Def,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}
/// JSON Web Key Type
@ -312,7 +332,6 @@ pub enum JsonWebEncryptionCompressionAlgorithm {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -320,30 +339,36 @@ pub enum JsonWebEncryptionCompressionAlgorithm {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum JsonWebKeyType {
/// Elliptic Curve
#[serde(rename = "EC")]
#[schemars(rename = "EC")]
#[display("EC")]
Ec,
/// RSA
#[serde(rename = "RSA")]
#[schemars(rename = "RSA")]
#[display("RSA")]
Rsa,
/// Octet sequence
#[serde(rename = "oct")]
#[schemars(rename = "oct")]
#[display("oct")]
Oct,
/// Octet string key pairs
#[serde(rename = "OKP")]
#[schemars(rename = "OKP")]
#[display("OKP")]
Okp,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}
/// JSON Web Key EC Elliptic Curve
@ -352,7 +377,6 @@ pub enum JsonWebKeyType {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -360,30 +384,36 @@ pub enum JsonWebKeyType {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum JsonWebKeyEcEllipticCurve {
/// P-256 Curve
#[serde(rename = "P-256")]
#[schemars(rename = "P-256")]
#[display("P-256")]
P256,
/// P-384 Curve
#[serde(rename = "P-384")]
#[schemars(rename = "P-384")]
#[display("P-384")]
P384,
/// P-521 Curve
#[serde(rename = "P-521")]
#[schemars(rename = "P-521")]
#[display("P-521")]
P521,
/// SECG secp256k1 curve
#[serde(rename = "secp256k1")]
#[schemars(rename = "secp256k1")]
#[display("secp256k1")]
Secp256K1,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}
/// JSON Web Key OKP Elliptic Curve
@ -392,7 +422,6 @@ pub enum JsonWebKeyEcEllipticCurve {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -400,30 +429,36 @@ pub enum JsonWebKeyEcEllipticCurve {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum JsonWebKeyOkpEllipticCurve {
/// Ed25519 signature algorithm key pairs
#[serde(rename = "Ed25519")]
#[schemars(rename = "Ed25519")]
#[display("Ed25519")]
Ed25519,
/// Ed448 signature algorithm key pairs
#[serde(rename = "Ed448")]
#[schemars(rename = "Ed448")]
#[display("Ed448")]
Ed448,
/// X25519 function key pairs
#[serde(rename = "X25519")]
#[schemars(rename = "X25519")]
#[display("X25519")]
X25519,
/// X448 function key pairs
#[serde(rename = "X448")]
#[schemars(rename = "X448")]
#[display("X448")]
X448,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}
/// JSON Web Key Use
@ -432,7 +467,6 @@ pub enum JsonWebKeyOkpEllipticCurve {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -440,20 +474,26 @@ pub enum JsonWebKeyOkpEllipticCurve {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum JsonWebKeyUse {
/// Digital Signature or MAC
#[serde(rename = "sig")]
#[schemars(rename = "sig")]
#[display("sig")]
Sig,
/// Encryption
#[serde(rename = "enc")]
#[schemars(rename = "enc")]
#[display("enc")]
Enc,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}
/// JSON Web Key Operation
@ -462,7 +502,6 @@ pub enum JsonWebKeyUse {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -470,48 +509,54 @@ pub enum JsonWebKeyUse {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum JsonWebKeyOperation {
/// Compute digital signature or MAC
#[serde(rename = "sign")]
#[schemars(rename = "sign")]
#[display("sign")]
Sign,
/// Verify digital signature or MAC
#[serde(rename = "verify")]
#[schemars(rename = "verify")]
#[display("verify")]
Verify,
/// Encrypt content
#[serde(rename = "encrypt")]
#[schemars(rename = "encrypt")]
#[display("encrypt")]
Encrypt,
/// Decrypt content and validate decryption, if applicable
#[serde(rename = "decrypt")]
#[schemars(rename = "decrypt")]
#[display("decrypt")]
Decrypt,
/// Encrypt key
#[serde(rename = "wrapKey")]
#[schemars(rename = "wrapKey")]
#[display("wrapKey")]
WrapKey,
/// Decrypt key and validate decryption, if applicable
#[serde(rename = "unwrapKey")]
#[schemars(rename = "unwrapKey")]
#[display("unwrapKey")]
UnwrapKey,
/// Derive key
#[serde(rename = "deriveKey")]
#[schemars(rename = "deriveKey")]
#[display("deriveKey")]
DeriveKey,
/// Derive bits not to be used as a key
#[serde(rename = "deriveBits")]
#[schemars(rename = "deriveBits")]
#[display("deriveBits")]
DeriveBits,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}

View File

@ -19,7 +19,7 @@
use parse_display::{Display, FromStr};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_with::{DeserializeFromStr, SerializeDisplay};
/// OAuth Access Token Type
///
@ -27,7 +27,6 @@ use serde::{Deserialize, Serialize};
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -35,25 +34,31 @@ use serde::{Deserialize, Serialize};
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum OAuthAccessTokenType {
/// `Bearer`
#[serde(rename = "Bearer")]
#[schemars(rename = "Bearer")]
#[display("Bearer")]
Bearer,
/// `N_A`
#[serde(rename = "N_A")]
#[schemars(rename = "N_A")]
#[display("N_A")]
Na,
/// `PoP`
#[serde(rename = "PoP")]
#[schemars(rename = "PoP")]
#[display("PoP")]
PoP,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}
/// OAuth Authorization Endpoint Response Type
@ -62,7 +67,6 @@ pub enum OAuthAccessTokenType {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -70,48 +74,48 @@ pub enum OAuthAccessTokenType {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
pub enum OAuthAuthorizationEndpointResponseType {
/// `code`
#[serde(rename = "code")]
#[schemars(rename = "code")]
#[display("code")]
Code,
/// `code id_token`
#[serde(rename = "code id_token")]
#[schemars(rename = "code id_token")]
#[display("code id_token")]
CodeIdToken,
/// `code id_token token`
#[serde(rename = "code id_token token")]
#[schemars(rename = "code id_token token")]
#[display("code id_token token")]
CodeIdTokenToken,
/// `code token`
#[serde(rename = "code token")]
#[schemars(rename = "code token")]
#[display("code token")]
CodeToken,
/// `id_token`
#[serde(rename = "id_token")]
#[schemars(rename = "id_token")]
#[display("id_token")]
IdToken,
/// `id_token token`
#[serde(rename = "id_token token")]
#[schemars(rename = "id_token token")]
#[display("id_token token")]
IdTokenToken,
/// `none`
#[serde(rename = "none")]
#[schemars(rename = "none")]
#[display("none")]
None,
/// `token`
#[serde(rename = "token")]
#[schemars(rename = "token")]
#[display("token")]
Token,
}
@ -122,7 +126,6 @@ pub enum OAuthAuthorizationEndpointResponseType {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -130,25 +133,31 @@ pub enum OAuthAuthorizationEndpointResponseType {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum OAuthTokenTypeHint {
/// `access_token`
#[serde(rename = "access_token")]
#[schemars(rename = "access_token")]
#[display("access_token")]
AccessToken,
/// `refresh_token`
#[serde(rename = "refresh_token")]
#[schemars(rename = "refresh_token")]
#[display("refresh_token")]
RefreshToken,
/// `pct`
#[serde(rename = "pct")]
#[schemars(rename = "pct")]
#[display("pct")]
Pct,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}
/// OAuth Token Endpoint Authentication Method
@ -157,7 +166,6 @@ pub enum OAuthTokenTypeHint {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -165,45 +173,51 @@ pub enum OAuthTokenTypeHint {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum OAuthClientAuthenticationMethod {
/// `none`
#[serde(rename = "none")]
#[schemars(rename = "none")]
#[display("none")]
None,
/// `client_secret_post`
#[serde(rename = "client_secret_post")]
#[schemars(rename = "client_secret_post")]
#[display("client_secret_post")]
ClientSecretPost,
/// `client_secret_basic`
#[serde(rename = "client_secret_basic")]
#[schemars(rename = "client_secret_basic")]
#[display("client_secret_basic")]
ClientSecretBasic,
/// `client_secret_jwt`
#[serde(rename = "client_secret_jwt")]
#[schemars(rename = "client_secret_jwt")]
#[display("client_secret_jwt")]
ClientSecretJwt,
/// `private_key_jwt`
#[serde(rename = "private_key_jwt")]
#[schemars(rename = "private_key_jwt")]
#[display("private_key_jwt")]
PrivateKeyJwt,
/// `tls_client_auth`
#[serde(rename = "tls_client_auth")]
#[schemars(rename = "tls_client_auth")]
#[display("tls_client_auth")]
TlsClientAuth,
/// `self_signed_tls_client_auth`
#[serde(rename = "self_signed_tls_client_auth")]
#[schemars(rename = "self_signed_tls_client_auth")]
#[display("self_signed_tls_client_auth")]
SelfSignedTlsClientAuth,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}
/// PKCE Code Challenge Method
@ -212,7 +226,6 @@ pub enum OAuthClientAuthenticationMethod {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
@ -220,18 +233,24 @@ pub enum OAuthClientAuthenticationMethod {
Hash,
Display,
FromStr,
Serialize,
Deserialize,
SerializeDisplay,
DeserializeFromStr,
JsonSchema,
)]
#[non_exhaustive]
pub enum PkceCodeChallengeMethod {
/// `plain`
#[serde(rename = "plain")]
#[schemars(rename = "plain")]
#[display("plain")]
Plain,
/// `S256`
#[serde(rename = "S256")]
#[schemars(rename = "S256")]
#[display("S256")]
S256,
/// An unknown value.
#[display("{0}")]
#[schemars(skip)]
Unknown(String),
}

View File

@ -248,7 +248,7 @@ impl From<&TimeOptions> for TimeNotBefore {
/// Returns an error if the algorithm is not supported.
///
/// [OpenID Connect Core 1.0 specification]: https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken
pub fn hash_token(alg: JsonWebSignatureAlg, token: &str) -> anyhow::Result<String> {
pub fn hash_token(alg: &JsonWebSignatureAlg, token: &str) -> anyhow::Result<String> {
let bits = match alg {
JsonWebSignatureAlg::Hs256
| JsonWebSignatureAlg::Rs256
@ -281,9 +281,7 @@ pub fn hash_token(alg: JsonWebSignatureAlg, token: &str) -> anyhow::Result<Strin
// Left-most half
hash.get(..32).map(ToOwned::to_owned)
}
JsonWebSignatureAlg::EdDsa | JsonWebSignatureAlg::None => {
return Err(anyhow::anyhow!("unsupported algorithm for hashing"))
}
_ => return Err(anyhow::anyhow!("unsupported algorithm for hashing")),
}
.context("failed to get first half of hash")?;
@ -292,14 +290,14 @@ pub fn hash_token(alg: JsonWebSignatureAlg, token: &str) -> anyhow::Result<Strin
#[derive(Debug, Clone)]
pub struct TokenHash<'a> {
alg: JsonWebSignatureAlg,
alg: &'a JsonWebSignatureAlg,
token: &'a str,
}
impl<'a> TokenHash<'a> {
/// Creates a new `TokenHash` validator for the given algorithm and token.
#[must_use]
pub fn new(alg: JsonWebSignatureAlg, token: &'a str) -> Self {
pub fn new(alg: &'a JsonWebSignatureAlg, token: &'a str) -> Self {
Self { alg, token }
}
}

View File

@ -21,7 +21,7 @@ use crate::jwt::JsonWebSignatureHeader;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Constraint<'a> {
Alg {
constraint_alg: JsonWebSignatureAlg,
constraint_alg: &'a JsonWebSignatureAlg,
},
Algs {
@ -33,17 +33,17 @@ pub enum Constraint<'a> {
},
Use {
constraint_use: JsonWebKeyUse,
constraint_use: &'a JsonWebKeyUse,
},
Kty {
constraint_kty: JsonWebKeyType,
constraint_kty: &'a JsonWebKeyType,
},
}
impl<'a> Constraint<'a> {
#[must_use]
pub fn alg(constraint_alg: JsonWebSignatureAlg) -> Self {
pub fn alg(constraint_alg: &'a JsonWebSignatureAlg) -> Self {
Constraint::Alg { constraint_alg }
}
@ -58,12 +58,12 @@ impl<'a> Constraint<'a> {
}
#[must_use]
pub fn use_(constraint_use: JsonWebKeyUse) -> Self {
pub fn use_(constraint_use: &'a JsonWebKeyUse) -> Self {
Constraint::Use { constraint_use }
}
#[must_use]
pub fn kty(constraint_kty: JsonWebKeyType) -> Self {
pub fn kty(constraint_kty: &'a JsonWebKeyType) -> Self {
Constraint::Kty { constraint_kty }
}
}
@ -76,7 +76,7 @@ pub enum ConstraintDecision {
}
pub trait Constrainable {
fn alg(&self) -> Option<JsonWebSignatureAlg> {
fn alg(&self) -> Option<&JsonWebSignatureAlg> {
None
}
@ -91,7 +91,7 @@ pub trait Constrainable {
}
/// Usage specified for this key
fn use_(&self) -> Option<JsonWebKeyUse> {
fn use_(&self) -> Option<&JsonWebKeyUse> {
None
}
@ -120,7 +120,7 @@ impl<'a> Constraint<'a> {
}
Constraint::Algs { constraint_algs } => {
if let Some(alg) = constrainable.alg() {
if constraint_algs.contains(&alg) {
if constraint_algs.contains(alg) {
ConstraintDecision::Positive
} else {
ConstraintDecision::Negative
@ -158,7 +158,7 @@ impl<'a> Constraint<'a> {
}
}
Constraint::Kty { constraint_kty } => {
if *constraint_kty == constrainable.kty() {
if **constraint_kty == constrainable.kty() {
ConstraintDecision::Positive
} else {
ConstraintDecision::Negative
@ -217,7 +217,7 @@ impl<'a> ConstraintSet<'a> {
}
#[must_use]
pub fn alg(mut self, constraint_alg: JsonWebSignatureAlg) -> Self {
pub fn alg(mut self, constraint_alg: &'a JsonWebSignatureAlg) -> Self {
self.constraints.insert(Constraint::alg(constraint_alg));
self
}
@ -235,13 +235,13 @@ impl<'a> ConstraintSet<'a> {
}
#[must_use]
pub fn use_(mut self, constraint_use: JsonWebKeyUse) -> Self {
pub fn use_(mut self, constraint_use: &'a JsonWebKeyUse) -> Self {
self.constraints.insert(Constraint::use_(constraint_use));
self
}
#[must_use]
pub fn kty(mut self, constraint_kty: JsonWebKeyType) -> Self {
pub fn kty(mut self, constraint_kty: &'a JsonWebKeyType) -> Self {
self.constraints.insert(Constraint::kty(constraint_kty));
self
}

View File

@ -59,7 +59,7 @@ impl AsymmetricSigningKey {
#[allow(dead_code)]
pub fn from_jwk_and_alg(
params: &JsonWebKeyPrivateParameters,
alg: JsonWebSignatureAlg,
alg: &JsonWebSignatureAlg,
) -> Result<Self, AsymmetricKeyFromJwkError> {
match (params, alg) {
(JsonWebKeyPrivateParameters::Rsa(params), alg) => match alg {
@ -69,7 +69,7 @@ impl AsymmetricSigningKey {
JsonWebSignatureAlg::Ps256 => Ok(Self::Ps256(params.try_into()?)),
JsonWebSignatureAlg::Ps384 => Ok(Self::Ps384(params.try_into()?)),
JsonWebSignatureAlg::Ps512 => Ok(Self::Ps512(params.try_into()?)),
_ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg }),
_ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg: alg.clone() }),
},
(JsonWebKeyPrivateParameters::Ec(params), JsonWebSignatureAlg::Es256)
@ -87,7 +87,7 @@ impl AsymmetricSigningKey {
(JsonWebKeyPrivateParameters::Ec(params), JsonWebSignatureAlg::Es512)
if params.crv == JsonWebKeyEcEllipticCurve::P521 =>
{
Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg })
Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg: alg.clone() })
}
(JsonWebKeyPrivateParameters::Ec(params), JsonWebSignatureAlg::Es256K)
@ -97,10 +97,10 @@ impl AsymmetricSigningKey {
}
(JsonWebKeyPrivateParameters::Okp(_params), JsonWebSignatureAlg::EdDsa) => {
Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg })
Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg: alg.clone() })
}
_ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg }),
_ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg: alg.clone() }),
}
}
}
@ -219,7 +219,7 @@ pub enum AsymmetricVerifyingKey {
impl AsymmetricVerifyingKey {
pub fn from_jwk_and_alg(
params: &JsonWebKeyPublicParameters,
alg: JsonWebSignatureAlg,
alg: &JsonWebSignatureAlg,
) -> Result<Self, AsymmetricKeyFromJwkError> {
match (params, alg) {
(JsonWebKeyPublicParameters::Rsa(params), alg) => match alg {
@ -229,7 +229,7 @@ impl AsymmetricVerifyingKey {
JsonWebSignatureAlg::Ps256 => Ok(Self::Ps256(params.try_into()?)),
JsonWebSignatureAlg::Ps384 => Ok(Self::Ps384(params.try_into()?)),
JsonWebSignatureAlg::Ps512 => Ok(Self::Ps512(params.try_into()?)),
_ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg }),
_ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg: alg.clone() }),
},
(JsonWebKeyPublicParameters::Ec(params), JsonWebSignatureAlg::Es256)
@ -247,7 +247,7 @@ impl AsymmetricVerifyingKey {
(JsonWebKeyPublicParameters::Ec(params), JsonWebSignatureAlg::Es512)
if params.crv == JsonWebKeyEcEllipticCurve::P521 =>
{
Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg })
Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg: alg.clone() })
}
(JsonWebKeyPublicParameters::Ec(params), JsonWebSignatureAlg::Es256K)
@ -257,10 +257,10 @@ impl AsymmetricVerifyingKey {
}
(JsonWebKeyPublicParameters::Okp(_params), JsonWebSignatureAlg::EdDsa) => {
Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg })
Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg: alg.clone() })
}
_ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg }),
_ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg: alg.clone() }),
}
}
}

View File

@ -33,15 +33,15 @@ pub struct InvalidAlgorithm {
}
impl SymmetricKey {
pub const fn new_for_alg(
key: Vec<u8>,
alg: JsonWebSignatureAlg,
) -> Result<Self, InvalidAlgorithm> {
pub fn new_for_alg(key: Vec<u8>, alg: &JsonWebSignatureAlg) -> Result<Self, InvalidAlgorithm> {
match alg {
JsonWebSignatureAlg::Hs256 => Ok(Self::hs256(key)),
JsonWebSignatureAlg::Hs384 => Ok(Self::hs384(key)),
JsonWebSignatureAlg::Hs512 => Ok(Self::hs512(key)),
_ => Err(InvalidAlgorithm { alg, key }),
_ => Err(InvalidAlgorithm {
alg: alg.clone(),
key,
}),
}
}

View File

@ -166,9 +166,9 @@ impl<P> JsonWebKey<P> {
{
Ok(JsonWebKey {
parameters: mapper(&self.parameters)?,
r#use: self.r#use,
r#use: self.r#use.clone(),
key_ops: self.key_ops.clone(),
alg: self.alg,
alg: self.alg.clone(),
kid: self.kid.clone(),
x5u: self.x5u.clone(),
x5c: self.x5c.clone(),
@ -183,9 +183,9 @@ impl<P> JsonWebKey<P> {
{
JsonWebKey {
parameters: mapper(&self.parameters),
r#use: self.r#use,
r#use: self.r#use.clone(),
key_ops: self.key_ops.clone(),
alg: self.alg,
alg: self.alg.clone(),
kid: self.kid.clone(),
x5u: self.x5u.clone(),
x5c: self.x5c.clone(),
@ -195,7 +195,7 @@ impl<P> JsonWebKey<P> {
}
#[must_use]
pub const fn with_use(mut self, value: JsonWebKeyUse) -> Self {
pub fn with_use(mut self, value: JsonWebKeyUse) -> Self {
self.r#use = Some(value);
self
}
@ -207,7 +207,7 @@ impl<P> JsonWebKey<P> {
}
#[must_use]
pub const fn with_alg(mut self, alg: JsonWebSignatureAlg) -> Self {
pub fn with_alg(mut self, alg: JsonWebSignatureAlg) -> Self {
self.alg = Some(alg);
self
}
@ -219,8 +219,8 @@ impl<P> JsonWebKey<P> {
}
#[must_use]
pub const fn alg(&self) -> Option<JsonWebSignatureAlg> {
self.alg
pub const fn alg(&self) -> Option<&JsonWebSignatureAlg> {
self.alg.as_ref()
}
#[must_use]
@ -245,12 +245,12 @@ where
self.parameters.possible_algs()
}
fn alg(&self) -> Option<JsonWebSignatureAlg> {
self.alg
fn alg(&self) -> Option<&JsonWebSignatureAlg> {
self.alg.as_ref()
}
fn use_(&self) -> Option<JsonWebKeyUse> {
self.r#use
fn use_(&self) -> Option<&JsonWebKeyUse> {
self.r#use.as_ref()
}
}
@ -317,13 +317,13 @@ impl<P> JsonWebKeySet<P> {
/// Find a key for the given algorithm. Returns `None` if no suitable key
/// was found.
#[must_use]
pub fn signing_key_for_algorithm(&self, alg: JsonWebSignatureAlg) -> Option<&JsonWebKey<P>>
pub fn signing_key_for_algorithm(&self, alg: &JsonWebSignatureAlg) -> Option<&JsonWebKey<P>>
where
P: ParametersInfo,
{
let constraints = ConstraintSet::new([
Constraint::alg(alg),
Constraint::use_(mas_iana::jose::JsonWebKeyUse::Sig),
Constraint::use_(&mas_iana::jose::JsonWebKeyUse::Sig),
]);
self.find_key(&constraints)
}
@ -338,7 +338,7 @@ impl<P> JsonWebKeySet<P> {
.keys
.iter()
.flat_map(|key| key.params().possible_algs())
.copied()
.cloned()
.collect();
algs.sort();
algs.dedup();
@ -389,15 +389,15 @@ mod tests {
}
let constraints = ConstraintSet::default()
.use_(JsonWebKeyUse::Sig)
.kty(JsonWebKeyType::Rsa)
.alg(JsonWebSignatureAlg::Rs256);
.use_(&JsonWebKeyUse::Sig)
.kty(&JsonWebKeyType::Rsa)
.alg(&JsonWebSignatureAlg::Rs256);
let candidates = constraints.filter(&jwks.keys);
assert_eq!(candidates.len(), 2);
let constraints = ConstraintSet::default()
.use_(JsonWebKeyUse::Sig)
.kty(JsonWebKeyType::Rsa)
.use_(&JsonWebKeyUse::Sig)
.kty(&JsonWebKeyType::Rsa)
.kid("03e84aed4ef4431014e8617567864c4efaaaede9");
let candidates = constraints.filter(&jwks.keys);
assert_eq!(candidates.len(), 1);

View File

@ -335,6 +335,7 @@ impl ParametersInfo for EcPrivateParameters {
JsonWebKeyEcEllipticCurve::P384 => &[JsonWebSignatureAlg::Es384],
JsonWebKeyEcEllipticCurve::P521 => &[JsonWebSignatureAlg::Es512],
JsonWebKeyEcEllipticCurve::Secp256K1 => &[JsonWebSignatureAlg::Es256K],
_ => &[],
}
}
}

View File

@ -137,8 +137,8 @@ impl EcPublicParameters {
Self { crv, x, y }
}
pub const fn crv(&self) -> JsonWebKeyEcEllipticCurve {
self.crv
pub const fn crv(&self) -> &JsonWebKeyEcEllipticCurve {
&self.crv
}
}
@ -148,11 +148,12 @@ impl ParametersInfo for EcPublicParameters {
}
fn possible_algs(&self) -> &[JsonWebSignatureAlg] {
match self.crv {
match &self.crv {
JsonWebKeyEcEllipticCurve::P256 => &[JsonWebSignatureAlg::Es256],
JsonWebKeyEcEllipticCurve::P384 => &[JsonWebSignatureAlg::Es384],
JsonWebKeyEcEllipticCurve::P521 => &[JsonWebSignatureAlg::Es512],
JsonWebKeyEcEllipticCurve::Secp256K1 => &[JsonWebSignatureAlg::Es256K],
_ => &[],
}
}
}
@ -182,8 +183,8 @@ impl OkpPublicParameters {
Self { crv, x }
}
pub const fn crv(&self) -> JsonWebKeyOkpEllipticCurve {
self.crv
pub const fn crv(&self) -> &JsonWebKeyOkpEllipticCurve {
&self.crv
}
}
@ -360,7 +361,7 @@ mod ec_impls {
type Error = ecdsa::Error;
fn try_from(value: &EcPublicParameters) -> Result<Self, Self::Error> {
if value.crv() != C::CRV {
if *value.crv() != C::CRV {
return Err(Self::Error::default());
}

View File

@ -82,8 +82,8 @@ impl JsonWebSignatureHeader {
}
#[must_use]
pub const fn alg(&self) -> JsonWebSignatureAlg {
self.alg
pub const fn alg(&self) -> &JsonWebSignatureAlg {
&self.alg
}
#[must_use]

View File

@ -70,7 +70,7 @@ macro_rules! asymetric_jwt_test {
fn validate_jwt() {
let jwt: Jwt<'_, Payload> = Jwt::try_from($jwt).unwrap();
assert_eq!(jwt.payload().hello, "world");
assert_eq!(jwt.header().alg(), JsonWebSignatureAlg::$alg);
assert_eq!(*jwt.header().alg(), JsonWebSignatureAlg::$alg);
}
#[test]
@ -105,7 +105,7 @@ macro_rules! asymetric_jwt_test {
let key = mas_jose::jwa::AsymmetricVerifyingKey::from_jwk_and_alg(
key.params(),
JsonWebSignatureAlg::$alg,
&JsonWebSignatureAlg::$alg,
)
.unwrap();
@ -118,12 +118,12 @@ macro_rules! asymetric_jwt_test {
let payload = Payload {
hello: "world".to_string(),
};
let header = JsonWebSignatureHeader::new(alg);
let header = JsonWebSignatureHeader::new(alg.clone());
let jwks = private_jwks();
let key = jwks.signing_key_for_algorithm(alg).unwrap();
let key = jwks.signing_key_for_algorithm(&alg).unwrap();
let key = mas_jose::jwa::AsymmetricSigningKey::from_jwk_and_alg(key.params(), alg)
let key = mas_jose::jwa::AsymmetricSigningKey::from_jwk_and_alg(key.params(), &alg)
.unwrap();
let jwt: Jwt<'_, Payload> = Jwt::sign(header, payload, &key).unwrap();
@ -133,7 +133,7 @@ macro_rules! asymetric_jwt_test {
let key = jwks.find_key(&jwt.header().into()).unwrap();
let key =
mas_jose::jwa::AsymmetricVerifyingKey::from_jwk_and_alg(key.params(), alg)
mas_jose::jwa::AsymmetricVerifyingKey::from_jwk_and_alg(key.params(), &alg)
.unwrap();
jwt.verify(&key).unwrap();
@ -155,14 +155,14 @@ macro_rules! symetric_jwt_test {
fn validate_jwt() {
let jwt: Jwt<'_, Payload> = Jwt::try_from($jwt).unwrap();
assert_eq!(jwt.payload().hello, "world");
assert_eq!(jwt.header().alg(), JsonWebSignatureAlg::$alg);
assert_eq!(*jwt.header().alg(), JsonWebSignatureAlg::$alg);
}
#[test]
fn verify_jwt() {
let jwt: Jwt<'_, Payload> = Jwt::try_from($jwt).unwrap();
let key =
mas_jose::jwa::SymmetricKey::new_for_alg(oct_key(), JsonWebSignatureAlg::$alg)
mas_jose::jwa::SymmetricKey::new_for_alg(oct_key(), &JsonWebSignatureAlg::$alg)
.unwrap();
jwt.verify(&key).unwrap();
}
@ -173,9 +173,9 @@ macro_rules! symetric_jwt_test {
let payload = Payload {
hello: "world".to_string(),
};
let header = JsonWebSignatureHeader::new(alg);
let header = JsonWebSignatureHeader::new(alg.clone());
let key = mas_jose::jwa::SymmetricKey::new_for_alg(oct_key(), alg).unwrap();
let key = mas_jose::jwa::SymmetricKey::new_for_alg(oct_key(), &alg).unwrap();
let jwt: Jwt<'_, Payload> = Jwt::sign(header, payload, &key).unwrap();
let jwt: Jwt<'_, Payload> = Jwt::try_from(jwt.as_str()).unwrap();

View File

@ -415,7 +415,7 @@ impl PrivateKey {
/// Returns an error if the key is not suited for the selected algorithm
pub fn verifying_key_for_alg(
&self,
alg: JsonWebSignatureAlg,
alg: &JsonWebSignatureAlg,
) -> Result<AsymmetricVerifyingKey, WrongAlgorithmError> {
let key = match (self, alg) {
(Self::Rsa(key), _) => {
@ -469,7 +469,7 @@ impl PrivateKey {
/// Returns an error if the key is not suited for the selected algorithm
pub fn signing_key_for_alg(
&self,
alg: JsonWebSignatureAlg,
alg: &JsonWebSignatureAlg,
) -> Result<AsymmetricSigningKey, WrongAlgorithmError> {
let key = match (self, alg) {
(Self::Rsa(key), _) => {

View File

@ -33,8 +33,8 @@ macro_rules! plain_test {
let algs = key.possible_algs();
assert_ne!(algs.len(), 0);
for &alg in algs {
let header = JsonWebSignatureHeader::new(alg);
for alg in algs {
let header = JsonWebSignatureHeader::new(alg.clone());
let payload = "hello";
let signer = key.signing_key_for_alg(alg).unwrap();
let jwt = Jwt::sign(header, payload, &signer).unwrap();
@ -58,8 +58,8 @@ macro_rules! enc_test {
let algs = key.possible_algs();
assert_ne!(algs.len(), 0);
for &alg in algs {
let header = JsonWebSignatureHeader::new(alg);
for alg in algs {
let header = JsonWebSignatureHeader::new(alg.clone());
let payload = "hello";
let signer = key.signing_key_for_alg(alg).unwrap();
let jwt = Jwt::sign(header, payload, &signer).unwrap();

View File

@ -33,7 +33,7 @@ use crate::{
/// An enum for types that accept either an [`OAuthClientAuthenticationMethod`]
/// or an [`OAuthAccessTokenType`].
#[derive(
SerializeDisplay, DeserializeFromStr, Clone, Copy, PartialEq, Eq, Hash, Debug, Display, FromStr,
SerializeDisplay, DeserializeFromStr, Clone, PartialEq, Eq, Hash, Debug, Display, FromStr,
)]
pub enum AuthenticationMethodOrAccessTokenType {
/// An authentication method.
@ -49,9 +49,9 @@ impl AuthenticationMethodOrAccessTokenType {
/// Get the authentication method of this
/// `AuthenticationMethodOrAccessTokenType`.
#[must_use]
pub fn authentication_method(&self) -> Option<OAuthClientAuthenticationMethod> {
pub fn authentication_method(&self) -> Option<&OAuthClientAuthenticationMethod> {
match self {
Self::AuthenticationMethod(m) => Some(*m),
Self::AuthenticationMethod(m) => Some(m),
Self::AccessTokenType(_) => None,
}
}
@ -59,10 +59,10 @@ impl AuthenticationMethodOrAccessTokenType {
/// Get the access token type of this
/// `AuthenticationMethodOrAccessTokenType`.
#[must_use]
pub fn access_token_type(&self) -> Option<OAuthAccessTokenType> {
pub fn access_token_type(&self) -> Option<&OAuthAccessTokenType> {
match self {
Self::AuthenticationMethod(_) => None,
Self::AccessTokenType(t) => Some(*t),
Self::AccessTokenType(t) => Some(t),
}
}
}
@ -470,8 +470,14 @@ impl ProviderMetadata {
validate_signing_alg_values_supported(
"token_endpoint",
&metadata.token_endpoint_auth_signing_alg_values_supported,
&metadata.token_endpoint_auth_methods_supported,
metadata
.token_endpoint_auth_signing_alg_values_supported
.iter()
.flatten(),
metadata
.token_endpoint_auth_methods_supported
.iter()
.flatten(),
)?;
if let Some(url) = &metadata.revocation_endpoint {
@ -480,8 +486,14 @@ impl ProviderMetadata {
validate_signing_alg_values_supported(
"revocation_endpoint",
&metadata.revocation_endpoint_auth_signing_alg_values_supported,
&metadata.revocation_endpoint_auth_methods_supported,
metadata
.revocation_endpoint_auth_signing_alg_values_supported
.iter()
.flatten(),
metadata
.revocation_endpoint_auth_methods_supported
.iter()
.flatten(),
)?;
if let Some(url) = &metadata.introspection_endpoint {
@ -500,8 +512,11 @@ impl ProviderMetadata {
});
validate_signing_alg_values_supported(
"introspection_endpoint",
&metadata.introspection_endpoint_auth_signing_alg_values_supported,
&introspection_methods,
metadata
.introspection_endpoint_auth_signing_alg_values_supported
.iter()
.flatten(),
introspection_methods.into_iter().flatten(),
)?;
if let Some(url) = &metadata.userinfo_endpoint {
@ -957,24 +972,32 @@ fn validate_url(
/// - The algorithm values must not contain `none`,
/// - If the `client_secret_jwt` or `private_key_jwt` authentication methods are
/// supported, the values must be present.
fn validate_signing_alg_values_supported(
fn validate_signing_alg_values_supported<'a>(
endpoint: &'static str,
values: &Option<Vec<JsonWebSignatureAlg>>,
methods: &Option<Vec<OAuthClientAuthenticationMethod>>,
values: impl Iterator<Item = &'a JsonWebSignatureAlg>,
mut methods: impl Iterator<Item = &'a OAuthClientAuthenticationMethod>,
) -> Result<(), ProviderMetadataVerificationError> {
if let Some(values) = values {
if values.contains(&JsonWebSignatureAlg::None) {
let mut no_values = true;
for value in values {
if *value == JsonWebSignatureAlg::None {
return Err(ProviderMetadataVerificationError::SigningAlgValuesWithNone(
endpoint,
));
}
} else if methods.iter().flatten().any(|method| {
matches!(
method,
OAuthClientAuthenticationMethod::ClientSecretJwt
| OAuthClientAuthenticationMethod::PrivateKeyJwt
)
}) {
no_values = false;
}
if no_values
&& methods.any(|method| {
matches!(
method,
OAuthClientAuthenticationMethod::ClientSecretJwt
| OAuthClientAuthenticationMethod::PrivateKeyJwt
)
})
{
return Err(ProviderMetadataVerificationError::MissingAuthSigningAlgValues(endpoint));
}

View File

@ -33,6 +33,9 @@ pub enum CodeChallengeError {
#[error("challenge verification failed")]
VerificationFailed,
#[error("unknown challenge method")]
UnknownChallengeMethod,
}
fn validate_verifier(verifier: &str) -> Result<(), CodeChallengeError> {
@ -61,7 +64,7 @@ pub trait CodeChallengeMethodExt {
///
/// Returns an error if the verifier did not adhere to the rules defined by
/// the RFC in terms of length and allowed characters
fn compute_challenge(self, verifier: &str) -> Result<Cow<'_, str>, CodeChallengeError>;
fn compute_challenge<'a>(&self, verifier: &'a str) -> Result<Cow<'a, str>, CodeChallengeError>;
/// Verify that a given verifier is valid for the given challenge
///
@ -70,7 +73,7 @@ pub trait CodeChallengeMethodExt {
/// Returns an error if the verifier did not match the challenge, or if the
/// verifier did not adhere to the rules defined by the RFC in terms of
/// length and allowed characters
fn verify(self, challenge: &str, verifier: &str) -> Result<(), CodeChallengeError>
fn verify(&self, challenge: &str, verifier: &str) -> Result<(), CodeChallengeError>
where
Self: Sized,
{
@ -83,7 +86,7 @@ pub trait CodeChallengeMethodExt {
}
impl CodeChallengeMethodExt for PkceCodeChallengeMethod {
fn compute_challenge(self, verifier: &str) -> Result<Cow<'_, str>, CodeChallengeError> {
fn compute_challenge<'a>(&self, verifier: &'a str) -> Result<Cow<'a, str>, CodeChallengeError> {
validate_verifier(verifier)?;
let challenge = match self {
@ -95,6 +98,7 @@ impl CodeChallengeMethodExt for PkceCodeChallengeMethod {
let verifier = BASE64URL_NOPAD.encode(&hash);
verifier.into()
}
_ => return Err(CodeChallengeError::UnknownChallengeMethod),
};
Ok(challenge)

View File

@ -42,13 +42,13 @@ pub const DEFAULT_GRANT_TYPES: &[GrantType] = &[GrantType::AuthorizationCode];
pub const DEFAULT_APPLICATION_TYPE: ApplicationType = ApplicationType::Web;
pub const DEFAULT_TOKEN_AUTH_METHOD: OAuthClientAuthenticationMethod =
OAuthClientAuthenticationMethod::ClientSecretBasic;
pub const DEFAULT_TOKEN_AUTH_METHOD: &OAuthClientAuthenticationMethod =
&OAuthClientAuthenticationMethod::ClientSecretBasic;
pub const DEFAULT_SIGNING_ALGORITHM: JsonWebSignatureAlg = JsonWebSignatureAlg::Rs256;
pub const DEFAULT_SIGNING_ALGORITHM: &JsonWebSignatureAlg = &JsonWebSignatureAlg::Rs256;
pub const DEFAULT_ENCRYPTION_ENC_ALGORITHM: JsonWebEncryptionEnc =
JsonWebEncryptionEnc::A128CbcHs256;
pub const DEFAULT_ENCRYPTION_ENC_ALGORITHM: &JsonWebEncryptionEnc =
&JsonWebEncryptionEnc::A128CbcHs256;
/// A collection of localized variants.
///
@ -463,7 +463,7 @@ impl ClientMetadata {
));
}
if self.token_endpoint_auth_method() == OAuthClientAuthenticationMethod::PrivateKeyJwt
if *self.token_endpoint_auth_method() == OAuthClientAuthenticationMethod::PrivateKeyJwt
&& self.jwks_uri.is_none()
&& self.jwks.is_none()
{
@ -486,26 +486,26 @@ impl ClientMetadata {
));
}
if self.id_token_signed_response_alg() == JsonWebSignatureAlg::None
if *self.id_token_signed_response_alg() == JsonWebSignatureAlg::None
&& response_types.iter().any(ResponseType::has_id_token)
{
return Err(ClientMetadataVerificationError::IdTokenSigningAlgNone);
}
if self.id_token_encrypted_response_enc.is_some() {
self.id_token_encrypted_response_alg.ok_or(
self.id_token_encrypted_response_alg.as_ref().ok_or(
ClientMetadataVerificationError::MissingEncryptionAlg("id_token"),
)?;
}
if self.userinfo_encrypted_response_enc.is_some() {
self.userinfo_encrypted_response_alg.ok_or(
self.userinfo_encrypted_response_alg.as_ref().ok_or(
ClientMetadataVerificationError::MissingEncryptionAlg("userinfo"),
)?;
}
if self.request_object_encryption_enc.is_some() {
self.request_object_encryption_alg.ok_or(
self.request_object_encryption_alg.as_ref().ok_or(
ClientMetadataVerificationError::MissingEncryptionAlg("request_object"),
)?;
}
@ -522,7 +522,7 @@ impl ClientMetadata {
}
if self.introspection_encrypted_response_enc.is_some() {
self.introspection_encrypted_response_alg.ok_or(
self.introspection_encrypted_response_alg.as_ref().ok_or(
ClientMetadataVerificationError::MissingEncryptionAlg("introspection"),
)?;
}
@ -542,9 +542,12 @@ impl ClientMetadata {
/// [authorization endpoint]: https://www.rfc-editor.org/rfc/rfc6749.html#section-3.1
#[must_use]
pub fn response_types(&self) -> Vec<ResponseType> {
self.response_types
.clone()
.unwrap_or_else(|| DEFAULT_RESPONSE_TYPES.map(ResponseType::from).into())
self.response_types.clone().unwrap_or_else(|| {
DEFAULT_RESPONSE_TYPES
.into_iter()
.filter_map(|t| ResponseType::try_from(t).ok())
.collect()
})
}
/// Array of [OAuth 2.0 `grant_type` values] that the client can use at the
@ -578,8 +581,9 @@ impl ClientMetadata {
///
/// [token endpoint]: https://www.rfc-editor.org/rfc/rfc6749.html#section-3.2
#[must_use]
pub fn token_endpoint_auth_method(&self) -> OAuthClientAuthenticationMethod {
pub fn token_endpoint_auth_method(&self) -> &OAuthClientAuthenticationMethod {
self.token_endpoint_auth_method
.as_ref()
.unwrap_or(DEFAULT_TOKEN_AUTH_METHOD)
}
@ -594,8 +598,9 @@ impl ClientMetadata {
///
/// [JWS]: http://tools.ietf.org/html/draft-ietf-jose-json-web-signature
#[must_use]
pub fn id_token_signed_response_alg(&self) -> JsonWebSignatureAlg {
pub fn id_token_signed_response_alg(&self) -> &JsonWebSignatureAlg {
self.id_token_signed_response_alg
.as_ref()
.unwrap_or(DEFAULT_SIGNING_ALGORITHM)
}
@ -610,11 +615,12 @@ impl ClientMetadata {
#[must_use]
pub fn id_token_encrypted_response(
&self,
) -> Option<(JsonWebEncryptionAlg, JsonWebEncryptionEnc)> {
self.id_token_encrypted_response_alg.map(|alg| {
) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
self.id_token_encrypted_response_alg.as_ref().map(|alg| {
(
alg,
self.id_token_encrypted_response_enc
.as_ref()
.unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
)
})
@ -631,11 +637,12 @@ impl ClientMetadata {
#[must_use]
pub fn userinfo_encrypted_response(
&self,
) -> Option<(JsonWebEncryptionAlg, JsonWebEncryptionEnc)> {
self.userinfo_encrypted_response_alg.map(|alg| {
) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
self.userinfo_encrypted_response_alg.as_ref().map(|alg| {
(
alg,
self.userinfo_encrypted_response_enc
.as_ref()
.unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
)
})
@ -652,11 +659,12 @@ impl ClientMetadata {
#[must_use]
pub fn request_object_encryption(
&self,
) -> Option<(JsonWebEncryptionAlg, JsonWebEncryptionEnc)> {
self.request_object_encryption_alg.map(|alg| {
) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
self.request_object_encryption_alg.as_ref().map(|alg| {
(
alg,
self.request_object_encryption_enc
.as_ref()
.unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
)
})
@ -705,14 +713,17 @@ impl ClientMetadata {
#[must_use]
pub fn introspection_encrypted_response(
&self,
) -> Option<(JsonWebEncryptionAlg, JsonWebEncryptionEnc)> {
self.introspection_encrypted_response_alg.map(|alg| {
(
alg,
self.introspection_encrypted_response_enc
.unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
)
})
) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
self.introspection_encrypted_response_alg
.as_ref()
.map(|alg| {
(
alg,
self.introspection_encrypted_response_enc
.as_ref()
.unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
)
})
}
}

View File

@ -332,10 +332,10 @@ pub async fn insert_client(
tos_uri: Option<&Url>,
jwks_uri: Option<&Url>,
jwks: Option<&PublicJsonWebKeySet>,
id_token_signed_response_alg: Option<JsonWebSignatureAlg>,
userinfo_signed_response_alg: Option<JsonWebSignatureAlg>,
token_endpoint_auth_method: Option<OAuthClientAuthenticationMethod>,
token_endpoint_auth_signing_alg: Option<JsonWebSignatureAlg>,
id_token_signed_response_alg: Option<&JsonWebSignatureAlg>,
userinfo_signed_response_alg: Option<&JsonWebSignatureAlg>,
token_endpoint_auth_method: Option<&OAuthClientAuthenticationMethod>,
token_endpoint_auth_signing_alg: Option<&JsonWebSignatureAlg>,
initiate_login_uri: Option<&Url>,
) -> Result<(), sqlx::Error> {
let response_types: Vec<String> = response_types.iter().map(ToString::to_string).collect();
@ -347,10 +347,10 @@ pub async fn insert_client(
let tos_uri = tos_uri.map(Url::as_str);
let jwks = jwks.map(serde_json::to_value).transpose().unwrap(); // TODO
let jwks_uri = jwks_uri.map(Url::as_str);
let id_token_signed_response_alg = id_token_signed_response_alg.map(|v| v.to_string());
let userinfo_signed_response_alg = userinfo_signed_response_alg.map(|v| v.to_string());
let token_endpoint_auth_method = token_endpoint_auth_method.map(|v| v.to_string());
let token_endpoint_auth_signing_alg = token_endpoint_auth_signing_alg.map(|v| v.to_string());
let id_token_signed_response_alg = id_token_signed_response_alg.map(ToString::to_string);
let userinfo_signed_response_alg = userinfo_signed_response_alg.map(ToString::to_string);
let token_endpoint_auth_method = token_endpoint_auth_method.map(ToString::to_string);
let token_endpoint_auth_signing_alg = token_endpoint_auth_signing_alg.map(ToString::to_string);
let initiate_login_uri = initiate_login_uri.map(Url::as_str);
let id = sqlx::query_scalar!(