fix: read Entra claims from id_token + UPN e-mail fallback (#24)
First Microsoft logins failed with 400 "email: Cannot be blank": Graph's
/oidc/userinfo endpoint omits the email claim for accounts without a
mail attribute, and team_members requires an e-mail (it also drives the
ENTRA_ADMIN_EMAILS role mapping). Reproduced against a mock Entra with
PocketBase v0.30.4; the user-supplied response body matched the
missing-email fingerprint exactly.
- provider config (reconciler + migration fast-path): userInfoURL is now
empty, so PocketBase reads the claims from the Entra id_token, which
always carries preferred_username (UPN) and email when available. The
#18 reconciler flips the already-deployed Labs provider automatically
on the next boot — no migration needed.
- pb_hooks/entra_oidc.pb.js: onRecordAuthWithOAuth2Request hook falls
back to the lowercased UPN when the email claim is absent. Guest UPNs
(ext_user#EXT#@tenant...) are excluded explicitly — "#" is RFC-valid
in an e-mail local part, so both a naive regex AND PocketBase's own
validation would accept them (caught by test V5). The hook also logs
every failed OAuth2 attempt with the underlying error to the container
log, which PocketBase otherwise only writes to its internal logs db.
Verified with a switchable mock-Entra matrix (8/8): no-email→UPN e-mail
+ allow-list role, email claim wins when present, no duplicate on
re-login, guest UPN yields a clean validation error, anonymous REST
create stays rejected, both log lines present. Regression: issue-22
matrix 9/9 (baseline pinned to 1a1351d now that #23 is merged), DoD
harness 15/15, npm test 112/112.
Closes #24
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -76,7 +76,12 @@ module.exports = {
|
||||
clientSecret: clientSecret,
|
||||
authURL: "https://login.microsoftonline.com/" + tenant + "/oauth2/v2.0/authorize",
|
||||
tokenURL: "https://login.microsoftonline.com/" + tenant + "/oauth2/v2.0/token",
|
||||
userInfoURL: "https://graph.microsoft.com/oidc/userinfo",
|
||||
// Deliberately empty: claims are read from the Entra id_token instead of
|
||||
// Graph's /oidc/userinfo. The userinfo endpoint omits `email` for
|
||||
// accounts without a mail attribute, while the id_token always carries
|
||||
// `preferred_username` (UPN) which entra_oidc.pb.js uses as an e-mail
|
||||
// fallback (issue #24).
|
||||
userInfoURL: "",
|
||||
displayName: "Microsoft",
|
||||
pkce: true,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user