feat(auth): allow sign-in by verified email domain, not just login allowlist#107
Merged
danielnaab merged 1 commit intomainfrom Apr 20, 2026
Merged
Conversation
…lowlist Previously the only authorization path was a comma-separated GitHub login allowlist in \`ALLOWED_USERS\`, defaulting to \`danielnaab\`. That meant even for colleagues at flexion, the operator had to know and add each GitHub username up front — a Flexion employee whose login wasn't on the list got redirected with \`error=unauthorized\`. Adds a complementary path: \`ALLOWED_EMAIL_DOMAINS\`. A user passes authorization if their GitHub login is in \`ALLOWED_USERS\` OR any of their verified GitHub emails matches a domain in \`ALLOWED_EMAIL_DOMAINS\`. Either alone is sufficient — personal-dev logins still work on an instance with a strict corporate-domain policy. Mechanics: - New \`fetchUserEmails(token)\` hits \`/user/emails\`. Requires the \`user:email\` OAuth scope, added to the signin redirect. - Empty-list response on 404 (scope missing) rather than throw — the login allowlist can still cover the user. - New \`hasAllowedEmailDomain(emails, domains)\` — case-insensitive exact domain match, verified emails only. Explicitly does not admit substring matches (\`not-flexion.us\` is rejected when the allowed domain is \`flexion.us\`). - Auth callback checks login first, then falls through to email domain only if needed. Logs which path authorised the user. Defaults: - \`ALLOWED_USERS=danielnaab\` (unchanged) - \`ALLOWED_EMAIL_DOMAINS=''\` (empty — no change in default behaviour) Production deployment: - NixOS per-branch env file now sets \`ALLOWED_EMAIL_DOMAINS=flexion.us\`. - Takes effect on next \`bun run cli nixos apply\` + branch redeploy. Tests added for \`fetchUserEmails\` (happy path, 404 fallback) and \`hasAllowedEmailDomain\` (match, case, unverified rejection, empty list, substring rejection). Existing auth-routes scope assertion updated to the new scope string.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Previously the only path to authorization was a comma-separated GitHub login allowlist in `ALLOWED_USERS`, defaulting to `danielnaab`. A Flexion colleague whose GitHub login wasn't on that list got redirected with `error=unauthorized` — fine for a solo dev project but the wrong default for a team resource.
Change
A user now passes authorization if their GitHub login is in `ALLOWED_USERS` or any of their verified GitHub emails matches a domain in `ALLOWED_EMAIL_DOMAINS`. Either mechanism alone is sufficient; evaluated in that order so a personal-dev login still works on an instance with a strict corporate-domain policy.
Details:
Defaults
Production rollout
`infrastructure/nixos/modules/deploy.nix` now sets `ALLOWED_EMAIL_DOMAINS=flexion.us` in the per-branch env file. Takes effect after `bun run cli nixos apply` on the EC2 instance and a branch redeploy. Existing users aren't affected — the login allowlist is still checked first.
Testing
Security notes