1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

Use new generated enums & query supported signing algs from the keystore

This commit is contained in:
Quentin Gliech
2022-01-11 18:46:26 +01:00
parent 0e70af0a75
commit 9003eaf0c2
11 changed files with 77 additions and 60 deletions

3
Cargo.lock generated
View File

@ -1571,6 +1571,7 @@ dependencies = [
"indoc",
"mas-config",
"mas-data-model",
"mas-iana",
"mas-jose",
"mas-static-files",
"mas-storage",
@ -1631,6 +1632,7 @@ dependencies = [
"ecdsa",
"elliptic-curve",
"hmac 0.12.0",
"mas-iana",
"p256",
"pkcs1",
"pkcs8",
@ -1954,6 +1956,7 @@ dependencies = [
"indoc",
"itertools",
"language-tags",
"mas-iana",
"parse-display",
"serde",
"serde_json",

View File

@ -59,6 +59,7 @@ mas-static-files = { path = "../static-files" }
mas-storage = { path = "../storage" }
mas-warp-utils = { path = "../warp-utils" }
mas-jose = { path = "../jose" }
mas-iana = { path = "../iana" }
[dev-dependencies]
indoc = "1.0.3"

View File

@ -15,15 +15,19 @@
use std::collections::HashSet;
use mas_config::OAuth2Config;
use mas_jose::{JsonWebSignatureAlgorithm, SigningKeystore};
use oauth2_types::{
oidc::{ClaimType, Metadata, SigningAlgorithm, SubjectType},
oidc::{ClaimType, Metadata, SubjectType},
pkce::CodeChallengeMethod,
requests::{ClientAuthenticationMethod, Display, GrantType, ResponseMode},
};
use warp::{filters::BoxedFilter, Filter, Reply};
#[allow(clippy::too_many_lines)]
pub(super) fn filter(config: &OAuth2Config) -> BoxedFilter<(Box<dyn Reply>,)> {
pub(super) fn filter(
key_store: impl SigningKeystore,
config: &OAuth2Config,
) -> BoxedFilter<(Box<dyn Reply>,)> {
let base = config.issuer.clone();
// This is how clients can authenticate
@ -39,25 +43,17 @@ pub(super) fn filter(config: &OAuth2Config) -> BoxedFilter<(Box<dyn Reply>,)> {
let client_auth_signing_alg_values_supported = Some({
let mut s = HashSet::new();
s.insert(SigningAlgorithm::Hs256);
s.insert(SigningAlgorithm::Hs384);
s.insert(SigningAlgorithm::Hs512);
s.insert(SigningAlgorithm::Rs256);
s.insert(SigningAlgorithm::Rs384);
s.insert(SigningAlgorithm::Rs512);
s.insert(JsonWebSignatureAlgorithm::Hs256);
s.insert(JsonWebSignatureAlgorithm::Hs384);
s.insert(JsonWebSignatureAlgorithm::Hs512);
s.insert(JsonWebSignatureAlgorithm::Rs256);
s.insert(JsonWebSignatureAlgorithm::Rs384);
s.insert(JsonWebSignatureAlgorithm::Rs512);
s
});
// This is how we can sign stuff
// TODO: query the signing store
let jwt_signing_alg_values_supported = Some({
let mut s = HashSet::new();
s.insert(SigningAlgorithm::Rs256);
s.insert(SigningAlgorithm::Rs384);
s.insert(SigningAlgorithm::Rs512);
s.insert(SigningAlgorithm::Es256);
s
});
let jwt_signing_alg_values_supported = Some(key_store.supported_algorithms());
// Prepare all the endpoints
let issuer = Some(base.clone());

View File

@ -43,7 +43,7 @@ pub fn filter(
oauth2_config: &OAuth2Config,
cookies_config: &CookiesConfig,
) -> BoxedFilter<(impl Reply,)> {
let discovery = discovery(oauth2_config);
let discovery = discovery(key_store.as_ref(), oauth2_config);
let keys = keys(key_store);
let authorization = authorization(pool, templates, oauth2_config, cookies_config);
let userinfo = userinfo(pool, oauth2_config);

View File

@ -31,3 +31,5 @@ thiserror = "1.0.30"
tokio = { version = "1.15.0", features = ["macros", "rt", "sync"] }
url = { version = "2.2.2", features = ["serde"] }
zeroize = "1.4.3"
mas-iana = { path = "../iana" }

View File

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::collections::HashSet;
use anyhow::bail;
use async_trait::async_trait;
use hmac::{Hmac, Mac};
@ -34,6 +36,16 @@ impl<'a> SharedSecret<'a> {
#[async_trait]
impl<'a> SigningKeystore for &SharedSecret<'a> {
fn supported_algorithms(self) -> HashSet<JsonWebSignatureAlgorithm> {
let mut algorithms = HashSet::with_capacity(3);
algorithms.insert(JsonWebSignatureAlgorithm::Hs256);
algorithms.insert(JsonWebSignatureAlgorithm::Hs384);
algorithms.insert(JsonWebSignatureAlgorithm::Hs512);
algorithms
}
async fn prepare_header(self, alg: JsonWebSignatureAlgorithm) -> anyhow::Result<JwtHeader> {
if !matches!(
alg,

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use anyhow::bail;
use async_trait::async_trait;
@ -126,6 +126,26 @@ impl StaticKeystore {
#[async_trait]
impl SigningKeystore for &StaticKeystore {
fn supported_algorithms(self) -> HashSet<JsonWebSignatureAlgorithm> {
let has_rsa = !self.rsa_keys.is_empty();
let has_es256 = !self.es256_keys.is_empty();
let capacity = (if has_rsa { 3 } else { 0 }) + (if has_es256 { 1 } else { 0 });
let mut algorithms = HashSet::with_capacity(capacity);
if has_rsa {
algorithms.insert(JsonWebSignatureAlgorithm::Rs256);
algorithms.insert(JsonWebSignatureAlgorithm::Rs384);
algorithms.insert(JsonWebSignatureAlgorithm::Rs512);
}
if has_es256 {
algorithms.insert(JsonWebSignatureAlgorithm::Es256);
}
algorithms
}
async fn prepare_header(self, alg: JsonWebSignatureAlgorithm) -> anyhow::Result<JwtHeader> {
let header = JwtHeader::new(alg);

View File

@ -12,12 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::collections::HashSet;
use async_trait::async_trait;
use crate::{iana::JsonWebSignatureAlgorithm, JsonWebKeySet, JwtHeader};
#[async_trait]
pub trait SigningKeystore {
fn supported_algorithms(self) -> HashSet<JsonWebSignatureAlgorithm>;
async fn prepare_header(self, alg: JsonWebSignatureAlgorithm) -> anyhow::Result<JwtHeader>;
async fn sign(self, header: &JwtHeader, msg: &[u8]) -> anyhow::Result<Vec<u8>>;

View File

@ -19,8 +19,9 @@
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::module_name_repetitions)]
pub(crate) use mas_iana::jose as iana;
pub mod claims;
pub(crate) mod iana;
pub(crate) mod jwk;
pub(crate) mod jwt;
mod keystore;

View File

@ -19,3 +19,5 @@ sha2 = "0.10.0"
data-encoding = "2.3.2"
thiserror = "1.0.30"
itertools = "0.10.3"
mas-iana = { path = "../iana" }

View File

@ -14,6 +14,7 @@
use std::collections::HashSet;
use mas_iana::jose::{JsonWebEncryptionAlgorithm, JsonWebSignatureAlgorithm};
use serde::Serialize;
use serde_with::skip_serializing_none;
use url::Url;
@ -38,28 +39,6 @@ pub enum ClaimType {
Distributed,
}
#[derive(Serialize, Clone, Copy, PartialEq, Eq, Hash)]
#[serde(rename_all = "UPPERCASE")]
pub enum SigningAlgorithm {
#[serde(rename = "none")]
None,
Hs256,
Hs384,
Hs512,
Ps256,
Ps384,
Ps512,
Rs256,
Rs384,
Rs512,
Es256,
Es256K,
Es384,
Es512,
#[serde(rename = "EcDSA")]
EcDsa,
}
/// Authorization server metadata, as described by the
/// [IANA registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#authorization-server-metadata)
#[skip_serializing_none]
@ -104,7 +83,8 @@ pub struct Metadata {
/// JSON array containing a list of the JWS signing algorithms supported by
/// the token endpoint for the signature on the JWT used to authenticate the
/// client at the token endpoint.
pub token_endpoint_auth_signing_alg_values_supported: Option<HashSet<SigningAlgorithm>>,
pub token_endpoint_auth_signing_alg_values_supported:
Option<HashSet<JsonWebSignatureAlgorithm>>,
/// URL of a page containing human-readable information that developers
/// might want or need to know when using the authorization server.
@ -135,7 +115,8 @@ pub struct Metadata {
/// JSON array containing a list of the JWS signing algorithms supported by
/// the revocation endpoint for the signature on the JWT used to
/// authenticate the client at the revocation endpoint.
pub revocation_endpoint_auth_signing_alg_values_supported: Option<HashSet<SigningAlgorithm>>,
pub revocation_endpoint_auth_signing_alg_values_supported:
Option<HashSet<JsonWebSignatureAlgorithm>>,
/// URL of the authorization server's OAuth 2.0 introspection endpoint.
pub introspection_endpoint: Option<Url>,
@ -147,7 +128,8 @@ pub struct Metadata {
/// JSON array containing a list of the JWS signing algorithms supported by
/// the introspection endpoint for the signature on the JWT used to
/// authenticate the client at the introspection endpoint.
pub introspection_endpoint_auth_signing_alg_values_supported: Option<HashSet<SigningAlgorithm>>,
pub introspection_endpoint_auth_signing_alg_values_supported:
Option<HashSet<JsonWebSignatureAlgorithm>>,
/// PKCE code challenge methods supported by this authorization server.
pub code_challenge_methods_supported: Option<HashSet<CodeChallengeMethod>>,
@ -165,45 +147,39 @@ pub struct Metadata {
/// JSON array containing a list of the JWS "alg" values supported by the OP
/// for the ID Token.
pub id_token_signing_alg_values_supported: Option<HashSet<SigningAlgorithm>>,
pub id_token_signing_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>,
// TODO: type
/// JSON array containing a list of the JWE "alg" values supported by the OP
/// for the ID Token.
pub id_token_encryption_alg_values_supported: Option<HashSet<SigningAlgorithm>>,
pub id_token_encryption_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>,
// TODO: type
/// JSON array containing a list of the JWE "enc" values supported by the OP
/// for the ID Token.
pub id_token_encryption_enc_values_supported: Option<HashSet<SigningAlgorithm>>,
pub id_token_encryption_enc_values_supported: Option<HashSet<JsonWebEncryptionAlgorithm>>,
/// JSON array containing a list of the JWS "alg" values supported by the
/// UserInfo Endpoint.
pub userinfo_signing_alg_values_supported: Option<HashSet<SigningAlgorithm>>,
pub userinfo_signing_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>,
// TODO: type
/// JSON array containing a list of the JWE "alg" values supported by the
/// UserInfo Endpoint.
pub userinfo_encryption_alg_values_supported: Option<HashSet<SigningAlgorithm>>,
pub userinfo_encryption_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>,
// TODO: type
/// JSON array containing a list of the JWE "enc" values supported by the
/// UserInfo Endpoint.
pub userinfo_encryption_enc_values_supported: Option<HashSet<SigningAlgorithm>>,
pub userinfo_encryption_enc_values_supported: Option<HashSet<JsonWebEncryptionAlgorithm>>,
/// JSON array containing a list of the JWS "alg" values supported by the OP
/// for Request Objects.
pub request_object_signing_alg_values_supported: Option<HashSet<SigningAlgorithm>>,
pub request_object_signing_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>,
// TODO: type
/// JSON array containing a list of the JWE "alg" values supported by the OP
/// for Request Objects.
pub request_object_encryption_alg_values_supported: Option<HashSet<SigningAlgorithm>>,
pub request_object_encryption_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>,
// TODO: type
/// JSON array containing a list of the JWE "enc" values supported by the OP
/// for Request Objects.
pub request_object_encryption_enc_values_supported: Option<HashSet<SigningAlgorithm>>,
pub request_object_encryption_enc_values_supported: Option<HashSet<JsonWebEncryptionAlgorithm>>,
/// JSON array containing a list of the "display" parameter values that the
/// OpenID Provider supports.