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

Additional parameters from upstream OAuth2 providers in the data model

This commit is contained in:
Quentin Gliech
2024-03-01 10:27:37 +01:00
parent 46c565cc89
commit 1821136e3f
14 changed files with 112 additions and 47 deletions

View File

@@ -310,6 +310,8 @@ async fn sync(root: &super::Options, prune: bool, dry_run: bool) -> anyhow::Resu
jwks_uri_override: provider.jwks_uri, jwks_uri_override: provider.jwks_uri,
discovery_mode, discovery_mode,
pkce_mode, pkce_mode,
// TODO: get that from the config
additional_authorization_parameters: Vec::new(),
}, },
) )
.await?; .await?;

View File

@@ -142,6 +142,7 @@ pub struct UpstreamOAuthProvider {
pub token_endpoint_auth_method: OAuthClientAuthenticationMethod, pub token_endpoint_auth_method: OAuthClientAuthenticationMethod,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
pub claims_imports: ClaimsImports, pub claims_imports: ClaimsImports,
pub additional_authorization_parameters: Vec<(String, String)>,
} }
/// Whether to set the email as verified when importing it from the upstream /// Whether to set the email as verified when importing it from the upstream

View File

@@ -505,6 +505,7 @@ mod tests {
token_endpoint_auth_method: OAuthClientAuthenticationMethod::None, token_endpoint_auth_method: OAuthClientAuthenticationMethod::None,
created_at: clock.now(), created_at: clock.now(),
claims_imports: UpstreamOAuthProviderClaimsImports::default(), claims_imports: UpstreamOAuthProviderClaimsImports::default(),
additional_authorization_parameters: Vec::new(),
}; };
// Without any override, it should just use discovery // Without any override, it should just use discovery

View File

@@ -925,6 +925,7 @@ mod tests {
jwks_uri_override: None, jwks_uri_override: None,
discovery_mode: mas_data_model::UpstreamOAuthProviderDiscoveryMode::Oidc, discovery_mode: mas_data_model::UpstreamOAuthProviderDiscoveryMode::Oidc,
pkce_mode: mas_data_model::UpstreamOAuthProviderPkceMode::Auto, pkce_mode: mas_data_model::UpstreamOAuthProviderPkceMode::Auto,
additional_authorization_parameters: Vec::new(),
}, },
) )
.await .await

View File

@@ -363,6 +363,7 @@ mod test {
jwks_uri_override: None, jwks_uri_override: None,
discovery_mode: mas_data_model::UpstreamOAuthProviderDiscoveryMode::Oidc, discovery_mode: mas_data_model::UpstreamOAuthProviderDiscoveryMode::Oidc,
pkce_mode: mas_data_model::UpstreamOAuthProviderPkceMode::Auto, pkce_mode: mas_data_model::UpstreamOAuthProviderPkceMode::Auto,
additional_authorization_parameters: Vec::new(),
}, },
) )
.await .await
@@ -397,6 +398,7 @@ mod test {
jwks_uri_override: None, jwks_uri_override: None,
discovery_mode: mas_data_model::UpstreamOAuthProviderDiscoveryMode::Oidc, discovery_mode: mas_data_model::UpstreamOAuthProviderDiscoveryMode::Oidc,
pkce_mode: mas_data_model::UpstreamOAuthProviderPkceMode::Auto, pkce_mode: mas_data_model::UpstreamOAuthProviderPkceMode::Auto,
additional_authorization_parameters: Vec::new(),
}, },
) )
.await .await

View File

