Skip to content

Commit

Permalink
Add support for allowing users based on their domain (#1651)
Browse files Browse the repository at this point in the history
e.g.
  ALLOWED_USER_DOMAINS=`["example.com"]`
  will allow both foo@example.com and bar@example.com

A user can log in if one of the conditions is true:
  - ALLOWED_USER_DOMAINS and ALLOWED_USER_EMAILS are empty
  - their email is in ALLOWED_USER_EMAILS
  - their email domain ALLOWED_USER_DOMAINS

Co-authored-by: Nathan Sarrazin <sarrazin.nathan@gmail.com>
  • Loading branch information
laurentlb and nsarrazin authored Jan 16, 2025
1 parent 2bb2a9f commit 1021e2f
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ OPENID_CONFIG=
MESSAGES_BEFORE_LOGIN=# how many messages a user can send in a conversation before having to login. set to 0 to force login right away
# if it's defined, only these emails will be allowed to use login
ALLOWED_USER_EMAILS=`[]`
# If it's defined, users with emails matching these domains will also be allowed to use login
ALLOWED_USER_DOMAINS=`[]`
# valid alternative redirect URLs for OAuth, used for HuggingChat apps
ALTERNATIVE_REDIRECT_URLS=`[]`
### Cookies
Expand Down
17 changes: 14 additions & 3 deletions src/routes/login/callback/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ const allowedUserEmails = z
.default([])
.parse(JSON5.parse(env.ALLOWED_USER_EMAILS));

const allowedUserDomains = z
.array(z.string().regex(/\.\w+$/)) // Contains at least a dot
.optional()
.default([])
.parse(JSON5.parse(env.ALLOWED_USER_DOMAINS));

export async function load({ url, locals, cookies, request, getClientAddress }) {
const { error: errorName, error_description: errorDescription } = z
.object({
Expand Down Expand Up @@ -46,16 +52,21 @@ export async function load({ url, locals, cookies, request, getClientAddress })
iss
);

// Filter by allowed user emails
if (allowedUserEmails.length > 0) {
// Filter by allowed user emails or domains
if (allowedUserEmails.length > 0 || allowedUserDomains.length > 0) {
if (!userData.email) {
error(403, "User not allowed: email not returned");
}
const emailVerified = userData.email_verified ?? true;
if (!emailVerified) {
error(403, "User not allowed: email not verified");
}
if (!allowedUserEmails.includes(userData.email)) {

const emailDomain = userData.email.split("@")[1];
const isEmailAllowed = allowedUserEmails.includes(userData.email);
const isDomainAllowed = allowedUserDomains.includes(emailDomain);

if (!isEmailAllowed && !isDomainAllowed) {
error(403, "User not allowed");
}
}
Expand Down

0 comments on commit 1021e2f

Please sign in to comment.