-
Notifications
You must be signed in to change notification settings - Fork 75
Description
Bug Report: MAS userinfo endpoint does not return email claim
Summary
Matrix Authentication Service (MAS) v1.8.0 userinfo endpoint does not return the email claim even when:
- The
emailscope is requested and granted - The user has a verified primary email address
Environment
- MAS Version: v1.8.0 (mas-cli v1.8.0)
- Repository: element-hq/matrix-authentication-service (latest main branch as of 2025-12-23)
- Deployment: Render.com (Docker container)
- Client: Authentik 2025.10.3 as OAuth source
Steps to Reproduce
- Configure a third-party OIDC client (e.g., Authentik) with MAS
- Request scopes:
openid email - User authenticates and grants consent
- Client exchanges code for token
- Client fetches userinfo endpoint:
GET /oauth2/userinfo
Expected Behavior
Per MAS documentation:
The
Per OpenID Connect Core 1.0 spec, Section 5.4:
The
email_verifiedClaims.
Expected userinfo response:
{
"sub": "01KD48QPHGZ4Z6A2S1HEP1DMX6",
"username": "ivantohelpyou",
"email": "[email protected]",
"email_verified": true
}Actual Behavior
Userinfo response only contains:
{
"sub": "01KD48QPHGZ4Z6A2S1HEP1DMX6",
"username": "ivantohelpyou"
}No email field is present.
Verification
Confirmed via database queries that:
- Session has email scope:
SELECT scope_list FROM oauth2_sessions ORDER BY created_at DESC LIMIT 1;
-- Result: {email,openid}- User has confirmed primary email:
SELECT u.username, e.email, e.confirmed_at
FROM users u
JOIN user_emails e ON u.primary_user_email_id = e.user_email_id
WHERE u.username = 'ivantohelpyou';
-- Result: ivantohelpyou | [email protected] | 2025-12-23 07:33:19.063857+00Source Code Analysis
Reviewed crates/handlers/src/oauth2/userinfo.rs (lines 34-37 in latest main):
#[derive(Serialize)]
struct UserInfo {
sub: String,
username: String,
}Root Cause: The UserInfo struct only contains sub and username fields. The email and email_verified fields are completely missing from the struct definition.
There is no code in the handler to:
- Check if the
emailscope was granted - Retrieve the user's primary email from the database
- Include email claims in the response
This appears to be an incomplete implementation rather than a configuration issue.
Impact
Severity: High - Breaks OIDC compliance and third-party integrations
- Third-party applications (Vikunja, Gitea, Authentik, etc.) that rely on the userinfo endpoint to get user email addresses cannot function properly with MAS as the identity provider
- MAS claims to support the
emailscope in documentation and discovery endpoint, but does not actually implement it - Forces manual workarounds or prevents using MAS as an identity provider for many applications
- Violates OpenID Connect Core 1.0 specification for the
emailscope
Workaround
Manually set the email on the downstream IdP (Authentik) user after first login, bypassing the MAS userinfo endpoint.
Additional Context
- MAS discovery endpoint (
/.well-known/openid-configuration) correctly listsemailinscopes_supported - MAS consent screen correctly displays "email" permission being requested
- The OAuth flow itself works correctly - the issue is purely in the userinfo handler implementation
- The database contains all necessary data (confirmed primary email exists and is verified)
- This bug exists in both the archived matrix-org repository and the current element-hq repository
Proposed Fix
The UserInfo struct in crates/handlers/src/oauth2/userinfo.rs should be updated to:
#[derive(Serialize)]
struct UserInfo {
sub: String,
username: String,
#[serde(skip_serializing_if = "Option::is_none")]
email: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
email_verified: Option<bool>,
}And the handler should:
- Check if the session has the
emailscope - If yes, fetch the user's primary email from the database
- Include
emailandemail_verifiedin the response