@@ -0,0 +1,38 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO upstream_oauth_providers (\n upstream_oauth_provider_id,\n issuer,\n human_name,\n brand_name,\n scope,\n token_endpoint_auth_method,\n token_endpoint_signing_alg,\n client_id,\n encrypted_client_secret,\n claims_imports,\n authorization_endpoint_override,\n token_endpoint_override,\n jwks_uri_override,\n discovery_mode,\n pkce_mode,\n additional_parameters,\n created_at\n ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9,\n $10, $11, $12, $13, $14, $15, $16, $17)\n ON CONFLICT (upstream_oauth_provider_id) \n DO UPDATE\n SET\n issuer = EXCLUDED.issuer,\n human_name = EXCLUDED.human_name,\n brand_name = EXCLUDED.brand_name,\n scope = EXCLUDED.scope,\n token_endpoint_auth_method = EXCLUDED.token_endpoint_auth_method,\n token_endpoint_signing_alg = EXCLUDED.token_endpoint_signing_alg,\n client_id = EXCLUDED.client_id,\n encrypted_client_secret = EXCLUDED.encrypted_client_secret,\n claims_imports = EXCLUDED.claims_imports,\n authorization_endpoint_override = EXCLUDED.authorization_endpoint_override,\n token_endpoint_override = EXCLUDED.token_endpoint_override,\n jwks_uri_override = EXCLUDED.jwks_uri_override,\n discovery_mode = EXCLUDED.discovery_mode,\n pkce_mode = EXCLUDED.pkce_mode,\n additional_parameters = EXCLUDED.additional_parameters\n RETURNING created_at\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "created_at",
"type_info": "Timestamptz"
}
],
"parameters": {
"Left": [
"Uuid",
"Text",
"Text",
"Text",
"Text",
"Text",
"Text",
"Text",
"Text",
"Jsonb",
"Text",
"Text",
"Text",
"Text",
"Text",
"Jsonb",
"Timestamptz"
]
},
"nullable": [
false
]
},
"hash": "21132afc29be5394a03680dd27d2aff5e2249a973083c0675935dc658f73b1f4"
}

View File

@@ -1,37 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO upstream_oauth_providers (\n upstream_oauth_provider_id,\n issuer,\n human_name,\n brand_name,\n scope,\n token_endpoint_auth_method,\n token_endpoint_signing_alg,\n client_id,\n encrypted_client_secret,\n claims_imports,\n authorization_endpoint_override,\n token_endpoint_override,\n jwks_uri_override,\n discovery_mode,\n pkce_mode,\n created_at\n ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9,\n $10, $11, $12, $13, $14, $15, $16)\n ON CONFLICT (upstream_oauth_provider_id) \n DO UPDATE\n SET\n issuer = EXCLUDED.issuer,\n human_name = EXCLUDED.human_name,\n brand_name = EXCLUDED.brand_name,\n scope = EXCLUDED.scope,\n token_endpoint_auth_method = EXCLUDED.token_endpoint_auth_method,\n token_endpoint_signing_alg = EXCLUDED.token_endpoint_signing_alg,\n client_id = EXCLUDED.client_id,\n encrypted_client_secret = EXCLUDED.encrypted_client_secret,\n claims_imports = EXCLUDED.claims_imports,\n authorization_endpoint_override = EXCLUDED.authorization_endpoint_override,\n token_endpoint_override = EXCLUDED.token_endpoint_override,\n jwks_uri_override = EXCLUDED.jwks_uri_override,\n discovery_mode = EXCLUDED.discovery_mode,\n pkce_mode = EXCLUDED.pkce_mode\n RETURNING created_at\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "created_at",
"type_info": "Timestamptz"
}
],
"parameters": {
"Left": [
"Uuid",
"Text",
"Text",
"Text",
"Text",
"Text",
"Text",
"Text",
"Text",
"Jsonb",
"Text",
"Text",
"Text",
"Text",
"Text",
"Timestamptz"
]
},
"nullable": [
false
]
},
"hash": "4668abf6520ecca2fa71a26b02d206600624bbba57985d4a7fba2763478cd065"
}

View File

