mirror of
https://github.com/element-hq/matrix-authentication-service.git
synced 2026-10-15 02:22:43 +00:00
Compare a registration token's pinned email address ignoring case
The rest of MAS compares email addresses ignoring case. Comparing the pin exactly made a token pinning `Alice@Example.com` unusable by a registration whose address came from an upstream provider as `alice@example.com`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LpxhUvvbRYpQSxhidPnnP7
This commit is contained in:
committed by
Quentin Gliech
co-authored by
Claude Opus 5.5
parent
6d30f3be66
commit
56f193dfbc
@@ -127,7 +127,11 @@ pub(super) async fn register(
|
||||
state.add_error_on_field(RegisterFormField::Username, FieldError::Invalid);
|
||||
}
|
||||
|
||||
if pinned_email.is_some_and(|pinned| Some(pinned) != email.as_deref()) {
|
||||
if pinned_email.is_some_and(|pinned| {
|
||||
!email
|
||||
.as_deref()
|
||||
.is_some_and(|email| pinned.eq_ignore_ascii_case(email))
|
||||
}) {
|
||||
state.add_error_on_field(RegisterFormField::Email, FieldError::Invalid);
|
||||
}
|
||||
|
||||
@@ -1172,6 +1176,39 @@ mod tests {
|
||||
assert!(!repo.user().exists("mallory").await.unwrap());
|
||||
}
|
||||
|
||||
/// An invite code's pinned email address matches whatever its case
|
||||
#[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")]
|
||||
async fn test_register_with_token_email_in_another_case(pool: PgPool) {
|
||||
setup();
|
||||
let state = TestState::from_pool(pool).await.unwrap();
|
||||
let cookies = CookieHelper::new();
|
||||
|
||||
add_registration_token(
|
||||
&state,
|
||||
"invite_alice",
|
||||
None,
|
||||
Some("alice@example.com"),
|
||||
false,
|
||||
)
|
||||
.await;
|
||||
|
||||
let csrf_token = mint_csrf_token(&state, &cookies);
|
||||
let request = Request::post(&*mas_router::Register::default().path_and_query()).form(
|
||||
serde_json::json!({
|
||||
"csrf": csrf_token,
|
||||
"username": "alice",
|
||||
"email": "Alice@Example.com",
|
||||
"password": "correcthorsebatterystaple",
|
||||
"password_confirm": "correcthorsebatterystaple",
|
||||
"token": "invite_alice",
|
||||
"accept_terms": "on",
|
||||
}),
|
||||
);
|
||||
let request = cookies.with_cookies(request);
|
||||
let response = state.request(request).await;
|
||||
response.assert_status(StatusCode::SEE_OTHER);
|
||||
}
|
||||
|
||||
/// An invite code which pins an email address can't be used to register
|
||||
/// another
|
||||
#[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")]
|
||||
|
||||
@@ -26,7 +26,7 @@ fn token_fits(
|
||||
&& token
|
||||
.email
|
||||
.as_deref()
|
||||
.is_none_or(|pinned| Some(pinned) == email)
|
||||
.is_none_or(|pinned| email.is_some_and(|email| pinned.eq_ignore_ascii_case(email)))
|
||||
&& (token.passwordless
|
||||
|| registration.password.is_some()
|
||||
|| registration
|
||||
|
||||
@@ -325,6 +325,39 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// A token's pinned email address matches whatever its case
|
||||
#[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")]
|
||||
async fn test_accepts_token_pinning_the_email_in_another_case(pool: PgPool) {
|
||||
setup();
|
||||
let state = TestState::from_pool(pool).await.unwrap();
|
||||
let cookies = CookieHelper::new();
|
||||
|
||||
add_registration_token(
|
||||
&state,
|
||||
"invite_alice",
|
||||
None,
|
||||
Some("Alice@Example.com"),
|
||||
false,
|
||||
)
|
||||
.await;
|
||||
let registration = add_registration(
|
||||
&state,
|
||||
&cookies,
|
||||
"alice",
|
||||
Some("alice@example.com"),
|
||||
true,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
let response = submit_token(&state, &cookies, ®istration, "invite_alice").await;
|
||||
response.assert_status(StatusCode::SEE_OTHER);
|
||||
response.assert_header_value(
|
||||
LOCATION,
|
||||
&mas_router::RegisterFinish::new(registration.id).path_and_query(),
|
||||
);
|
||||
}
|
||||
|
||||
/// A registration linked upstream needs no password, so any token fits it
|
||||
#[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")]
|
||||
async fn test_accepts_token_not_passwordless_upstream(pool: PgPool) {
|
||||
|
||||
Reference in New Issue
Block a user