Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/hash-external-services/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,18 @@ services:
# KRATOS_OIDC_ENABLED=true
# KRATOS_OIDC_GOOGLE_CLIENT_ID=<your-client-id>
# KRATOS_OIDC_GOOGLE_CLIENT_SECRET=<your-client-secret>
# KRATOS_OIDC_MICROSOFT_CLIENT_ID=<your-client-id>
# KRATOS_OIDC_MICROSOFT_CLIENT_SECRET=<your-client-secret>
# KRATOS_OIDC_MICROSOFT_TENANT_ID=<your-tenant-id>
SELFSERVICE_METHODS_OIDC_ENABLED: "${KRATOS_OIDC_ENABLED:-false}"
SELFSERVICE_FLOWS_REGISTRATION_AFTER_OIDC_HOOKS_0_CONFIG_URL: "http://host.docker.internal:5001/kratos-after-registration"
SELFSERVICE_FLOWS_REGISTRATION_AFTER_OIDC_HOOKS_0_CONFIG_AUTH_CONFIG_VALUE: "${KRATOS_API_KEY}"
SELFSERVICE_METHODS_OIDC_CONFIG_BASE_REDIRECT_URI: "http://localhost:5001/auth"
SELFSERVICE_METHODS_OIDC_CONFIG_PROVIDERS_0_CLIENT_ID: "${KRATOS_OIDC_GOOGLE_CLIENT_ID}"
SELFSERVICE_METHODS_OIDC_CONFIG_PROVIDERS_0_CLIENT_SECRET: "${KRATOS_OIDC_GOOGLE_CLIENT_SECRET}"
SELFSERVICE_METHODS_OIDC_CONFIG_PROVIDERS_1_CLIENT_ID: "${KRATOS_OIDC_MICROSOFT_CLIENT_ID}"
SELFSERVICE_METHODS_OIDC_CONFIG_PROVIDERS_1_CLIENT_SECRET: "${KRATOS_OIDC_MICROSOFT_CLIENT_SECRET}"
SELFSERVICE_METHODS_OIDC_CONFIG_PROVIDERS_1_MICROSOFT_TENANT: "${KRATOS_OIDC_MICROSOFT_TENANT_ID}"
SELFSERVICE_FLOWS_VERIFICATION_UI_URL: "http://localhost:3000/verification"
SELFSERVICE_FLOWS_RECOVERY_UI_URL: "http://localhost:3000/recovery"
SELFSERVICE_FLOWS_SETTINGS_UI_URL: "http://localhost:3000/settings/security"
Expand Down
25 changes: 25 additions & 0 deletions apps/hash-external-services/kratos/hooks/oidc.microsoft.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
local claims = std.extVar('claims');

// Microsoft may provide email via 'email', 'preferred_username', or 'upn'
local email =
if "email" in claims && claims.email != "" then claims.email
else if "preferred_username" in claims && claims.preferred_username != "" then claims.preferred_username
else if "upn" in claims && claims.upn != "" then claims.upn
else error "Microsoft OIDC: no email claim found in token";

{
identity: {
traits: {
emails: [email],
},
// Microsoft Entra ID verifies directory emails; check email_verified
// claim if present, otherwise trust the directory.
verified_addresses: if "email_verified" in claims then (
if claims.email_verified then [
{ value: email, via: "email" },
] else []
) else [
{ value: email, via: "email" },
],
},
}
10 changes: 10 additions & 0 deletions apps/hash-external-services/kratos/kratos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ selfservice:
essential: true
email_verified:
essential: true
- id: microsoft
provider: microsoft
label: Microsoft
# Set `client_id` through the `SELFSERVICE_METHODS_OIDC_CONFIG_PROVIDERS_1_CLIENT_ID` environment variable
# Set `client_secret` through the `SELFSERVICE_METHODS_OIDC_CONFIG_PROVIDERS_1_CLIENT_SECRET` environment variable
# Set `microsoft_tenant` through the `SELFSERVICE_METHODS_OIDC_CONFIG_PROVIDERS_1_MICROSOFT_TENANT` environment variable
mapper_url: "file:///etc/config/kratos/hooks/oidc.microsoft.jsonnet"
scope:
- email
- profile
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing requested_claims makes email verification check ineffective

Medium Severity

The Microsoft provider in kratos.yml doesn't include requested_claims for email_verified (unlike the Google provider), so Microsoft will almost never include email_verified in the ID token. This means the email_verified check in oidc.microsoft.jsonnet is effectively dead code β€” the mapper will always fall into the else branch that unconditionally marks emails as verified. Combined with the preferred_username/upn fallback chain, any value Microsoft returns gets auto-verified without actual verification.

Additional Locations (1)
Fix in CursorΒ Fix in Web


flows:
error:
Expand Down
Loading