@@ -1,6 +1,6 @@
{ {
"db_name": "PostgreSQL", "db_name": "PostgreSQL",
"query": "\n SELECT\n upstream_oauth_provider_id,\n issuer,\n human_name,\n brand_name,\n scope,\n client_id,\n encrypted_client_secret,\n token_endpoint_signing_alg,\n token_endpoint_auth_method,\n created_at,\n claims_imports as \"claims_imports: Json<UpstreamOAuthProviderClaimsImports>\",\n jwks_uri_override,\n authorization_endpoint_override,\n token_endpoint_override,\n discovery_mode,\n pkce_mode\n FROM upstream_oauth_providers\n ", "query": "\n SELECT\n upstream_oauth_provider_id,\n issuer,\n human_name,\n brand_name,\n scope,\n client_id,\n encrypted_client_secret,\n token_endpoint_signing_alg,\n token_endpoint_auth_method,\n created_at,\n claims_imports as \"claims_imports: Json<UpstreamOAuthProviderClaimsImports>\",\n jwks_uri_override,\n authorization_endpoint_override,\n token_endpoint_override,\n discovery_mode,\n pkce_mode,\n additional_parameters as \"additional_parameters: Json<Vec<(String, String)>>\"\n FROM upstream_oauth_providers\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
@@ -82,6 +82,11 @@
"ordinal": 15, "ordinal": 15,
"name": "pkce_mode", "name": "pkce_mode",
"type_info": "Text" "type_info": "Text"
},
{
"ordinal": 16,
"name": "additional_parameters: Json<Vec<(String, String)>>",
"type_info": "Jsonb"
} }
], ],
"parameters": { "parameters": {
@@ -103,8 +108,9 @@
true, true,
true, true,
false, false,
false false,
true
] ]
}, },
"hash": "2098ff49e9f4b847543b3186dbc4a8cdf1d21f788a533477c233455c57a1b755" "hash": "ccf4965aa84c497ac9759cb31f3ecba59fdf18085791f799dfd398bef4f8eb8c"
} }

View File

@@ -1,6 +1,6 @@
{ {
"db_name": "PostgreSQL", "db_name": "PostgreSQL",
"query": "\n SELECT\n upstream_oauth_provider_id,\n issuer,\n human_name,\n brand_name,\n scope,\n client_id,\n encrypted_client_secret,\n token_endpoint_signing_alg,\n token_endpoint_auth_method,\n created_at,\n claims_imports as \"claims_imports: Json<UpstreamOAuthProviderClaimsImports>\",\n jwks_uri_override,\n authorization_endpoint_override,\n token_endpoint_override,\n discovery_mode,\n pkce_mode\n FROM upstream_oauth_providers\n WHERE upstream_oauth_provider_id = $1\n ", "query": "\n SELECT\n upstream_oauth_provider_id,\n issuer,\n human_name,\n brand_name,\n scope,\n client_id,\n encrypted_client_secret,\n token_endpoint_signing_alg,\n token_endpoint_auth_method,\n created_at,\n claims_imports as \"claims_imports: Json<UpstreamOAuthProviderClaimsImports>\",\n jwks_uri_override,\n authorization_endpoint_override,\n token_endpoint_override,\n discovery_mode,\n pkce_mode,\n additional_parameters as \"additional_parameters: Json<Vec<(String, String)>>\"\n FROM upstream_oauth_providers\n WHERE upstream_oauth_provider_id = $1\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
@@ -82,6 +82,11 @@
"ordinal": 15, "ordinal": 15,
"name": "pkce_mode", "name": "pkce_mode",
"type_info": "Text" "type_info": "Text"
},
{
"ordinal": 16,
"name": "additional_parameters: Json<Vec<(String, String)>>",
"type_info": "Jsonb"
} }
], ],
"parameters": { "parameters": {
@@ -105,8 +110,9 @@
true, true,
true, true,
false, false,
false false,
true
] ]
}, },
"hash": "eb5af2b52b65eb9fba94418075dac0ddb04752d374e1905d1d935313090375c9" "hash": "d8d9e49227b7945b4c3bcd842b59a7af6a21f7e9e2d715dc6360c3d691373903"
} }

View File

@@ -0,0 +1,18 @@
-- Copyright 2024 The Matrix.org Foundation C.I.C.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- Adds a column to the upstream_oauth_providers table to store additional parameters to be sent to the OAuth provider.
-- Parameters are stored as [["key", "value"], ["key", "value"], ...] in a JSONB column to keep key ordering.
ALTER TABLE upstream_oauth_providers
ADD COLUMN additional_parameters JSONB;

