Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Add support for allowing users based on their domain (#1651)
Browse filese.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]>
- .env +2 -0
- 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
}
|