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
Make the email verification state more configurable on upstream OAuth 2.0 registration
This also marks the email as primary
This commit is contained in:
@ -26,10 +26,10 @@ use tracing::{info, info_span, warn};
|
|||||||
|
|
||||||
use crate::util::database_connection_from_config;
|
use crate::util::database_connection_from_config;
|
||||||
|
|
||||||
fn map_import_preference(
|
fn map_import_action(
|
||||||
config: &mas_config::UpstreamOAuth2ImportPreference,
|
config: &mas_config::UpstreamOAuth2ImportAction,
|
||||||
) -> mas_data_model::UpstreamOAuthProviderImportPreference {
|
) -> mas_data_model::UpstreamOAuthProviderImportAction {
|
||||||
let action = match &config.action {
|
match config {
|
||||||
mas_config::UpstreamOAuth2ImportAction::Ignore => {
|
mas_config::UpstreamOAuth2ImportAction::Ignore => {
|
||||||
mas_data_model::UpstreamOAuthProviderImportAction::Ignore
|
mas_data_model::UpstreamOAuthProviderImportAction::Ignore
|
||||||
}
|
}
|
||||||
@ -42,9 +42,15 @@ fn map_import_preference(
|
|||||||
mas_config::UpstreamOAuth2ImportAction::Require => {
|
mas_config::UpstreamOAuth2ImportAction::Require => {
|
||||||
mas_data_model::UpstreamOAuthProviderImportAction::Require
|
mas_data_model::UpstreamOAuthProviderImportAction::Require
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mas_data_model::UpstreamOAuthProviderImportPreference { action }
|
fn map_import_preference(
|
||||||
|
config: &mas_config::UpstreamOAuth2ImportPreference,
|
||||||
|
) -> mas_data_model::UpstreamOAuthProviderImportPreference {
|
||||||
|
mas_data_model::UpstreamOAuthProviderImportPreference {
|
||||||
|
action: map_import_action(&config.action),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_claims_imports(
|
fn map_claims_imports(
|
||||||
@ -64,7 +70,25 @@ fn map_claims_imports(
|
|||||||
email: config
|
email: config
|
||||||
.email
|
.email
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(map_import_preference)
|
.map(|c| mas_data_model::UpstreamOAuthProviderImportPreference {
|
||||||
|
action: map_import_action(&c.action),
|
||||||
|
})
|
||||||
|
.unwrap_or_default(),
|
||||||
|
// XXX: this is a bit ugly
|
||||||
|
verify_email: config
|
||||||
|
.email
|
||||||
|
.as_ref()
|
||||||
|
.map(|c| match c.set_email_verification {
|
||||||
|
mas_config::UpstreamOAuth2SetEmailVerification::Always => {
|
||||||
|
mas_data_model::UpsreamOAuthProviderSetEmailVerification::Always
|
||||||
|
}
|
||||||
|
mas_config::UpstreamOAuth2SetEmailVerification::Never => {
|
||||||
|
mas_data_model::UpsreamOAuthProviderSetEmailVerification::Never
|
||||||
|
}
|
||||||
|
mas_config::UpstreamOAuth2SetEmailVerification::Import => {
|
||||||
|
mas_data_model::UpsreamOAuthProviderSetEmailVerification::Import
|
||||||
|
}
|
||||||
|
})
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,8 +49,11 @@ pub use self::{
|
|||||||
},
|
},
|
||||||
templates::TemplatesConfig,
|
templates::TemplatesConfig,
|
||||||
upstream_oauth2::{
|
upstream_oauth2::{
|
||||||
ClaimsImports as UpstreamOAuth2ClaimsImports, ImportAction as UpstreamOAuth2ImportAction,
|
ClaimsImports as UpstreamOAuth2ClaimsImports,
|
||||||
ImportPreference as UpstreamOAuth2ImportPreference, UpstreamOAuth2Config,
|
EmailImportPreference as UpstreamOAuth2EmailImportPreference,
|
||||||
|
ImportAction as UpstreamOAuth2ImportAction,
|
||||||
|
ImportPreference as UpstreamOAuth2ImportPreference,
|
||||||
|
SetEmailVerification as UpstreamOAuth2SetEmailVerification, UpstreamOAuth2Config,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crate::util::ConfigurationSection;
|
use crate::util::ConfigurationSection;
|
||||||
|
@ -104,6 +104,34 @@ pub struct ImportPreference {
|
|||||||
pub action: ImportAction,
|
pub action: ImportAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Should the email address be marked as verified
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum SetEmailVerification {
|
||||||
|
/// Mark the email address as verified
|
||||||
|
Always,
|
||||||
|
|
||||||
|
/// Don't mark the email address as verified
|
||||||
|
Never,
|
||||||
|
|
||||||
|
/// Mark the email address as verified if the upstream provider says it is
|
||||||
|
/// through the `email_verified` claim
|
||||||
|
#[default]
|
||||||
|
Import,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// What should be done with the email claim
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, JsonSchema)]
|
||||||
|
pub struct EmailImportPreference {
|
||||||
|
/// How to handle the claim
|
||||||
|
#[serde(default)]
|
||||||
|
pub action: ImportAction,
|
||||||
|
|
||||||
|
/// Should the email address be marked as verified
|
||||||
|
#[serde(default)]
|
||||||
|
pub set_email_verification: SetEmailVerification,
|
||||||
|
}
|
||||||
|
|
||||||
/// How claims should be imported
|
/// How claims should be imported
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, JsonSchema)]
|
||||||
pub struct ClaimsImports {
|
pub struct ClaimsImports {
|
||||||
@ -118,7 +146,7 @@ pub struct ClaimsImports {
|
|||||||
/// Import the email address of the user based on the `email` and
|
/// Import the email address of the user based on the `email` and
|
||||||
/// `email_verified` claims
|
/// `email_verified` claims
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub email: Option<ImportPreference>,
|
pub email: Option<EmailImportPreference>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
|
@ -46,9 +46,10 @@ pub use self::{
|
|||||||
AccessToken, AccessTokenState, RefreshToken, RefreshTokenState, TokenFormatError, TokenType,
|
AccessToken, AccessTokenState, RefreshToken, RefreshTokenState, TokenFormatError, TokenType,
|
||||||
},
|
},
|
||||||
upstream_oauth2::{
|
upstream_oauth2::{
|
||||||
UpstreamOAuthAuthorizationSession, UpstreamOAuthAuthorizationSessionState,
|
UpsreamOAuthProviderSetEmailVerification, UpstreamOAuthAuthorizationSession,
|
||||||
UpstreamOAuthLink, UpstreamOAuthProvider, UpstreamOAuthProviderClaimsImports,
|
UpstreamOAuthAuthorizationSessionState, UpstreamOAuthLink, UpstreamOAuthProvider,
|
||||||
UpstreamOAuthProviderImportAction, UpstreamOAuthProviderImportPreference,
|
UpstreamOAuthProviderClaimsImports, UpstreamOAuthProviderImportAction,
|
||||||
|
UpstreamOAuthProviderImportPreference,
|
||||||
},
|
},
|
||||||
users::{
|
users::{
|
||||||
Authentication, AuthenticationMethod, BrowserSession, Password, User, UserEmail,
|
Authentication, AuthenticationMethod, BrowserSession, Password, User, UserEmail,
|
||||||
|
@ -21,7 +21,8 @@ pub use self::{
|
|||||||
provider::{
|
provider::{
|
||||||
ClaimsImports as UpstreamOAuthProviderClaimsImports,
|
ClaimsImports as UpstreamOAuthProviderClaimsImports,
|
||||||
ImportAction as UpstreamOAuthProviderImportAction,
|
ImportAction as UpstreamOAuthProviderImportAction,
|
||||||
ImportPreference as UpstreamOAuthProviderImportPreference, UpstreamOAuthProvider,
|
ImportPreference as UpstreamOAuthProviderImportPreference,
|
||||||
|
SetEmailVerification as UpsreamOAuthProviderSetEmailVerification, UpstreamOAuthProvider,
|
||||||
},
|
},
|
||||||
session::{UpstreamOAuthAuthorizationSession, UpstreamOAuthAuthorizationSessionState},
|
session::{UpstreamOAuthAuthorizationSession, UpstreamOAuthAuthorizationSessionState},
|
||||||
};
|
};
|
||||||
|
@ -31,6 +31,32 @@ pub struct UpstreamOAuthProvider {
|
|||||||
pub claims_imports: ClaimsImports,
|
pub claims_imports: ClaimsImports,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether to set the email as verified when importing it from the upstream
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum SetEmailVerification {
|
||||||
|
/// Set the email as verified
|
||||||
|
Always,
|
||||||
|
|
||||||
|
/// Never set the email as verified
|
||||||
|
Never,
|
||||||
|
|
||||||
|
/// Set the email as verified if the upstream provider claims it is verified
|
||||||
|
#[default]
|
||||||
|
Import,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetEmailVerification {
|
||||||
|
#[must_use]
|
||||||
|
pub fn should_mark_as_verified(&self, upstream_verified: bool) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Always => true,
|
||||||
|
Self::Never => false,
|
||||||
|
Self::Import => upstream_verified,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||||
pub struct ClaimsImports {
|
pub struct ClaimsImports {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -41,6 +67,9 @@ pub struct ClaimsImports {
|
|||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub email: ImportPreference,
|
pub email: ImportPreference,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub verify_email: SetEmailVerification,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||||
|
@ -527,11 +527,19 @@ pub(crate) async fn post(
|
|||||||
.add(&mut rng, &clock, &user, email)
|
.add(&mut rng, &clock, &user, email)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Mark the email as verified if the upstream provider says it is.
|
// Mark the email as verified according to the policy and whether the provider
|
||||||
if payload.email_verified {
|
// claims it is, and make it the primary email.
|
||||||
repo.user_email()
|
if provider
|
||||||
|
.claims_imports
|
||||||
|
.verify_email
|
||||||
|
.should_mark_as_verified(payload.email_verified)
|
||||||
|
{
|
||||||
|
let user_email = repo
|
||||||
|
.user_email()
|
||||||
.mark_as_verified(&clock, user_email)
|
.mark_as_verified(&clock, user_email)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
repo.user_email().set_as_primary(&user_email).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@
|
|||||||
"default": null,
|
"default": null,
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/ImportPreference"
|
"$ref": "#/definitions/EmailImportPreference"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -687,6 +687,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"EmailImportPreference": {
|
||||||
|
"description": "What should be done with the email claim",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"action": {
|
||||||
|
"description": "How to handle the claim",
|
||||||
|
"default": "ignore",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/ImportAction"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"set_email_verification": {
|
||||||
|
"description": "Should the email address be marked as verified",
|
||||||
|
"default": "import",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/SetEmailVerification"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"EmailSmtpMode": {
|
"EmailSmtpMode": {
|
||||||
"description": "Encryption mode to use",
|
"description": "Encryption mode to use",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
@ -1752,6 +1776,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"SetEmailVerification": {
|
||||||
|
"description": "Should the email address be marked as verified",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"description": "Mark the email address as verified",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"always"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Don't mark the email address as verified",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"never"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Mark the email address as verified if the upstream provider says it is through the `email_verified` claim",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"import"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"TelemetryConfig": {
|
"TelemetryConfig": {
|
||||||
"description": "Configuration related to sending monitoring data",
|
"description": "Configuration related to sending monitoring data",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
Reference in New Issue
Block a user