View File

@@ -110,6 +110,7 @@ pub enum UpstreamOAuthProviders {
ClaimsImports, ClaimsImports,
DiscoveryMode, DiscoveryMode,
PkceMode, PkceMode,
AdditionalParameters,
JwksUriOverride, JwksUriOverride,
TokenEndpointOverride, TokenEndpointOverride,
AuthorizationEndpointOverride, AuthorizationEndpointOverride,

View File

@@ -76,6 +76,7 @@ mod tests {
jwks_uri_override: None, jwks_uri_override: None,
discovery_mode: mas_data_model::UpstreamOAuthProviderDiscoveryMode::Oidc, discovery_mode: mas_data_model::UpstreamOAuthProviderDiscoveryMode::Oidc,
pkce_mode: mas_data_model::UpstreamOAuthProviderPkceMode::Auto, pkce_mode: mas_data_model::UpstreamOAuthProviderPkceMode::Auto,
additional_authorization_parameters: Vec::new(),
}, },
) )
.await .await
@@ -259,6 +260,7 @@ mod tests {
jwks_uri_override: None, jwks_uri_override: None,
discovery_mode: mas_data_model::UpstreamOAuthProviderDiscoveryMode::Oidc, discovery_mode: mas_data_model::UpstreamOAuthProviderDiscoveryMode::Oidc,
pkce_mode: mas_data_model::UpstreamOAuthProviderPkceMode::Auto, pkce_mode: mas_data_model::UpstreamOAuthProviderPkceMode::Auto,
additional_authorization_parameters: Vec::new(),
}, },
) )
.await .await

View File

