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

Use iana generated types in more places

This commit is contained in:
Quentin Gliech
2022-01-12 12:22:54 +01:00
parent 2844706bb1
commit 5b9c35a079
20 changed files with 222 additions and 211 deletions

View File

@ -16,11 +16,46 @@
#![deny(clippy::all)]
#![warn(clippy::pedantic)]
use mas_iana::oauth::OAuthAuthorizationEndpointResponseType;
pub trait ResponseTypeExt {
fn has_code(&self) -> bool;
fn has_token(&self) -> bool;
fn has_id_token(&self) -> bool;
}
impl ResponseTypeExt for OAuthAuthorizationEndpointResponseType {
fn has_code(&self) -> bool {
matches!(
self,
Self::Code | Self::CodeToken | Self::CodeIdToken | Self::CodeIdTokenToken
)
}
fn has_token(&self) -> bool {
matches!(
self,
Self::Token | Self::CodeToken | Self::IdTokenToken | Self::CodeIdTokenToken
)
}
fn has_id_token(&self) -> bool {
matches!(
self,
Self::IdToken | Self::IdTokenToken | Self::CodeIdToken | Self::CodeIdTokenToken
)
}
}
pub mod errors;
pub mod oidc;
pub mod pkce;
pub mod requests;
pub mod scope;
pub mod prelude {
pub use crate::{pkce::CodeChallengeMethodExt, ResponseTypeExt};
}
#[cfg(test)]
mod test_utils;

View File

