You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-07-31 09:24:31 +03:00
Add tests for private_key_jwt client auth
This commit is contained in:
@ -61,6 +61,12 @@ impl JwksOrJwksUri {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<JsonWebKeySet> for JwksOrJwksUri {
|
||||||
|
fn from(jwks: JsonWebKeySet) -> Self {
|
||||||
|
Self::Jwks(jwks)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug)]
|
#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(tag = "client_auth_method", rename_all = "snake_case")]
|
#[serde(tag = "client_auth_method", rename_all = "snake_case")]
|
||||||
pub enum OAuth2ClientAuthMethodConfig {
|
pub enum OAuth2ClientAuthMethodConfig {
|
||||||
|
@ -18,21 +18,59 @@ use anyhow::bail;
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use base64ct::{Base64UrlUnpadded, Encoding};
|
use base64ct::{Base64UrlUnpadded, Encoding};
|
||||||
use digest::Digest;
|
use digest::Digest;
|
||||||
use ecdsa::VerifyingKey;
|
use ecdsa::{SigningKey, VerifyingKey};
|
||||||
use p256::{NistP256, PublicKey};
|
use p256::{NistP256, PublicKey};
|
||||||
use pkcs1::EncodeRsaPublicKey;
|
use pkcs1::{DecodeRsaPrivateKey, EncodeRsaPublicKey};
|
||||||
use pkcs8::EncodePublicKey;
|
use pkcs8::{DecodePrivateKey, EncodePublicKey};
|
||||||
use rsa::{PublicKey as _, RsaPublicKey};
|
use rsa::{PublicKey as _, RsaPrivateKey, RsaPublicKey};
|
||||||
use sha2::{Sha256, Sha384, Sha512};
|
use sha2::{Sha256, Sha384, Sha512};
|
||||||
use signature::{Signature, Signer, Verifier};
|
use signature::{Signature, Signer, Verifier};
|
||||||
|
|
||||||
use super::{ExportJwks, SigningKeystore, VerifyingKeystore};
|
use super::{ExportJwks, SigningKeystore, VerifyingKeystore};
|
||||||
use crate::{iana::JsonWebSignatureAlgorithm, JsonWebKey, JsonWebKeySet, JwtHeader};
|
use crate::{iana::JsonWebSignatureAlgorithm, JsonWebKey, JsonWebKeySet, JwtHeader};
|
||||||
|
|
||||||
|
// Generate with
|
||||||
|
// openssl genrsa 2048
|
||||||
|
const TEST_RSA_PKCS1_PEM: &str = "-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEA1j7Y2CH6Ss8tgaNvcQPaRJKnCZD8ABqNPyKDWLQLph6Zi7gZ
|
||||||
|
GqmRtTzMuevo2ezpkbCiQAPEp1ms022P92bB+uqG7xmzHTzbwLtnq3OAdjmrnaFV
|
||||||
|
I4v89WHUsTXX9hiYOK5dOM81bNZ6muxWZ0L/xw4jVWe7xkqnp2Lluq0HknlzP5yJ
|
||||||
|
UEikf5BkpX0iyIu2/X4r8YVp8uzG34l/8qBx6k3rO2VkOQOSybZj1oij5KZCusnu
|
||||||
|
QjJLKWXCqJToWE6iVn+Q0N6ySDLgmJ7Zq0Sou/9N/oWKn94FOsouQgET5NuzoIFR
|
||||||
|
qTb321fQ8gbqt/OupBbBKEo1qUU+cS77TD/AuQIDAQABAoIBAQDLSZzmD+93lnf+
|
||||||
|
f36ZxOcRk/nNGPYUfx0xH+VzgHthJ73YFlozs1xflQ5JB/DM/4BsziZWCX1KsctM
|
||||||
|
XrRxMt6y4GAidcc/4eQ+T1RCGfl1tKkDi/bGIOloSGjRsV5208V0WvZ3lh2CZUy2
|
||||||
|
vbQKjUc3sFGUkzZYI7RLHosPA2mg78IVuSnqvNaU0TgA2KkaxWs6Ecr/ys80cUvj
|
||||||
|
KKj04DmX5xaXwUKmz353i5gIt3aY3G5CAw5fU/ocDKR8nzVCpBAGbRRiUaVKIT06
|
||||||
|
APSkLDTUnxSYtHtDJGHjgU/TsvAwTA92J3ue5Ysu9xTE+WyHA6Rgux7RQSD/wWHr
|
||||||
|
LdRPwxPFAoGBAOytMPh/f2zKmotanjho0QNfhAUHoQUfPudYT0nnDceOsi1jYWbQ
|
||||||
|
c/wPeQQC4Hp/pTUrkSIQPEz/hSxzZ6RPxxuGB8O94I0uLwQK4V1UwbgfsRa9zQzW
|
||||||
|
n0kgKZ8w8h8B7qyiKyIAnZzvKtNEnKrzrct4HsN3OEoXTwuAUYlvWtQTAoGBAOe8
|
||||||
|
0liNaH9V6ecZiojkRR1tiQkr/dCV+a13eXXaRA/8y/3wKCQ4idYncclQJTLKsAwW
|
||||||
|
hHuDd4uLgtifREVIBD2jGdlznNr9HQNuZgwjuUoH+r1YLGgiMWeVYSr0m8lyDlQl
|
||||||
|
BJKTAphrqo6VJWDAnM18v+by//yRleSjVMqZ3zmDAoGBAMpA0rl5EyagGON/g/hG
|
||||||
|
sl8Ej+hQdazP38yJbfCEsATaD6+z3rei6Yr8mfjwkG5+iGrgmT0XzMAsF909ndMP
|
||||||
|
jeIabqY6rBtZ3TnCJobAeG9lPctmVUVkX2h5QLhWdoJC/3iteNis2AQVam5yksOQ
|
||||||
|
S/O16ew2BHdkZds5Q/SDoYXbAoGAK9tVZ8LjWu30hXMU/9FLr0USoTS9JWOszAKH
|
||||||
|
byFuriPmq1lvD2PP2kK+yx2q3JD1fmQokIOR9Uvi6IJD1mTJwKyEcN3reppailKz
|
||||||
|
Z2q/X15hOsJcLR0DgpoHuKxwa1B1m8Ehu2etHxGJRtC9MTFiu5T3cIrenXskBhBP
|
||||||
|
NMSoNWcCgYAD3u3zdeVo3gVoxneS7GNVI2WBhjtqgNIbINuxGZvfztm7+vNPE6sQ
|
||||||
|
VL8i+09uoM1H6sXbe2XXORmtW0j/6MmYhSoBXNdqWTNAiyNRhwEQtowqgl5R7PBu
|
||||||
|
//QZTF1z62R9IKDMRG3f5Wn8e1Dys6tXBuG603g+Dkkc/km476mrgw==
|
||||||
|
-----END RSA PRIVATE KEY-----";
|
||||||
|
|
||||||
|
// Generate with
|
||||||
|
// openssl ecparam -genkey -name prime256v1 | openssl pkcs8 -topk8 -nocrypt
|
||||||
|
const TEST_ECDSA_PKCS8_PEM: &str = "-----BEGIN PRIVATE KEY-----
|
||||||
|
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg+tHxet7G+uar2Cef
|
||||||
|
iYPb7jv3uzncFtwJ7RhDOvEA0fChRANCAATCKn2AEqa9785k+TmwkeCvLub8XGrF
|
||||||
|
ezE6bA/blaPVE3nu4SUVYKULRJQxNjeOSra8TQrlIS8e5ItbMn8Tv9KV
|
||||||
|
-----END PRIVATE KEY-----";
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct StaticKeystore {
|
pub struct StaticKeystore {
|
||||||
rsa_keys: HashMap<String, rsa::RsaPrivateKey>,
|
rsa_keys: HashMap<String, rsa::RsaPrivateKey>,
|
||||||
es256_keys: HashMap<String, ecdsa::SigningKey<NistP256>>,
|
es256_keys: HashMap<String, SigningKey<NistP256>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StaticKeystore {
|
impl StaticKeystore {
|
||||||
@ -41,6 +79,18 @@ impl StaticKeystore {
|
|||||||
StaticKeystore::default()
|
StaticKeystore::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_test_rsa_key(&mut self) -> anyhow::Result<()> {
|
||||||
|
let rsa = RsaPrivateKey::from_pkcs1_pem(TEST_RSA_PKCS1_PEM)?;
|
||||||
|
self.add_rsa_key(rsa)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_test_ecdsa_key(&mut self) -> anyhow::Result<()> {
|
||||||
|
let ecdsa = SigningKey::from_pkcs8_pem(TEST_ECDSA_PKCS8_PEM)?;
|
||||||
|
self.add_ecdsa_key(ecdsa)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_rsa_key(&mut self, key: rsa::RsaPrivateKey) -> anyhow::Result<()> {
|
pub fn add_rsa_key(&mut self, key: rsa::RsaPrivateKey) -> anyhow::Result<()> {
|
||||||
let pubkey: &RsaPublicKey = &key;
|
let pubkey: &RsaPublicKey = &key;
|
||||||
let der = pubkey.to_pkcs1_der()?;
|
let der = pubkey.to_pkcs1_der()?;
|
||||||
@ -57,7 +107,7 @@ impl StaticKeystore {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_ecdsa_key(&mut self, key: ecdsa::SigningKey<NistP256>) -> anyhow::Result<()> {
|
pub fn add_ecdsa_key(&mut self, key: SigningKey<NistP256>) -> anyhow::Result<()> {
|
||||||
let pubkey: PublicKey = key.verifying_key().into();
|
let pubkey: PublicKey = key.verifying_key().into();
|
||||||
let der = EncodePublicKey::to_public_key_der(&pubkey)?;
|
let der = EncodePublicKey::to_public_key_der(&pubkey)?;
|
||||||
let digest = {
|
let digest = {
|
||||||
@ -297,63 +347,15 @@ impl ExportJwks for StaticKeystore {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ecdsa::SigningKey;
|
|
||||||
use pkcs1::DecodeRsaPrivateKey;
|
|
||||||
use pkcs8::DecodePrivateKey;
|
|
||||||
use rsa::RsaPrivateKey;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// Generate with
|
|
||||||
// openssl genrsa 2048
|
|
||||||
const RSA_PKCS1_PEM: &str = "-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEpAIBAAKCAQEA1j7Y2CH6Ss8tgaNvcQPaRJKnCZD8ABqNPyKDWLQLph6Zi7gZ
|
|
||||||
GqmRtTzMuevo2ezpkbCiQAPEp1ms022P92bB+uqG7xmzHTzbwLtnq3OAdjmrnaFV
|
|
||||||
I4v89WHUsTXX9hiYOK5dOM81bNZ6muxWZ0L/xw4jVWe7xkqnp2Lluq0HknlzP5yJ
|
|
||||||
UEikf5BkpX0iyIu2/X4r8YVp8uzG34l/8qBx6k3rO2VkOQOSybZj1oij5KZCusnu
|
|
||||||
QjJLKWXCqJToWE6iVn+Q0N6ySDLgmJ7Zq0Sou/9N/oWKn94FOsouQgET5NuzoIFR
|
|
||||||
qTb321fQ8gbqt/OupBbBKEo1qUU+cS77TD/AuQIDAQABAoIBAQDLSZzmD+93lnf+
|
|
||||||
f36ZxOcRk/nNGPYUfx0xH+VzgHthJ73YFlozs1xflQ5JB/DM/4BsziZWCX1KsctM
|
|
||||||
XrRxMt6y4GAidcc/4eQ+T1RCGfl1tKkDi/bGIOloSGjRsV5208V0WvZ3lh2CZUy2
|
|
||||||
vbQKjUc3sFGUkzZYI7RLHosPA2mg78IVuSnqvNaU0TgA2KkaxWs6Ecr/ys80cUvj
|
|
||||||
KKj04DmX5xaXwUKmz353i5gIt3aY3G5CAw5fU/ocDKR8nzVCpBAGbRRiUaVKIT06
|
|
||||||
APSkLDTUnxSYtHtDJGHjgU/TsvAwTA92J3ue5Ysu9xTE+WyHA6Rgux7RQSD/wWHr
|
|
||||||
LdRPwxPFAoGBAOytMPh/f2zKmotanjho0QNfhAUHoQUfPudYT0nnDceOsi1jYWbQ
|
|
||||||
c/wPeQQC4Hp/pTUrkSIQPEz/hSxzZ6RPxxuGB8O94I0uLwQK4V1UwbgfsRa9zQzW
|
|
||||||
n0kgKZ8w8h8B7qyiKyIAnZzvKtNEnKrzrct4HsN3OEoXTwuAUYlvWtQTAoGBAOe8
|
|
||||||
0liNaH9V6ecZiojkRR1tiQkr/dCV+a13eXXaRA/8y/3wKCQ4idYncclQJTLKsAwW
|
|
||||||
hHuDd4uLgtifREVIBD2jGdlznNr9HQNuZgwjuUoH+r1YLGgiMWeVYSr0m8lyDlQl
|
|
||||||
BJKTAphrqo6VJWDAnM18v+by//yRleSjVMqZ3zmDAoGBAMpA0rl5EyagGON/g/hG
|
|
||||||
sl8Ej+hQdazP38yJbfCEsATaD6+z3rei6Yr8mfjwkG5+iGrgmT0XzMAsF909ndMP
|
|
||||||
jeIabqY6rBtZ3TnCJobAeG9lPctmVUVkX2h5QLhWdoJC/3iteNis2AQVam5yksOQ
|
|
||||||
S/O16ew2BHdkZds5Q/SDoYXbAoGAK9tVZ8LjWu30hXMU/9FLr0USoTS9JWOszAKH
|
|
||||||
byFuriPmq1lvD2PP2kK+yx2q3JD1fmQokIOR9Uvi6IJD1mTJwKyEcN3reppailKz
|
|
||||||
Z2q/X15hOsJcLR0DgpoHuKxwa1B1m8Ehu2etHxGJRtC9MTFiu5T3cIrenXskBhBP
|
|
||||||
NMSoNWcCgYAD3u3zdeVo3gVoxneS7GNVI2WBhjtqgNIbINuxGZvfztm7+vNPE6sQ
|
|
||||||
VL8i+09uoM1H6sXbe2XXORmtW0j/6MmYhSoBXNdqWTNAiyNRhwEQtowqgl5R7PBu
|
|
||||||
//QZTF1z62R9IKDMRG3f5Wn8e1Dys6tXBuG603g+Dkkc/km476mrgw==
|
|
||||||
-----END RSA PRIVATE KEY-----";
|
|
||||||
|
|
||||||
// Generate with
|
|
||||||
// openssl ecparam -genkey -name prime256v1 | openssl pkcs8 -topk8 -nocrypt
|
|
||||||
const EC_PKCS8_PEM: &str = "-----BEGIN PRIVATE KEY-----
|
|
||||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg+tHxet7G+uar2Cef
|
|
||||||
iYPb7jv3uzncFtwJ7RhDOvEA0fChRANCAATCKn2AEqa9785k+TmwkeCvLub8XGrF
|
|
||||||
ezE6bA/blaPVE3nu4SUVYKULRJQxNjeOSra8TQrlIS8e5ItbMn8Tv9KV
|
|
||||||
-----END PRIVATE KEY-----";
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_static_store() {
|
async fn test_static_store() {
|
||||||
let message = "this is the message to sign".as_bytes();
|
let message = "this is the message to sign".as_bytes();
|
||||||
let store = {
|
let store = {
|
||||||
let mut s = StaticKeystore::new();
|
let mut s = StaticKeystore::new();
|
||||||
|
s.add_test_rsa_key().unwrap();
|
||||||
let rsa = RsaPrivateKey::from_pkcs1_pem(RSA_PKCS1_PEM).unwrap();
|
s.add_test_ecdsa_key().unwrap();
|
||||||
s.add_rsa_key(rsa).unwrap();
|
|
||||||
|
|
||||||
let ecdsa = SigningKey::from_pkcs8_pem(EC_PKCS8_PEM).unwrap();
|
|
||||||
s.add_ecdsa_key(ecdsa).unwrap();
|
|
||||||
|
|
||||||
s
|
s
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ struct ClientAuthForm<T> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use headers::authorization::Credentials;
|
use headers::authorization::Credentials;
|
||||||
use mas_config::{ConfigurationSection, OAuth2ClientAuthMethodConfig};
|
use mas_config::{ConfigurationSection, OAuth2ClientAuthMethodConfig};
|
||||||
use mas_jose::{JsonWebSignatureAlgorithm, SigningKeystore};
|
use mas_jose::{ExportJwks, JsonWebSignatureAlgorithm, SigningKeystore, StaticKeystore};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -292,7 +292,14 @@ mod tests {
|
|||||||
// Long client_secret to support it as a HS512 key
|
// Long client_secret to support it as a HS512 key
|
||||||
const CLIENT_SECRET: &str = "leek2zaeyeb8thai7piehea3vah6ool9oanin9aeraThuci9EeghaekaiD1upe4Quoh7xeMae2meitohj0Waaveiwaorah1yazohr6Vae7iebeiRaWene5IeWeeciezu";
|
const CLIENT_SECRET: &str = "leek2zaeyeb8thai7piehea3vah6ool9oanin9aeraThuci9EeghaekaiD1upe4Quoh7xeMae2meitohj0Waaveiwaorah1yazohr6Vae7iebeiRaWene5IeWeeciezu";
|
||||||
|
|
||||||
fn oauth2_config() -> OAuth2Config {
|
fn client_private_keystore() -> StaticKeystore {
|
||||||
|
let mut store = StaticKeystore::new();
|
||||||
|
store.add_test_rsa_key().unwrap();
|
||||||
|
store.add_test_ecdsa_key().unwrap();
|
||||||
|
store
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn oauth2_config() -> OAuth2Config {
|
||||||
let mut config = OAuth2Config::test();
|
let mut config = OAuth2Config::test();
|
||||||
config.clients.push(OAuth2ClientConfig {
|
config.clients.push(OAuth2ClientConfig {
|
||||||
client_id: "public".to_string(),
|
client_id: "public".to_string(),
|
||||||
@ -327,6 +334,19 @@ mod tests {
|
|||||||
},
|
},
|
||||||
redirect_uris: Vec::new(),
|
redirect_uris: Vec::new(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let store = client_private_keystore();
|
||||||
|
let jwks = store.export_jwks().await.unwrap();
|
||||||
|
config.clients.push(OAuth2ClientConfig {
|
||||||
|
client_id: "private-key-jwt".to_string(),
|
||||||
|
client_auth_method: OAuth2ClientAuthMethodConfig::PrivateKeyJwt(jwks.clone().into()),
|
||||||
|
redirect_uris: Vec::new(),
|
||||||
|
});
|
||||||
|
config.clients.push(OAuth2ClientConfig {
|
||||||
|
client_id: "private-key-jwt-2".to_string(),
|
||||||
|
client_auth_method: OAuth2ClientAuthMethodConfig::PrivateKeyJwt(jwks.into()),
|
||||||
|
redirect_uris: Vec::new(),
|
||||||
|
});
|
||||||
config
|
config
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,7 +373,7 @@ mod tests {
|
|||||||
|
|
||||||
async fn client_secret_jwt(alg: JsonWebSignatureAlgorithm) {
|
async fn client_secret_jwt(alg: JsonWebSignatureAlgorithm) {
|
||||||
let audience = "https://example.com/token".to_string();
|
let audience = "https://example.com/token".to_string();
|
||||||
let filter = client_authentication::<Form>(&oauth2_config(), audience.clone());
|
let filter = client_authentication::<Form>(&oauth2_config().await, audience.clone());
|
||||||
|
|
||||||
let store = SharedSecret::new(&CLIENT_SECRET);
|
let store = SharedSecret::new(&CLIENT_SECRET);
|
||||||
let claims = ClientAssertionClaims {
|
let claims = ClientAssertionClaims {
|
||||||
@ -422,10 +442,101 @@ mod tests {
|
|||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn client_secret_jwt_rs256() {
|
||||||
|
private_key_jwt(JsonWebSignatureAlgorithm::Rs256).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn client_secret_jwt_rs384() {
|
||||||
|
private_key_jwt(JsonWebSignatureAlgorithm::Rs384).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn client_secret_jwt_rs512() {
|
||||||
|
private_key_jwt(JsonWebSignatureAlgorithm::Rs512).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn client_secret_jwt_es256() {
|
||||||
|
private_key_jwt(JsonWebSignatureAlgorithm::Es256).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn private_key_jwt(alg: JsonWebSignatureAlgorithm) {
|
||||||
|
let audience = "https://example.com/token".to_string();
|
||||||
|
let filter = client_authentication::<Form>(&oauth2_config().await, audience.clone());
|
||||||
|
|
||||||
|
let store = client_private_keystore();
|
||||||
|
let claims = ClientAssertionClaims {
|
||||||
|
issuer: "private-key-jwt".to_string(),
|
||||||
|
subject: "private-key-jwt".to_string(),
|
||||||
|
audience,
|
||||||
|
jwt_id: None,
|
||||||
|
};
|
||||||
|
let header = store.prepare_header(alg).await.expect("JWT header");
|
||||||
|
let jwt = DecodedJsonWebToken::new(header, claims);
|
||||||
|
let jwt = jwt.sign(&store).await.expect("signed token");
|
||||||
|
let jwt = jwt.serialize();
|
||||||
|
|
||||||
|
// TODO: test failing cases
|
||||||
|
// - expired token
|
||||||
|
// - "not before" in the future
|
||||||
|
// - subject/issuer mismatch
|
||||||
|
// - audience mismatch
|
||||||
|
// - wrong secret/signature
|
||||||
|
|
||||||
|
let (auth, client, body) = warp::test::request()
|
||||||
|
.method("POST")
|
||||||
|
.header("Content-Type", mime::APPLICATION_WWW_FORM_URLENCODED.to_string())
|
||||||
|
.body(serde_urlencoded::to_string(json!({
|
||||||
|
"client_id": "private-key-jwt",
|
||||||
|
"client_assertion": jwt,
|
||||||
|
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
||||||
|
"foo": "baz",
|
||||||
|
"bar": "foobar",
|
||||||
|
})).unwrap())
|
||||||
|
.filter(&filter)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(auth, ClientAuthenticationMethod::PrivateKeyJwt);
|
||||||
|
assert_eq!(client.client_id, "private-key-jwt");
|
||||||
|
assert_eq!(body.foo, "baz");
|
||||||
|
assert_eq!(body.bar, "foobar");
|
||||||
|
|
||||||
|
// Without client_id
|
||||||
|
let res = warp::test::request()
|
||||||
|
.method("POST")
|
||||||
|
.header("Content-Type", mime::APPLICATION_WWW_FORM_URLENCODED.to_string())
|
||||||
|
.body(serde_urlencoded::to_string(json!({
|
||||||
|
"client_assertion": jwt,
|
||||||
|
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
||||||
|
"foo": "baz",
|
||||||
|
"bar": "foobar",
|
||||||
|
})).unwrap())
|
||||||
|
.filter(&filter)
|
||||||
|
.await;
|
||||||
|
assert!(res.is_ok());
|
||||||
|
|
||||||
|
// client_id mismatch
|
||||||
|
let res = warp::test::request()
|
||||||
|
.method("POST")
|
||||||
|
.body(serde_urlencoded::to_string(json!({
|
||||||
|
"client_id": "private-key-jwt-2",
|
||||||
|
"client_assertion": jwt,
|
||||||
|
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
||||||
|
"foo": "baz",
|
||||||
|
"bar": "foobar",
|
||||||
|
})).unwrap())
|
||||||
|
.filter(&filter)
|
||||||
|
.await;
|
||||||
|
assert!(res.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn client_secret_post() {
|
async fn client_secret_post() {
|
||||||
let filter = client_authentication::<Form>(
|
let filter = client_authentication::<Form>(
|
||||||
&oauth2_config(),
|
&oauth2_config().await,
|
||||||
"https://example.com/token".to_string(),
|
"https://example.com/token".to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -457,7 +568,7 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn client_secret_basic() {
|
async fn client_secret_basic() {
|
||||||
let filter = client_authentication::<Form>(
|
let filter = client_authentication::<Form>(
|
||||||
&oauth2_config(),
|
&oauth2_config().await,
|
||||||
"https://example.com/token".to_string(),
|
"https://example.com/token".to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -489,7 +600,7 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn none() {
|
async fn none() {
|
||||||
let filter = client_authentication::<Form>(
|
let filter = client_authentication::<Form>(
|
||||||
&oauth2_config(),
|
&oauth2_config().await,
|
||||||
"https://example.com/token".to_string(),
|
"https://example.com/token".to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user