@@ -67,6 +67,7 @@ struct ProviderLookup {
token_endpoint_override: Option<String>, token_endpoint_override: Option<String>,
discovery_mode: String, discovery_mode: String,
pkce_mode: String, pkce_mode: String,
additional_parameters: Option<Json<Vec<(String, String)>>>,
} }
impl TryFrom<ProviderLookup> for UpstreamOAuthProvider { impl TryFrom<ProviderLookup> for UpstreamOAuthProvider {
@@ -143,6 +144,11 @@ impl TryFrom<ProviderLookup> for UpstreamOAuthProvider {
.source(e) .source(e)
})?; })?;
let additional_authorization_parameters = value
.additional_parameters
.map(|Json(x)| x)
.unwrap_or_default();
Ok(UpstreamOAuthProvider { Ok(UpstreamOAuthProvider {
id, id,
issuer: value.issuer, issuer: value.issuer,
@@ -160,6 +166,7 @@ impl TryFrom<ProviderLookup> for UpstreamOAuthProvider {
jwks_uri_override, jwks_uri_override,
discovery_mode, discovery_mode,
pkce_mode, pkce_mode,
additional_authorization_parameters,
}) })
} }
} }
@@ -197,7 +204,8 @@ impl<'c> UpstreamOAuthProviderRepository for PgUpstreamOAuthProviderRepository<'
authorization_endpoint_override, authorization_endpoint_override,
token_endpoint_override, token_endpoint_override,
discovery_mode, discovery_mode,
pkce_mode pkce_mode,
additional_parameters as "additional_parameters: Json<Vec<(String, String)>>"
FROM upstream_oauth_providers FROM upstream_oauth_providers
WHERE upstream_oauth_provider_id = $1 WHERE upstream_oauth_provider_id = $1
"#, "#,
@@ -305,6 +313,7 @@ impl<'c> UpstreamOAuthProviderRepository for PgUpstreamOAuthProviderRepository<'
jwks_uri_override: params.jwks_uri_override, jwks_uri_override: params.jwks_uri_override,
discovery_mode: params.discovery_mode, discovery_mode: params.discovery_mode,
pkce_mode: params.pkce_mode, pkce_mode: params.pkce_mode,
additional_authorization_parameters: params.additional_authorization_parameters,
}) })
} }
@@ -411,9 +420,10 @@ impl<'c> UpstreamOAuthProviderRepository for PgUpstreamOAuthProviderRepository<'
jwks_uri_override, jwks_uri_override,
discovery_mode, discovery_mode,
pkce_mode, pkce_mode,
additional_parameters,
created_at created_at
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9,
$10, $11, $12, $13, $14, $15, $16) $10, $11, $12, $13, $14, $15, $16, $17)
ON CONFLICT (upstream_oauth_provider_id) ON CONFLICT (upstream_oauth_provider_id)
DO UPDATE DO UPDATE
SET SET
@@ -430,7 +440,8 @@ impl<'c> UpstreamOAuthProviderRepository for PgUpstreamOAuthProviderRepository<'
token_endpoint_override = EXCLUDED.token_endpoint_override, token_endpoint_override = EXCLUDED.token_endpoint_override,
jwks_uri_override = EXCLUDED.jwks_uri_override, jwks_uri_override = EXCLUDED.jwks_uri_override,
discovery_mode = EXCLUDED.discovery_mode, discovery_mode = EXCLUDED.discovery_mode,
pkce_mode = EXCLUDED.pkce_mode pkce_mode = EXCLUDED.pkce_mode,
additional_parameters = EXCLUDED.additional_parameters
RETURNING created_at RETURNING created_at
"#, "#,
Uuid::from(id), Uuid::from(id),
@@ -457,6 +468,7 @@ impl<'c> UpstreamOAuthProviderRepository for PgUpstreamOAuthProviderRepository<'
params.jwks_uri_override.as_ref().map(ToString::to_string), params.jwks_uri_override.as_ref().map(ToString::to_string),
params.discovery_mode.as_str(), params.discovery_mode.as_str(),
params.pkce_mode.as_str(), params.pkce_mode.as_str(),
Json(&params.additional_authorization_parameters) as _,
created_at, created_at,
) )
.traced() .traced()
@@ -480,6 +492,7 @@ impl<'c> UpstreamOAuthProviderRepository for PgUpstreamOAuthProviderRepository<'
jwks_uri_override: params.jwks_uri_override, jwks_uri_override: params.jwks_uri_override,
discovery_mode: params.discovery_mode, discovery_mode: params.discovery_mode,
pkce_mode: params.pkce_mode, pkce_mode: params.pkce_mode,
additional_authorization_parameters: params.additional_authorization_parameters,
}) })
} }
@@ -607,6 +620,13 @@ impl<'c> UpstreamOAuthProviderRepository for PgUpstreamOAuthProviderRepository<'
)), )),
ProviderLookupIden::PkceMode, ProviderLookupIden::PkceMode,
) )
.expr_as(
Expr::col((
UpstreamOAuthProviders::Table,
UpstreamOAuthProviders::AdditionalParameters,
)),
ProviderLookupIden::AdditionalParameters,
)
.from(UpstreamOAuthProviders::Table) .from(UpstreamOAuthProviders::Table)
.generate_pagination( .generate_pagination(
( (
@@ -691,7 +711,8 @@ impl<'c> UpstreamOAuthProviderRepository for PgUpstreamOAuthProviderRepository<'
authorization_endpoint_override, authorization_endpoint_override,
token_endpoint_override, token_endpoint_override,
discovery_mode, discovery_mode,
pkce_mode pkce_mode,
additional_parameters as "additional_parameters: Json<Vec<(String, String)>>"
FROM upstream_oauth_providers FROM upstream_oauth_providers
"#, "#,
) )

View File

@@ -74,6 +74,9 @@ pub struct UpstreamOAuthProviderParams {
/// How should PKCE be used /// How should PKCE be used
pub pkce_mode: UpstreamOAuthProviderPkceMode, pub pkce_mode: UpstreamOAuthProviderPkceMode,
/// Additional parameters to include in the authorization request
pub additional_authorization_parameters: Vec<(String, String)>,
} }
/// Filter parameters for listing upstream OAuth 2.0 providers /// Filter parameters for listing upstream OAuth 2.0 providers