You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-11-20 12:02:22 +03:00
Support private_key_jwt client auth
Which includes having a verifying keystore out of JWKS (and soon out of a JWKS URI)
This commit is contained in:
@@ -38,7 +38,7 @@ pub use self::{
|
||||
csrf::CsrfConfig,
|
||||
database::DatabaseConfig,
|
||||
http::HttpConfig,
|
||||
oauth2::{OAuth2ClientConfig, OAuth2Config},
|
||||
oauth2::{OAuth2ClientAuthMethodConfig, OAuth2ClientConfig, OAuth2Config},
|
||||
telemetry::{
|
||||
MetricsConfig, MetricsExporterConfig, Propagator, TelemetryConfig, TracingConfig,
|
||||
TracingExporterConfig,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
use anyhow::Context;
|
||||
use async_trait::async_trait;
|
||||
use mas_jose::StaticKeystore;
|
||||
use mas_jose::{JsonWebKeySet, StaticJwksStore, StaticKeystore};
|
||||
use pkcs8::{DecodePrivateKey, EncodePrivateKey};
|
||||
use rsa::{
|
||||
pkcs1::{DecodeRsaPrivateKey, EncodeRsaPrivateKey},
|
||||
@@ -43,13 +43,41 @@ pub struct KeyConfig {
|
||||
key: String,
|
||||
}
|
||||
|
||||
#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum JwksOrJwksUri {
|
||||
Jwks(JsonWebKeySet),
|
||||
JwksUri(Url),
|
||||
}
|
||||
|
||||
impl JwksOrJwksUri {
|
||||
pub fn key_store(&self) -> StaticJwksStore {
|
||||
let jwks = match self {
|
||||
Self::Jwks(jwks) => jwks.clone(),
|
||||
Self::JwksUri(_) => unimplemented!("jwks_uri are not implemented yet"),
|
||||
};
|
||||
|
||||
StaticJwksStore::new(jwks)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(tag = "client_auth_method", rename_all = "snake_case")]
|
||||
pub enum OAuth2ClientAuthMethodConfig {
|
||||
None,
|
||||
ClientSecretBasic { client_secret: String },
|
||||
ClientSecretPost { client_secret: String },
|
||||
ClientSecretJwt { client_secret: String },
|
||||
PrivateKeyJwt(JwksOrJwksUri),
|
||||
}
|
||||
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct OAuth2ClientConfig {
|
||||
pub client_id: String,
|
||||
|
||||
#[serde(default)]
|
||||
pub client_secret: Option<String>,
|
||||
#[serde(flatten)]
|
||||
pub client_auth_method: OAuth2ClientAuthMethodConfig,
|
||||
|
||||
#[serde(default)]
|
||||
pub redirect_uris: Vec<Url>,
|
||||
@@ -246,25 +274,55 @@ mod tests {
|
||||
-----END PRIVATE KEY-----
|
||||
issuer: https://example.com
|
||||
clients:
|
||||
- client_id: hello
|
||||
- client_id: public
|
||||
client_auth_method: none
|
||||
redirect_uris:
|
||||
- https://exemple.fr/callback
|
||||
- client_id: world
|
||||
|
||||
- client_id: secret-basic
|
||||
client_auth_method: client_secret_basic
|
||||
client_secret: hello
|
||||
|
||||
- client_id: secret-post
|
||||
client_auth_method: client_secret_post
|
||||
client_secret: hello
|
||||
|
||||
- client_id: secret-jwk
|
||||
client_auth_method: client_secret_jwt
|
||||
client_secret: hello
|
||||
|
||||
- client_id: jwks
|
||||
client_auth_method: private_key_jwt
|
||||
jwks:
|
||||
keys:
|
||||
- kid: "03e84aed4ef4431014e8617567864c4efaaaede9"
|
||||
kty: "RSA"
|
||||
alg: "RS256"
|
||||
use: "sig"
|
||||
e: "AQAB"
|
||||
n: "ma2uRyBeSEOatGuDpCiV9oIxlDWix_KypDYuhQfEzqi_BiF4fV266OWfyjcABbam59aJMNvOnKW3u_eZM-PhMCBij5MZ-vcBJ4GfxDJeKSn-GP_dJ09rpDcILh8HaWAnPmMoi4DC0nrfE241wPISvZaaZnGHkOrfN_EnA5DligLgVUbrA5rJhQ1aSEQO_gf1raEOW3DZ_ACU3qhtgO0ZBG3a5h7BPiRs2sXqb2UCmBBgwyvYLDebnpE7AotF6_xBIlR-Cykdap3GHVMXhrIpvU195HF30ZoBU4dMd-AeG6HgRt4Cqy1moGoDgMQfbmQ48Hlunv9_Vi2e2CLvYECcBw"
|
||||
|
||||
- kid: "d01c1abe249269f72ef7ca2613a86c9f05e59567"
|
||||
kty: "RSA"
|
||||
alg: "RS256"
|
||||
use: "sig"
|
||||
e: "AQAB"
|
||||
n: "0hukqytPwrj1RbMYhYoepCi3CN5k7DwYkTe_Cmb7cP9_qv4ok78KdvFXt5AnQxCRwBD7-qTNkkfMWO2RxUMBdQD0ED6tsSb1n5dp0XY8dSWiBDCX8f6Hr-KolOpvMLZKRy01HdAWcM6RoL9ikbjYHUEW1C8IJnw3MzVHkpKFDL354aptdNLaAdTCBvKzU9WpXo10g-5ctzSlWWjQuecLMQ4G1mNdsR1LHhUENEnOvgT8cDkX0fJzLbEbyBYkdMgKggyVPEB1bg6evG4fTKawgnf0IDSPxIU-wdS9wdSP9ZCJJPLi5CEp-6t6rE_sb2dGcnzjCGlembC57VwpkUvyMw"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let config = OAuth2Config::load_from_file("config.yaml")?;
|
||||
|
||||
assert_eq!(config.issuer, "https://example.com".parse().unwrap());
|
||||
assert_eq!(config.clients.len(), 2);
|
||||
assert_eq!(config.clients.len(), 5);
|
||||
|
||||
assert_eq!(config.clients[0].client_id, "hello");
|
||||
assert_eq!(config.clients[0].client_id, "public");
|
||||
assert_eq!(
|
||||
config.clients[0].redirect_uris,
|
||||
vec!["https://exemple.fr/callback".parse().unwrap()]
|
||||
);
|
||||
|
||||
assert_eq!(config.clients[1].client_id, "world");
|
||||
assert_eq!(config.clients[1].client_id, "secret-basic");
|
||||
assert_eq!(config.clients[1].redirect_uris, Vec::new());
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user