Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🛂 feat: Required OpenID Role #2279

Merged
merged 20 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@ OPENID_ISSUER=
OPENID_SESSION_SECRET=
OPENID_SCOPE="openid profile email"
OPENID_CALLBACK_URL=/oauth/openid/callback
OPENID_REQUIRED_ROLE=
OPENID_REQUIRED_ROLE_TOKEN_KIND=
OPENID_REQUIRED_ROLE_PARAMETER_PATH=

OPENID_BUTTON_LABEL=
OPENID_IMAGE_URL=
Expand Down
35 changes: 34 additions & 1 deletion api/strategies/openidStrategy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const fs = require('fs');
const path = require('path');
const axios = require('axios');
const passport = require('passport');
const jwtDecode = require('jsonwebtoken/decode');
const { Issuer, Strategy: OpenIDStrategy } = require('openid-client');
const { logger } = require('~/config');
const User = require('~/models/User');
Expand Down Expand Up @@ -44,7 +45,9 @@ async function setupOpenId() {
client_secret: process.env.OPENID_CLIENT_SECRET,
redirect_uris: [process.env.DOMAIN_SERVER + process.env.OPENID_CALLBACK_URL],
});

const requiredRole = process.env.OPENID_REQUIRED_ROLE;
const requiredRoleParameterPath = process.env.OPENID_REQUIRED_ROLE_PARAMETER_PATH;
const requiredRoleTokenKind = process.env.OPENID_REQUIRED_ROLE_TOKEN_KIND;
const openidLogin = new OpenIDStrategy(
{
client,
Expand All @@ -71,6 +74,36 @@ async function setupOpenId() {
fullName = userinfo.username || userinfo.email;
}

if (requiredRole) {
let decodedToken = '';
if (requiredRoleTokenKind === 'access') {
decodedToken = jwtDecode(tokenset.access_token);
} else if (requiredRoleTokenKind === 'id') {
decodedToken = jwtDecode(tokenset.id_token);
}
const pathParts = requiredRoleParameterPath.split('.');
let found = true;
let roles = pathParts.reduce((o, key) => {
if (o === null || o === undefined || !(key in o)) {
found = false;
return [];
}
return o[key];
}, decodedToken);

if (!found) {
console.error(
`Key '${requiredRoleParameterPath}' not found in ${requiredRoleTokenKind} token!`,
);
}

if (!roles.includes(requiredRole)) {
return done(null, false, {
message: `You must have the "${requiredRole}" role to log in.`,
});
}
}

if (!user) {
user = new User({
provider: 'openid',
Expand Down
114 changes: 114 additions & 0 deletions docs/install/configuration/OAuth2-and-OIDC/aws.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
title: AWS Cognito
description: Learn how to configure LibreChat to use AWS Cognito for user authentication.
weight: -7
---

# AWS Cognito

## Create a new User Pool in Cognito

- Visit: **[https://console.aws.amazon.com/cognito/](https://console.aws.amazon.com/cognito/)**
- Sign in as Root User
- Click on `Create user pool`

![image](https://github.com/danny-avila/LibreChat/assets/32828263/e9b412c3-2cf1-4f54-998c-d1d6c12581a5)

## Configure sign-in experience

Your Cognito user pool sign-in options should include `User Name` and `Email`.

![image](https://github.com/danny-avila/LibreChat/assets/32828263/d2cf362d-469e-4993-8466-10282da114c2)

## Configure Security Requirements

You can configure the password requirements now if you desire

![image](https://github.com/danny-avila/LibreChat/assets/32828263/e125e8f1-961b-4a38-a6b7-ed1faf29c4a3)

## Configure sign-up experience

Choose the attributes required at signup. The minimum required is `name`. If you want to require users to use their full name at sign up use: `given_name` and `family_name` as required attributes.

![image](https://github.com/danny-avila/LibreChat/assets/32828263/558b8e2c-afbd-4dd1-87f3-c409463b5f7c)

## Configure message delivery

Send email with Cognito can be used for free for up to 50 emails a day

![image](https://github.com/danny-avila/LibreChat/assets/32828263/fcb2323b-708e-488c-9420-7eb482974648)

## Integrate your app

Select `Use Cognitio Hosted UI` and chose a domain name

![image](https://github.com/danny-avila/LibreChat/assets/32828263/111b3dd4-3b20-4e3e-80e1-7167d2ad0f62)

Set the app type to `Confidential client`
Make sure `Generate a client secret` is set.
Set the `Allowed callback URLs` to `https://YOUR_DOMAIN/oauth/openid/callback`

![image](https://github.com/danny-avila/LibreChat/assets/32828263/1f92a532-7c4d-4632-a55d-9d00bf77fc4d)

Under `Advanced app client settings` make sure `Profile` is included in the `OpenID Connect scopes` (in the bottom)

![image](https://github.com/danny-avila/LibreChat/assets/32828263/5b035eae-4a8e-482c-abd5-29cee6502eeb)

## Review and create
You can now make last minute changes, click on `Create user pool` when you're done reviewing the configuration

![image](https://github.com/danny-avila/LibreChat/assets/32828263/dc8b2374-9adb-4065-85dc-a087d625372d)

![image](https://github.com/danny-avila/LibreChat/assets/32828263/67efb1e9-dfe3-4ebd-9ebb-92186c514b5c)

![image](https://github.com/danny-avila/LibreChat/assets/32828263/9f819175-ace1-44b1-ba68-af21ac9f6735)

![image](https://github.com/danny-avila/LibreChat/assets/32828263/3e7b8b17-4e12-49af-99cf-78981d6331df)

## Get your environment variables

1. Open your User Pool

![image](https://github.com/danny-avila/LibreChat/assets/32828263/b658ff2a-d252-4f3d-90a7-9fbde42c01db)

2. The `User Pool ID` and your AWS region will be used to construct the `OPENID_ISSUER` (see below)

![image](https://github.com/danny-avila/LibreChat/assets/32828263/dc8ae403-cbff-4aae-9eee-42d7cf3485e7)
![image](https://github.com/danny-avila/LibreChat/assets/32828263/d606f5c8-c60b-4d20-bdb2-d0d69e49ea1e)

3. Go to the `App Integrations` tab

![image](https://github.com/danny-avila/LibreChat/assets/32828263/58713bdc-24bc-47de-bdca-020dc321e997)

4. Open the app client

![image](https://github.com/danny-avila/LibreChat/assets/32828263/271bf7d2-3df2-43a7-87fc-e50294e49b2e)

5. Toggle `Show Client Secret`

![image](https://github.com/danny-avila/LibreChat/assets/32828263/a844fe65-313d-4754-81b4-380336e0e336)

- Use the `Client ID` for `OPENID_CLIENT_ID`

- Use the `Client secret` for `OPENID_CLIENT_SECRET`

- Generate a random string for the `OPENID_SESSION_SECRET`

> The `OPENID_SCOPE` and `OPENID_CALLBACK_URL` are pre-configured with the correct values

6. Open the `.env` file at the root of your LibreChat folder and add the following variables with the values you copied:

```bash
DOMAIN_CLIENT=https://your-domain.com # use http://localhost:3080 if not using a custom domain
DOMAIN_SERVER=https://your-domain.com # use http://localhost:3080 if not using a custom domain

OPENID_CLIENT_ID=Your client ID
OPENID_CLIENT_SECRET=Your client secret
OPENID_ISSUER=https://cognito-idp.[AWS REGION].amazonaws.com/[USER POOL ID]/.well-known/openid-configuration
OPENID_SESSION_SECRET=Any random string
OPENID_SCOPE=openid profile email
OPENID_CALLBACK_URL=/oauth/openid/callback
```
7. Save the .env file

> Note: If using docker, run `docker compose up -d` to apply the .env configuration changes
59 changes: 59 additions & 0 deletions docs/install/configuration/OAuth2-and-OIDC/azure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: Azure Entra
description: Learn how to configure LibreChat to use Azure Entra for user authentication.
weight: -6
---

# OpenID with Azure Entra

1. Go to the [Azure Portal](https://portal.azure.com/) and sign in with your account.
2. In the search box, type "Azure Entra" and click on it.
3. On the left menu, click on App registrations and then on New registration.
4. Give your app a name and select Web as the platform type.
5. In the Redirect URI field, enter `http://localhost:3080/oauth/openid/callback` and click on Register.

![image](https://github.com/danny-avila/LibreChat/assets/6623884/2b1aabce-850e-4165-bf76-3c1984f10b6c)

6. You will see an Overview page with some information about your app. Copy the Application (client) ID and the
Directory (tenant) ID and save them somewhere.

![image](https://github.com/danny-avila/LibreChat/assets/6623884/e67d5e97-e26d-48a5-aa6e-50de4450b1fd)

7. On the left menu, click on Authentication and check the boxes for Access tokens and ID tokens under Implicit
grant and hybrid flows.

![image](https://github.com/danny-avila/LibreChat/assets/6623884/88a16cbc-ff68-4b3a-ba7b-b380cc3d2366)

8. On the left menu, click on Certificates & Secrets and then on New client secret. Give your secret a
name and an expiration date and click on Add. You will see a Value column with your secret. Copy it and
save it somewhere. Don't share it with anyone!

![image](https://github.com/danny-avila/LibreChat/assets/6623884/31aa6cee-5402-4ce0-a950-1b7e147aafc8)

9. If you want to restrict access by groups you should add the groups claim to the token. To do this, go to
Token configuration and click on Add group claim. Select the groups you want to include in the token and click on Add.

![image](https://github.com/danny-avila/LibreChat/assets/6623884/c9d353f5-2cb2-4f00-b4f0-493cfec8fe9a)

10. Open the .env file in your project folder and add the following variables with the values you copied:

```bash
DOMAIN_CLIENT=https://your-domain.com # use http://localhost:3080 if not using a custom domain
DOMAIN_SERVER=https://your-domain.com # use http://localhost:3080 if not using a custom domain

OPENID_CLIENT_ID=Your Application (client) ID
OPENID_CLIENT_SECRET=Your client secret
OPENID_ISSUER=https://login.microsoftonline.com/Your Directory (tenant ID)/v2.0/
OPENID_SESSION_SECRET=Any random string
OPENID_SCOPE=openid profile email #DO NOT CHANGE THIS
OPENID_CALLBACK_URL=/oauth/openid/callback # this should be the same for everyone

# If you want to restrict access by groups
OPENID_REQUIRED_ROLE_TOKEN_KIND=id
OPENID_REQUIRED_ROLE_PARAMETER_PATH="roles"
OPENID_REQUIRED_ROLE="Your Group Name"
```
11. Save the .env file

> Note: If using docker, run `docker compose up -d` to apply the .env configuration changes

49 changes: 49 additions & 0 deletions docs/install/configuration/OAuth2-and-OIDC/discord.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
title: Discord
description: Learn how to configure LibreChat to use Discord for user authentication.
weight: -11
---

# Discord

## Create a new Discord Application

- Go to **[Discord Developer Portal](https://discord.com/developers)**

- Create a new Application and give it a name

![image](https://github.com/danny-avila/LibreChat/assets/32828263/7e7cdfa0-d1d6-4b6b-a8a9-905aaa40d135)

## Discord Application Configuration

- In the OAuth2 general settings add a valid redirect URL:
- Example for localhost: `http://localhost:3080/oauth/discord/callback`
- Example for a domain: `https://example.com/oauth/discord/callback`

![image](https://github.com/danny-avila/LibreChat/assets/32828263/6c56fb92-f4ab-43b9-981b-f98babeeb19d)

- In `Default Authorization Link`, select `In-app Authorization` and set the scopes to `applications.commands`

![image](https://github.com/danny-avila/LibreChat/assets/32828263/2ce94670-9422-48d2-97e9-ec40bd331573)

- Save changes and reset the Client Secret

![image](https://github.com/danny-avila/LibreChat/assets/32828263/3af164fc-66ed-4e5e-9f5a-9bcab3df37b4)
![image](https://github.com/danny-avila/LibreChat/assets/32828263/2ece3935-68e6-4f2e-8656-9721cba5388a)

## .env Configuration

- Paste your `Client ID` and `Client Secret` in the `.env` file:

```bash
DOMAIN_CLIENT=https://your-domain.com # use http://localhost:3080 if not using a custom domain
DOMAIN_SERVER=https://your-domain.com # use http://localhost:3080 if not using a custom domain

DISCORD_CLIENT_ID=your_client_id
DISCORD_CLIENT_SECRET=your_client_secret
DISCORD_CALLBACK_URL=/oauth/discord/callback
```

- Save the `.env` file

> Note: If using docker, run `docker compose up -d` to apply the .env configuration changes
83 changes: 83 additions & 0 deletions docs/install/configuration/OAuth2-and-OIDC/facebook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: Facebook
description: Learn how to configure LibreChat to use Facebook for user authentication.
weight: -8
---

# Facebook - WIP

> ⚠️ **Warning: Work in progress, not currently functional**

> ❗ Note: Facebook Authentication will not work from `localhost`

## Create a Facebook Application

- Go to the **[Facebook Developer Portal](https://developers.facebook.com/)**

- Click on "My Apps" in the header menu

![image](https://github.com/danny-avila/LibreChat/assets/32828263/b75ccb8b-d56b-41b7-8b0d-a32c2e762962)

- Create a new application

![image](https://github.com/danny-avila/LibreChat/assets/32828263/706f050d-5423-44cc-80f0-120913695d8f)

- Select "Authenticate and request data from users with Facebook Login"

![image](https://github.com/danny-avila/LibreChat/assets/32828263/2ebbb571-afe8-429e-ab39-be6e83d12c01)

- Choose "No, I'm not creating a game"

![image](https://github.com/danny-avila/LibreChat/assets/32828263/88b5160a-9c72-414a-bbcc-7717b81106f3)

- Provide an `app name` and `App contact email` and click `Create app`

![image](https://github.com/danny-avila/LibreChat/assets/32828263/e1282c9e-4e7d-4cbe-82c9-cc76967f83e1)

## Facebook Application Configuration

- In the side menu, select "Use cases" and click "Customize" under "Authentication and account creation."

![image](https://github.com/danny-avila/LibreChat/assets/32828263/39f4bb70-d9dc-4d1c-8443-2666fe56499b)

- Add the `email permission`

![image](https://github.com/danny-avila/LibreChat/assets/32828263/dfa20879-2cb8-4daf-883d-3790854afca0)

- Now click `Go to settings`

![image](https://github.com/danny-avila/LibreChat/assets/32828263/512213a2-bd8b-4fd3-96c7-0de6d3222ddd)

- Ensure that `Client OAuth login`, `Web OAuth login` and `Enforce HTTPS` are **enabled**.

![image](https://github.com/danny-avila/LibreChat/assets/32828263/3a7d935b-97bf-493b-b909-39ecf9b3432b)

- Add a `Valid OAuth Redirect URIs` and "Save changes"
- Example for a domain: `https://example.com/oauth/facebook/callback`

![image](https://github.com/danny-avila/LibreChat/assets/32828263/ef8e54ee-a766-4871-9719-d4eff7a770b6)

- Click `Go back` and select `Basic` in the `App settings` tab

![image](https://github.com/danny-avila/LibreChat/assets/32828263/0d14f702-5183-422e-a12c-5d1b6031581b)

- Click "Show" next to the App secret.

![image](https://github.com/danny-avila/LibreChat/assets/32828263/9a009e37-2bb6-4da6-b5c7-9139c3db6185)

## .env Configuration

- Copy the `App ID` and `App Secret` and paste them into the `.env` file as follows:

```bash
DOMAIN_CLIENT=https://your-domain.com # use http://localhost:3080 if not using a custom domain
DOMAIN_SERVER=https://your-domain.com # use http://localhost:3080 if not using a custom domain

FACEBOOK_CLIENT_ID=your_app_id
FACEBOOK_CLIENT_SECRET=your_app_secret
FACEBOOK_CALLBACK_URL=/oauth/facebook/callback
```

- Save the `.env` file.

> Note: If using docker, run `docker compose up -d` to apply the .env configuration changes
Loading
Loading