@ -14,15 +14,18 @@
use std::collections::HashSet;
use mas_iana::jose::{JsonWebEncryptionAlg, JsonWebEncryptionEnc, JsonWebSignatureAlg};
use mas_iana::{
jose::{JsonWebEncryptionAlg, JsonWebEncryptionEnc, JsonWebSignatureAlg},
oauth::{
OAuthAuthorizationEndpointResponseType, OAuthClientAuthenticationMethod,
PkceCodeChallengeMethod,
},
};
use serde::Serialize;
use serde_with::skip_serializing_none;
use url::Url;
use crate::{
pkce::CodeChallengeMethod,
requests::{ClientAuthenticationMethod, Display, GrantType, ResponseMode},
};
use crate::requests::{Display, GrantType, ResponseMode};
#[derive(Serialize, Clone, Copy, PartialEq, Eq, Hash)]
#[serde(rename_all = "lowercase")]
@ -66,7 +69,7 @@ pub struct Metadata {
/// JSON array containing a list of the OAuth 2.0 "response_type" values
/// that this authorization server supports.
pub response_types_supported: Option<HashSet<String>>,
pub response_types_supported: Option<HashSet<OAuthAuthorizationEndpointResponseType>>,
/// JSON array containing a list of the OAuth 2.0 "response_mode" values
/// that this authorization server supports.
@ -78,7 +81,7 @@ pub struct Metadata {
/// JSON array containing a list of client authentication methods supported
/// by this token endpoint.
pub token_endpoint_auth_methods_supported: Option<HashSet<ClientAuthenticationMethod>>,
pub token_endpoint_auth_methods_supported: Option<HashSet<OAuthClientAuthenticationMethod>>,
/// 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
@ -109,7 +112,8 @@ pub struct Metadata {
/// JSON array containing a list of client authentication methods supported
/// by this revocation endpoint.
pub revocation_endpoint_auth_methods_supported: Option<HashSet<ClientAuthenticationMethod>>,
pub revocation_endpoint_auth_methods_supported:
Option<HashSet<OAuthClientAuthenticationMethod>>,
/// JSON array containing a list of the JWS signing algorithms supported by
/// the revocation endpoint for the signature on the JWT used to
@ -121,7 +125,8 @@ pub struct Metadata {
/// JSON array containing a list of client authentication methods supported
/// by this introspection endpoint.
pub introspection_endpoint_auth_methods_supported: Option<HashSet<ClientAuthenticationMethod>>,
pub introspection_endpoint_auth_methods_supported:
Option<HashSet<OAuthClientAuthenticationMethod>>,
/// JSON array containing a list of the JWS signing algorithms supported by
/// the introspection endpoint for the signature on the JWT used to
@ -130,7 +135,7 @@ pub struct Metadata {
Option<HashSet<JsonWebSignatureAlg>>,
/// PKCE code challenge methods supported by this authorization server.
pub code_challenge_methods_supported: Option<HashSet<CodeChallengeMethod>>,
pub code_challenge_methods_supported: Option<HashSet<PkceCodeChallengeMethod>>,
/// URL of the OP's UserInfo Endpoint.
pub userinfo_endpoint: Option<Url>,

View File

@ -15,40 +15,23 @@
use std::borrow::Cow;
use data_encoding::BASE64URL_NOPAD;
use parse_display::{Display, FromStr};
use mas_iana::oauth::PkceCodeChallengeMethod;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
#[derive(
Debug,
Hash,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
Copy,
Display,
FromStr,
Serialize,
Deserialize,
)]
pub enum CodeChallengeMethod {
#[serde(rename = "plain")]
#[display("plain")]
Plain,
pub trait CodeChallengeMethodExt {
#[must_use]
fn compute_challenge(self, verifier: &str) -> Cow<'_, str>;
#[serde(rename = "S256")]
#[display("S256")]
S256,
#[must_use]
fn verify(self, challenge: &str, verifier: &str) -> bool;
}
impl CodeChallengeMethod {
#[must_use]
pub fn compute_challenge(self, verifier: &str) -> Cow<'_, str> {
impl CodeChallengeMethodExt for PkceCodeChallengeMethod {
fn compute_challenge(self, verifier: &str) -> Cow<'_, str> {
match self {
CodeChallengeMethod::Plain => verifier.into(),
CodeChallengeMethod::S256 => {
Self::Plain => verifier.into(),
Self::S256 => {
let mut hasher = Sha256::new();
hasher.update(verifier.as_bytes());
let hash = hasher.finalize();
@ -58,15 +41,14 @@ impl CodeChallengeMethod {
}
}
#[must_use]
pub fn verify(self, challenge: &str, verifier: &str) -> bool {
fn verify(self, challenge: &str, verifier: &str) -> bool {
self.compute_challenge(verifier) == challenge
}
}
#[derive(Serialize, Deserialize)]
pub struct AuthorizationRequest {
pub code_challenge_method: CodeChallengeMethod,
pub code_challenge_method: PkceCodeChallengeMethod,
pub code_challenge: String,
}

View File

@ -16,6 +16,9 @@ use std::{collections::HashSet, hash::Hash, num::NonZeroU32};
use chrono::{DateTime, Duration, Utc};
use language_tags::LanguageTag;
use mas_iana::oauth::{
OAuthAccessTokenType, OAuthAuthorizationEndpointResponseType, OAuthTokenTypeHint,
};
use parse_display::{Display, FromStr};
use serde::{Deserialize, Serialize};
use serde_with::{
@ -28,29 +31,6 @@ use crate::scope::Scope;
// ref: https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml
#[derive(
Debug,
Hash,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
Copy,
Display,
FromStr,
Serialize,
Deserialize,
)]
#[display(style = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum ResponseType {
Code,
IdToken,
Token,
None,
}
#[derive(
Debug,
Hash,
@ -72,37 +52,6 @@ pub enum ResponseMode {
FormPost,
}
#[derive(
Debug,
Hash,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
Copy,
Display,
FromStr,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum ClientAuthenticationMethod {
None,
ClientSecretPost,
ClientSecretBasic,
ClientSecretJwt,
PrivateKeyJwt,
}
impl ClientAuthenticationMethod {
#[must_use]
/// Check if the authentication method is for public client or not
pub fn public(&self) -> bool {
matches!(self, &Self::None)
}
}
#[derive(
Debug,
Hash,
@ -151,8 +100,7 @@ pub enum Prompt {
#[serde_as]
#[derive(Serialize, Deserialize)]
pub struct AuthorizationRequest {
#[serde_as(as = "StringWithSeparator::<SpaceSeparator, ResponseType>")]
pub response_type: HashSet<ResponseType>,
pub response_type: OAuthAuthorizationEndpointResponseType,
pub client_id: String,
@ -200,25 +148,6 @@ pub struct AuthorizationResponse<R> {
pub response: R,
}
#[derive(
Debug,
Hash,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
Copy,
Display,
FromStr,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum TokenType {
Bearer,
}
#[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct AuthorizationCodeGrant {
@ -285,7 +214,7 @@ pub struct AccessTokenResponse {
// TODO: this should be somewhere else
id_token: Option<String>,
token_type: TokenType,
token_type: OAuthAccessTokenType,
#[serde_as(as = "Option<DurationSeconds<i64>>")]
expires_in: Option<Duration>,
@ -300,7 +229,7 @@ impl AccessTokenResponse {
access_token,
refresh_token: None,
id_token: None,
token_type: TokenType::Bearer,
token_type: OAuthAccessTokenType::Bearer,
expires_in: None,
scope: None,
}
@ -331,20 +260,13 @@ impl AccessTokenResponse {
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum TokenTypeHint {
AccessToken,
RefreshToken,
}
#[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct IntrospectionRequest {
pub token: String,
#[serde(default)]
pub token_type_hint: Option<TokenTypeHint>,
pub token_type_hint: Option<OAuthTokenTypeHint>,
}
#[serde_as]
@ -359,7 +281,7 @@ pub struct IntrospectionResponse {
pub username: Option<String>,
pub token_type: Option<TokenTypeHint>,
pub token_type: Option<OAuthTokenTypeHint>,
#[serde_as(as = "Option<TimestampSeconds>")]
pub exp: Option<DateTime<Utc>>,