laurentlb nsarrazin commited on
Commit
9e5dd18
·
unverified ·
1 Parent(s): 3ad7680

Add support for allowing users based on their domain (#1651)

Browse files

e.g.
ALLOWED_USER_DOMAINS=`["example.com"]`
will allow both [email protected] and [email protected]

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 <[email protected]>

Files changed (2) hide show
  1. .env +2 -0
  2. src/routes/login/callback/+page.server.ts +14 -3
.env CHANGED
@@ -71,6 +71,8 @@ OPENID_CONFIG=
71
  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
72
  # if it's defined, only these emails will be allowed to use login
73
  ALLOWED_USER_EMAILS=`[]`
 
 
74
  # valid alternative redirect URLs for OAuth, used for HuggingChat apps
75
  ALTERNATIVE_REDIRECT_URLS=`[]`
76
  ### Cookies
 
71
  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
72
  # if it's defined, only these emails will be allowed to use login
73
  ALLOWED_USER_EMAILS=`[]`
74
+ # If it's defined, users with emails matching these domains will also be allowed to use login
75
+ ALLOWED_USER_DOMAINS=`[]`
76
  # valid alternative redirect URLs for OAuth, used for HuggingChat apps
77
  ALTERNATIVE_REDIRECT_URLS=`[]`
78
  ### Cookies
src/routes/login/callback/+page.server.ts CHANGED
@@ -12,6 +12,12 @@ const allowedUserEmails = z
12
  .default([])
13
  .parse(JSON5.parse(env.ALLOWED_USER_EMAILS));
14
 
 
 
 
 
 
 
15
  export async function load({ url, locals, cookies, request, getClientAddress }) {
16
  const { error: errorName, error_description: errorDescription } = z
17
  .object({
@@ -46,8 +52,8 @@ export async function load({ url, locals, cookies, request, getClientAddress })
46
  iss
47
  );
48
 
49
- // Filter by allowed user emails
50
- if (allowedUserEmails.length > 0) {
51
  if (!userData.email) {
52
  error(403, "User not allowed: email not returned");
53
  }
@@ -55,7 +61,12 @@ export async function load({ url, locals, cookies, request, getClientAddress })
55
  if (!emailVerified) {
56
  error(403, "User not allowed: email not verified");
57
  }
58
- if (!allowedUserEmails.includes(userData.email)) {
 
 
 
 
 
59
  error(403, "User not allowed");
60
  }
61
  }
 
12
  .default([])
13
  .parse(JSON5.parse(env.ALLOWED_USER_EMAILS));
14
 
15
+ const allowedUserDomains = z
16
+ .array(z.string().regex(/\.\w+$/)) // Contains at least a dot
17
+ .optional()
18
+ .default([])
19
+ .parse(JSON5.parse(env.ALLOWED_USER_DOMAINS));
20
+
21
  export async function load({ url, locals, cookies, request, getClientAddress }) {
22
  const { error: errorName, error_description: errorDescription } = z
23
  .object({
 
52
  iss
53
  );
54
 
55
+ // Filter by allowed user emails or domains
56
+ if (allowedUserEmails.length > 0 || allowedUserDomains.length > 0) {
57
  if (!userData.email) {
58
  error(403, "User not allowed: email not returned");
59
  }
 
61
  if (!emailVerified) {
62
  error(403, "User not allowed: email not verified");
63
  }
64
+
65
+ const emailDomain = userData.email.split("@")[1];
66
+ const isEmailAllowed = allowedUserEmails.includes(userData.email);
67
+ const isDomainAllowed = allowedUserDomains.includes(emailDomain);
68
+
69
+ if (!isEmailAllowed && !isDomainAllowed) {
70
  error(403, "User not allowed");
71
  }
72
  }