mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
Discord Login (#615)
* Add files via upload * Create linode-setup.md * Create cloudflare-setup.md * Update cloudflare-setup.md * Delete 4-linode.png * Delete 3-linode.png * Add files via upload * Add files via upload * Update cloudflare-setup.md * Update linode-setup.md * Rename cloudflare-setup.md to cloudflare.md * Rename linode-setup.md to linode.md * Update mkdocs.yml * Update cloudflare.md * Update linode.md * Update README.md * Update README.md * Update linode.md sentence in Italian * v1 The frontend has been completed, along with the .env variables. However, there is an issue of infinite loading thereafter. * Fix email and remove deprecated GitHub passport * Update user_auth_system.md add How to Set Up a Github Authentication * Update .env.example Improved the comment above the GitHub client ID and secret. * Update user_auth_system.md * Update package.json * Remove unnecessary passport GitHub package * fixed conflicts fixed conflicts between Berry-13:main and danny-avila:main in api/server/index.js 45:54 * Delete e -i HEAD~2 * (WIP) Discord Login * Fix duplicate githubLoginEnabled * .env.example restore * Update user_auth_system.md Discord Login * Fix and new Feature 1. Added Discord login to .env.example. 2. Created Google, Github, and Discord icons in client\src\components\svg. 3. Added the social login option in the .env file; it fixes the ---or---. Check Discord for more information. * fix Login.tsx and Registration.tsx * Update user_auth_system.md * Update .env.example * Added OpenID Icon * quick discord icon fix * discord strategy fix * remove comment
This commit is contained in:
parent
c17c1488ca
commit
747e087cf5
21 changed files with 328 additions and 144 deletions
19
.env.example
19
.env.example
|
|
@ -187,6 +187,9 @@ MEILI_MASTER_KEY=DrhYf7zENyR6AlUCKmnz0eYASOQdl6zxH7s7MKFSfFCt
|
||||||
# Allow Public Registration
|
# Allow Public Registration
|
||||||
ALLOW_REGISTRATION=true
|
ALLOW_REGISTRATION=true
|
||||||
|
|
||||||
|
# Allow Social Registration
|
||||||
|
ALLOW_SOCIAL_LOGIN=false
|
||||||
|
|
||||||
# JWT Secrets
|
# JWT Secrets
|
||||||
JWT_SECRET=secret
|
JWT_SECRET=secret
|
||||||
JWT_REFRESH_SECRET=secret
|
JWT_REFRESH_SECRET=secret
|
||||||
|
|
@ -219,12 +222,20 @@ OPENID_IMAGE_URL=
|
||||||
SESSION_EXPIRY=(1000 * 60 * 60 * 24) * 7
|
SESSION_EXPIRY=(1000 * 60 * 60 * 24) * 7
|
||||||
|
|
||||||
# Github:
|
# Github:
|
||||||
# Get the Client ID and Secret from your Github Application
|
# Get the Client ID and Secret from your Discord Application
|
||||||
|
# Add your Discord Client ID and Client Secret here:
|
||||||
|
|
||||||
|
GITHUB_CLIENT_ID=your_client_id
|
||||||
|
GITHUB_CLIENT_SECRET=your_client_secret
|
||||||
|
GITHUB_CALLBACK_URL=/oauth/github/callback # this should be the same for everyone
|
||||||
|
|
||||||
|
# Discord:
|
||||||
|
# Get the Client ID and Secret from your Discord Application
|
||||||
# Add your Github Client ID and Client Secret here:
|
# Add your Github Client ID and Client Secret here:
|
||||||
|
|
||||||
GITHUB_CLIENT_ID=
|
DISCORD_CLIENT_ID=your_client_id
|
||||||
GITHUB_CLIENT_SECRET=
|
DISCORD_CLIENT_SECRET=your_client_secret
|
||||||
GITHUB_CALLBACK_URL=/oauth/github/callback
|
DISCORD_CALLBACK_URL=/oauth/discord/callback # this should be the same for everyone
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
# Application Domains
|
# Application Domains
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,11 @@ const userSchema = mongoose.Schema(
|
||||||
unique: true,
|
unique: true,
|
||||||
sparse: true
|
sparse: true
|
||||||
},
|
},
|
||||||
|
discordId: {
|
||||||
|
type: String,
|
||||||
|
unique: true,
|
||||||
|
sparse: true
|
||||||
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: []
|
default: []
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,9 @@ config.validate(); // Validate the config
|
||||||
if (process.env.GITHUB_CLIENT_ID && process.env.GITHUB_CLIENT_SECRET) {
|
if (process.env.GITHUB_CLIENT_ID && process.env.GITHUB_CLIENT_SECRET) {
|
||||||
require('../strategies/githubStrategy');
|
require('../strategies/githubStrategy');
|
||||||
}
|
}
|
||||||
|
if (process.env.DISCORD_CLIENT_ID && process.env.DISCORD_CLIENT_SECRET) {
|
||||||
|
require('../strategies/discordStrategy');
|
||||||
|
}
|
||||||
if (process.env.OPENID_CLIENT_ID && process.env.OPENID_CLIENT_SECRET &&
|
if (process.env.OPENID_CLIENT_ID && process.env.OPENID_CLIENT_SECRET &&
|
||||||
process.env.OPENID_ISSUER && process.env.OPENID_SCOPE &&
|
process.env.OPENID_ISSUER && process.env.OPENID_SCOPE &&
|
||||||
process.env.OPENID_SESSION_SECRET) {
|
process.env.OPENID_SESSION_SECRET) {
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,11 @@ afterEach(() => {
|
||||||
delete process.env.OPENID_AUTH_URL;
|
delete process.env.OPENID_AUTH_URL;
|
||||||
delete process.env.GITHUB_CLIENT_ID;
|
delete process.env.GITHUB_CLIENT_ID;
|
||||||
delete process.env.GITHUB_CLIENT_SECRET;
|
delete process.env.GITHUB_CLIENT_SECRET;
|
||||||
|
delete process.env.DISCORD_CLIENT_ID;
|
||||||
|
delete process.env.DISCORD_CLIENT_SECRET;
|
||||||
delete process.env.DOMAIN_SERVER;
|
delete process.env.DOMAIN_SERVER;
|
||||||
delete process.env.ALLOW_REGISTRATION;
|
delete process.env.ALLOW_REGISTRATION;
|
||||||
|
delete process.env.ALLOW_SOCIAL_LOGIN;
|
||||||
});
|
});
|
||||||
|
|
||||||
//TODO: This works/passes locally but http request tests fail with 404 in CI. Need to figure out why.
|
//TODO: This works/passes locally but http request tests fail with 404 in CI. Need to figure out why.
|
||||||
|
|
@ -36,8 +39,11 @@ describe.skip('GET /', () => {
|
||||||
process.env.OPENID_AUTH_URL= 'http://test-server.com';
|
process.env.OPENID_AUTH_URL= 'http://test-server.com';
|
||||||
process.env.GITHUB_CLIENT_ID = 'Test Github client Id';
|
process.env.GITHUB_CLIENT_ID = 'Test Github client Id';
|
||||||
process.env.GITHUB_CLIENT_SECRET= 'Test Github client Secret';
|
process.env.GITHUB_CLIENT_SECRET= 'Test Github client Secret';
|
||||||
|
process.env.DISCORD_CLIENT_ID = 'Test Discord client Id';
|
||||||
|
process.env.DISCORD_CLIENT_SECRET= 'Test Discord client Secret';
|
||||||
process.env.DOMAIN_SERVER = 'http://test-server.com';
|
process.env.DOMAIN_SERVER = 'http://test-server.com';
|
||||||
process.env.ALLOW_REGISTRATION = 'true';
|
process.env.ALLOW_REGISTRATION = 'true';
|
||||||
|
process.env.ALLOW_SOCIAL_LOGIN = 'true';
|
||||||
|
|
||||||
const response = await request(app).get('/');
|
const response = await request(app).get('/');
|
||||||
|
|
||||||
|
|
@ -49,8 +55,10 @@ describe.skip('GET /', () => {
|
||||||
openidLabel: 'Test OpenID',
|
openidLabel: 'Test OpenID',
|
||||||
openidImageUrl: 'http://test-server.com',
|
openidImageUrl: 'http://test-server.com',
|
||||||
githubLoginEnabled: true,
|
githubLoginEnabled: true,
|
||||||
|
discordLoginEnabled: true,
|
||||||
serverDomain: 'http://test-server.com',
|
serverDomain: 'http://test-server.com',
|
||||||
registrationEnabled: 'true',
|
registrationEnabled: 'true',
|
||||||
|
socialLoginEnabled: 'true',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,24 @@ router.get('/', async function (req, res) {
|
||||||
const openidLabel = process.env.OPENID_BUTTON_LABEL || 'Login with OpenID';
|
const openidLabel = process.env.OPENID_BUTTON_LABEL || 'Login with OpenID';
|
||||||
const openidImageUrl = process.env.OPENID_IMAGE_URL;
|
const openidImageUrl = process.env.OPENID_IMAGE_URL;
|
||||||
const githubLoginEnabled = !!process.env.GITHUB_CLIENT_ID && !!process.env.GITHUB_CLIENT_SECRET;
|
const githubLoginEnabled = !!process.env.GITHUB_CLIENT_ID && !!process.env.GITHUB_CLIENT_SECRET;
|
||||||
|
const discordLoginEnabled = !!process.env.DISCORD_CLIENT_ID && !!process.env.DISCORD_CLIENT_SECRET;
|
||||||
const serverDomain = process.env.DOMAIN_SERVER || 'http://localhost:3080';
|
const serverDomain = process.env.DOMAIN_SERVER || 'http://localhost:3080';
|
||||||
const registrationEnabled = process.env.ALLOW_REGISTRATION === 'true';
|
const registrationEnabled = process.env.ALLOW_REGISTRATION === 'true';
|
||||||
|
const socialLoginEnabled = process.env.ALLOW_SOCIAL_LOGIN === 'true';
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
appTitle,
|
||||||
|
googleLoginEnabled,
|
||||||
|
openidLoginEnabled,
|
||||||
|
openidLabel,
|
||||||
|
openidImageUrl,
|
||||||
|
githubLoginEnabled,
|
||||||
|
discordLoginEnabled,
|
||||||
|
serverDomain,
|
||||||
|
registrationEnabled,
|
||||||
|
socialLoginEnabled
|
||||||
|
});
|
||||||
|
|
||||||
return res.status(200).send({appTitle, googleLoginEnabled, openidLoginEnabled, openidLabel, openidImageUrl, githubLoginEnabled, serverDomain, registrationEnabled});
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return res.status(500).send({error: err.message});
|
return res.status(500).send({error: err.message});
|
||||||
|
|
|
||||||
|
|
@ -115,4 +115,32 @@ router.get(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
'/discord',
|
||||||
|
passport.authenticate('discord', {
|
||||||
|
scope: ['identify', 'email'],
|
||||||
|
session: false
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
'/discord/callback',
|
||||||
|
passport.authenticate('discord', {
|
||||||
|
failureRedirect: `${domains.client}/login`,
|
||||||
|
failureMessage: true,
|
||||||
|
session: false,
|
||||||
|
scope: ['identify', 'email']
|
||||||
|
}),
|
||||||
|
(req, res) => {
|
||||||
|
const token = req.user.generateToken();
|
||||||
|
res.cookie('token', token, {
|
||||||
|
expires: new Date(Date.now() + eval(process.env.SESSION_EXPIRY)),
|
||||||
|
httpOnly: false,
|
||||||
|
secure: isProduction
|
||||||
|
});
|
||||||
|
res.redirect(domains.client);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
|
||||||
57
api/strategies/discordStrategy.js
Normal file
57
api/strategies/discordStrategy.js
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
const passport = require('passport');
|
||||||
|
const { Strategy: DiscordStrategy } = require('passport-discord');
|
||||||
|
const User = require('../models/User');
|
||||||
|
const config = require('../../config/loader');
|
||||||
|
const domains = config.domains;
|
||||||
|
|
||||||
|
const discordLogin = new DiscordStrategy(
|
||||||
|
{
|
||||||
|
clientID: process.env.DISCORD_CLIENT_ID,
|
||||||
|
clientSecret: process.env.DISCORD_CLIENT_SECRET,
|
||||||
|
callbackURL: `${domains.server}${process.env.DISCORD_CALLBACK_URL}`,
|
||||||
|
scope: ['identify', 'email'] // Request scopes
|
||||||
|
},
|
||||||
|
async (accessToken, refreshToken, profile, cb) => {
|
||||||
|
try {
|
||||||
|
const discordId = profile.id;
|
||||||
|
const email = profile.email;
|
||||||
|
|
||||||
|
const existingUser = await User.findOne({ discordId });
|
||||||
|
if (existingUser) {
|
||||||
|
return cb(null, existingUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
const userWithEmail = await User.findOne({ email });
|
||||||
|
if (userWithEmail) {
|
||||||
|
userWithEmail.discordId = discordId;
|
||||||
|
await userWithEmail.save();
|
||||||
|
return cb(null, userWithEmail);
|
||||||
|
}
|
||||||
|
|
||||||
|
let avatarURL;
|
||||||
|
if (profile.avatar) {
|
||||||
|
const format = profile.avatar.startsWith('a_') ? 'gif' : 'png';
|
||||||
|
avatarURL = `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.${format}`;
|
||||||
|
} else {
|
||||||
|
const defaultAvatarNum = Number(profile.discriminator) % 5;
|
||||||
|
avatarURL = `https://cdn.discordapp.com/embed/avatars/${defaultAvatarNum}.png`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newUser = await User.create({
|
||||||
|
provider: 'discord',
|
||||||
|
discordId,
|
||||||
|
username: profile.username,
|
||||||
|
email,
|
||||||
|
name: profile.global_name,
|
||||||
|
avatar: avatarURL
|
||||||
|
});
|
||||||
|
|
||||||
|
cb(null, newUser);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
cb(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
passport.use(discordLogin);
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import LoginForm from './LoginForm';
|
import LoginForm from './LoginForm';
|
||||||
import { useAuthContext } from '~/hooks/AuthContext';
|
import { useAuthContext } from '~/hooks/AuthContext';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
@ -7,6 +7,7 @@ import { useRecoilValue } from 'recoil';
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
import { localize } from '~/localization/Translation';
|
import { localize } from '~/localization/Translation';
|
||||||
import { useGetStartupConfig } from '@librechat/data-provider';
|
import { useGetStartupConfig } from '@librechat/data-provider';
|
||||||
|
import { GoogleIcon, OpenIDIcon, GithubIcon, DiscordIcon } from '~/components'
|
||||||
|
|
||||||
function Login() {
|
function Login() {
|
||||||
const { login, error, isAuthenticated } = useAuthContext();
|
const { login, error, isAuthenticated } = useAuthContext();
|
||||||
|
|
@ -21,6 +22,7 @@ function Login() {
|
||||||
navigate('/chat/new');
|
navigate('/chat/new');
|
||||||
}
|
}
|
||||||
}, [isAuthenticated, navigate]);
|
}, [isAuthenticated, navigate]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen flex-col items-center justify-center bg-white pt-6 sm:pt-0">
|
<div className="flex min-h-screen flex-col items-center justify-center bg-white pt-6 sm:pt-0">
|
||||||
<div className="mt-6 w-96 overflow-hidden bg-white px-6 py-4 sm:max-w-md sm:rounded-lg">
|
<div className="mt-6 w-96 overflow-hidden bg-white px-6 py-4 sm:max-w-md sm:rounded-lg">
|
||||||
|
|
@ -43,46 +45,26 @@ function Login() {
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{startupConfig?.googleLoginEnabled && (
|
{startupConfig?.socialLoginEnabled && (
|
||||||
|
<div className="relative mt-6 flex w-full items-center justify-center border border-t uppercase">
|
||||||
|
<div className="absolute bg-white px-3 text-xs">Or</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{startupConfig?.googleLoginEnabled && startupConfig?.socialLoginEnabled && (
|
||||||
<>
|
<>
|
||||||
<div className="relative mt-6 flex w-full items-center justify-center border border-t uppercase">
|
|
||||||
<div className="absolute bg-white px-3 text-xs">Or</div>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4 flex gap-x-2">
|
<div className="mt-4 flex gap-x-2">
|
||||||
<a
|
<a
|
||||||
aria-label="Login with Google"
|
aria-label="Login with Google"
|
||||||
className="justify-left flex w-full items-center space-x-3 rounded-md border border-gray-300 px-5 py-3 hover:bg-gray-50 focus:ring-2 focus:ring-violet-600 focus:ring-offset-1"
|
className="justify-left flex w-full items-center space-x-3 rounded-md border border-gray-300 px-5 py-3 hover:bg-gray-50 focus:ring-2 focus:ring-violet-600 focus:ring-offset-1"
|
||||||
href={`${startupConfig.serverDomain}/oauth/google`}
|
href={`${startupConfig.serverDomain}/oauth/google`}>
|
||||||
>
|
<GoogleIcon />
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 512 512"
|
|
||||||
id="google"
|
|
||||||
className="h-5 w-5"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill="#fbbb00"
|
|
||||||
d="M113.47 309.408 95.648 375.94l-65.139 1.378C11.042 341.211 0 299.9 0 256c0-42.451 10.324-82.483 28.624-117.732h.014L86.63 148.9l25.404 57.644c-5.317 15.501-8.215 32.141-8.215 49.456.002 18.792 3.406 36.797 9.651 53.408z"
|
|
||||||
></path>
|
|
||||||
<path
|
|
||||||
fill="#518ef8"
|
|
||||||
d="M507.527 208.176C510.467 223.662 512 239.655 512 256c0 18.328-1.927 36.206-5.598 53.451-12.462 58.683-45.025 109.925-90.134 146.187l-.014-.014-73.044-3.727-10.338-64.535c29.932-17.554 53.324-45.025 65.646-77.911h-136.89V208.176h245.899z"
|
|
||||||
></path>
|
|
||||||
<path
|
|
||||||
fill="#28b446"
|
|
||||||
d="m416.253 455.624.014.014C372.396 490.901 316.666 512 256 512c-97.491 0-182.252-54.491-225.491-134.681l82.961-67.91c21.619 57.698 77.278 98.771 142.53 98.771 28.047 0 54.323-7.582 76.87-20.818l83.383 68.262z"
|
|
||||||
></path>
|
|
||||||
<path
|
|
||||||
fill="#f14336"
|
|
||||||
d="m419.404 58.936-82.933 67.896C313.136 112.246 285.552 103.82 256 103.82c-66.729 0-123.429 42.957-143.965 102.724l-83.397-68.276h-.014C71.23 56.123 157.06 0 256 0c62.115 0 119.068 22.126 163.404 58.936z"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
<p>{localize(lang, 'com_auth_google_login')}</p>
|
<p>{localize(lang, 'com_auth_google_login')}</p>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{startupConfig?.openidLoginEnabled && (
|
{startupConfig?.openidLoginEnabled && startupConfig?.socialLoginEnabled && (
|
||||||
<>
|
<>
|
||||||
<div className="mt-4 flex gap-x-2">
|
<div className="mt-4 flex gap-x-2">
|
||||||
<a
|
<a
|
||||||
|
|
@ -93,52 +75,44 @@ function Login() {
|
||||||
{startupConfig.openidImageUrl ? (
|
{startupConfig.openidImageUrl ? (
|
||||||
<img src={startupConfig.openidImageUrl} alt="OpenID Logo" className="h-5 w-5" />
|
<img src={startupConfig.openidImageUrl} alt="OpenID Logo" className="h-5 w-5" />
|
||||||
) : (
|
) : (
|
||||||
<svg
|
<OpenIDIcon />
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 448 512"
|
|
||||||
id="openid"
|
|
||||||
className="h-5 w-5"
|
|
||||||
>
|
|
||||||
<path d="M271.5 432l-68 32C88.5 453.7 0 392.5 0 318.2c0-71.5 82.5-131 191.7-144.3v43c-71.5 12.5-124 53-124 101.3 0 51 58.5 93.3 135.7 103v-340l68-33.2v384zM448 291l-131.3-28.5 36.8-20.7c-19.5-11.5-43.5-20-70-24.8v-43c46.2 5.5 87.7 19.5 120.3 39.3l35-19.8L448 291z"></path>
|
|
||||||
</svg>
|
|
||||||
)}
|
)}
|
||||||
<p>{startupConfig.openidLabel}</p>
|
<p>{startupConfig.openidLabel}</p>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{startupConfig?.githubLoginEnabled && (
|
{startupConfig?.githubLoginEnabled && startupConfig?.socialLoginEnabled && (
|
||||||
<>
|
<>
|
||||||
<div className="relative mt-6 flex w-full items-center justify-center border border-t uppercase">
|
|
||||||
<div className="absolute bg-white px-3 text-xs">Or</div>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4 flex gap-x-2">
|
|
||||||
<a
|
|
||||||
aria-label="Login with GitHub"
|
|
||||||
className="justify-left flex w-full items-center space-x-3 rounded-md border border-gray-300 px-5 py-3 hover:bg-gray-50 focus:ring-2 focus:ring-violet-600 focus:ring-offset-1"
|
|
||||||
href={`${startupConfig.serverDomain}/oauth/github`}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
id="github"
|
|
||||||
className="h-5 w-5"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M12 0a12 12 0 0 0-3.84 23.399c.608.112.832-.256.832-.576v-2.015c-3.395.736-4.115-1.632-4.115-1.632a3.241 3.241 0 0 0-1.359-1.792c-1.104-.736.064-.736.064-.736a2.566 2.566 0 0 1 1.824 1.216a2.638 2.638 0 0 0 3.616 1.024a2.607 2.607 0 0 1 .768-1.6c-2.688-.32-5.504-1.344-5.504-5.984a4.677 4.677 0 0 1 1.216-3.168a4.383 4.383 0 0 1 .128-3.136s1.024-.32 3.36 1.216a11.66 11.66 0 0 1 6.112 0c2.336-1.536 3.36-1.216 3.36-1.216a4.354 4.354 0 0 1 .128 3.136a4.628 4.628 0 0 1 1.216 3.168c0 4.672-2.848 5.664-5.536 5.952a2.881 2.881 0 0 1 .832 2.24v3.36c0 .32.224.672.832.576A12 12 0 0 0 12 0z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<p>Login with GitHub</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
|
<div className="mt-4 flex gap-x-2">
|
||||||
|
<a
|
||||||
|
aria-label="Login with GitHub"
|
||||||
|
className="justify-left flex w-full items-center space-x-3 rounded-md border border-gray-300 px-5 py-3 hover:bg-gray-50 focus:ring-2 focus:ring-violet-600 focus:ring-offset-1"
|
||||||
|
href={`${startupConfig.serverDomain}/oauth/github`}>
|
||||||
|
<GithubIcon />
|
||||||
|
<p>Login with Github</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{startupConfig?.discordLoginEnabled && startupConfig?.socialLoginEnabled && (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<div className="mt-4 flex gap-x-2">
|
||||||
|
<a
|
||||||
|
aria-label="Login with Discord"
|
||||||
|
className="justify-left flex w-full items-center space-x-3 rounded-md border border-gray-300 px-5 py-3 hover:bg-gray-50 focus:ring-2 focus:ring-violet-600 focus:ring-offset-1"
|
||||||
|
href={`${startupConfig.serverDomain}/oauth/discord`}>
|
||||||
|
<DiscordIcon />
|
||||||
|
<p>Login with Discord</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
export default Login;
|
export default Login;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
TRegisterUser,
|
TRegisterUser,
|
||||||
useGetStartupConfig
|
useGetStartupConfig
|
||||||
} from '@librechat/data-provider';
|
} from '@librechat/data-provider';
|
||||||
|
import { GoogleIcon, OpenIDIcon, GithubIcon, DiscordIcon } from '~/components'
|
||||||
|
|
||||||
function Registration() {
|
function Registration() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
@ -283,51 +284,28 @@ function Registration() {
|
||||||
{localize(lang, 'com_auth_login')}
|
{localize(lang, 'com_auth_login')}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
{startupConfig?.googleLoginEnabled && (
|
{startupConfig?.socialLoginEnabled && (
|
||||||
|
<div className="relative mt-6 flex w-full items-center justify-center border border-t uppercase">
|
||||||
|
<div className="absolute bg-white px-3 text-xs">Or</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{startupConfig?.googleLoginEnabled && startupConfig?.socialLoginEnabled && (
|
||||||
<>
|
<>
|
||||||
<div className="relative mt-6 flex w-full items-center justify-center border border-t uppercase">
|
|
||||||
<div className="absolute bg-white px-3 text-xs">Or</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-4 flex gap-x-2">
|
<div className="mt-4 flex gap-x-2">
|
||||||
<a
|
<a
|
||||||
aria-label="Login with Google"
|
aria-label="Login with Google"
|
||||||
href={`${startupConfig.serverDomain}/oauth/google`}
|
|
||||||
className="justify-left flex w-full items-center space-x-3 rounded-md border border-gray-300 px-5 py-3 hover:bg-gray-50 focus:ring-2 focus:ring-violet-600 focus:ring-offset-1"
|
className="justify-left flex w-full items-center space-x-3 rounded-md border border-gray-300 px-5 py-3 hover:bg-gray-50 focus:ring-2 focus:ring-violet-600 focus:ring-offset-1"
|
||||||
>
|
href={`${startupConfig.serverDomain}/oauth/google`}>
|
||||||
<svg
|
<GoogleIcon />
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 512 512"
|
|
||||||
id="google"
|
|
||||||
className="h-5 w-5"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill="#fbbb00"
|
|
||||||
d="M113.47 309.408 95.648 375.94l-65.139 1.378C11.042 341.211 0 299.9 0 256c0-42.451 10.324-82.483 28.624-117.732h.014L86.63 148.9l25.404 57.644c-5.317 15.501-8.215 32.141-8.215 49.456.002 18.792 3.406 36.797 9.651 53.408z"
|
|
||||||
></path>
|
|
||||||
<path
|
|
||||||
fill="#518ef8"
|
|
||||||
d="M507.527 208.176C510.467 223.662 512 239.655 512 256c0 18.328-1.927 36.206-5.598 53.451-12.462 58.683-45.025 109.925-90.134 146.187l-.014-.014-73.044-3.727-10.338-64.535c29.932-17.554 53.324-45.025 65.646-77.911h-136.89V208.176h245.899z"
|
|
||||||
></path>
|
|
||||||
<path
|
|
||||||
fill="#28b446"
|
|
||||||
d="m416.253 455.624.014.014C372.396 490.901 316.666 512 256 512c-97.491 0-182.252-54.491-225.491-134.681l82.961-67.91c21.619 57.698 77.278 98.771 142.53 98.771 28.047 0 54.323-7.582 76.87-20.818l83.383 68.262z"
|
|
||||||
></path>
|
|
||||||
<path
|
|
||||||
fill="#f14336"
|
|
||||||
d="m419.404 58.936-82.933 67.896C313.136 112.246 285.552 103.82 256 103.82c-66.729 0-123.429 42.957-143.965 102.724l-83.397-68.276h-.014C71.23 56.123 157.06 0 256 0c62.115 0 119.068 22.126 163.404 58.936z"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
<p>{localize(lang, 'com_auth_google_login')}</p>
|
<p>{localize(lang, 'com_auth_google_login')}</p>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{startupConfig?.openidLoginEnabled && (
|
{startupConfig?.openidLoginEnabled && startupConfig?.socialLoginEnabled && (
|
||||||
<>
|
<>
|
||||||
<div className="relative mt-6 flex w-full items-center justify-center border border-t uppercase">
|
|
||||||
<div className="absolute bg-white px-3 text-xs">Or</div>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4 flex gap-x-2">
|
<div className="mt-4 flex gap-x-2">
|
||||||
<a
|
<a
|
||||||
aria-label="Login with OpenID"
|
aria-label="Login with OpenID"
|
||||||
|
|
@ -337,48 +315,42 @@ function Registration() {
|
||||||
{startupConfig.openidImageUrl ? (
|
{startupConfig.openidImageUrl ? (
|
||||||
<img src={startupConfig.openidImageUrl} alt="OpenID Logo" className="h-5 w-5" />
|
<img src={startupConfig.openidImageUrl} alt="OpenID Logo" className="h-5 w-5" />
|
||||||
) : (
|
) : (
|
||||||
<svg
|
<OpenIDIcon />
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 448 512"
|
|
||||||
id="openid"
|
|
||||||
className="h-5 w-5"
|
|
||||||
>
|
|
||||||
<path d="M271.5 432l-68 32C88.5 453.7 0 392.5 0 318.2c0-71.5 82.5-131 191.7-144.3v43c-71.5 12.5-124 53-124 101.3 0 51 58.5 93.3 135.7 103v-340l68-33.2v384zM448 291l-131.3-28.5 36.8-20.7c-19.5-11.5-43.5-20-70-24.8v-43c46.2 5.5 87.7 19.5 120.3 39.3l35-19.8L448 291z"></path>
|
|
||||||
</svg>
|
|
||||||
)}
|
)}
|
||||||
<p>{startupConfig.openidLabel}</p>
|
<p>{startupConfig.openidLabel}</p>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{startupConfig?.githubLoginEnabled && (
|
{startupConfig?.githubLoginEnabled && startupConfig?.socialLoginEnabled && (
|
||||||
<>
|
<>
|
||||||
<div className="relative mt-6 flex w-full items-center justify-center border border-t uppercase">
|
|
||||||
<div className="absolute bg-white px-3 text-xs">Or</div>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4 flex gap-x-2">
|
|
||||||
<a
|
|
||||||
aria-label="Login with GitHub"
|
|
||||||
href={`${startupConfig.serverDomain}/oauth/github`}
|
|
||||||
className="justify-left flex w-full items-center space-x-3 rounded-md border border-gray-300 px-5 py-3 hover:bg-gray-50 focus:ring-2 focus:ring-violet-600 focus:ring-offset-1"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
id="github"
|
|
||||||
className="h-5 w-5"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M12 0a12 12 0 0 0-3.84 23.399c.608.112.832-.256.832-.576v-2.015c-3.395.736-4.115-1.632-4.115-1.632a3.241 3.241 0 0 0-1.359-1.792c-1.104-.736.064-.736.064-.736a2.566 2.566 0 0 1 1.824 1.216a2.638 2.638 0 0 0 3.616 1.024a2.607 2.607 0 0 1 .768-1.6c-2.688-.32-5.504-1.344-5.504-5.984a4.677 4.677 0 0 1 1.216-3.168a4.383 4.383 0 0 1 .128-3.136s1.024-.32 3.36 1.216a11.66 11.66 0 0 1 6.112 0c2.336-1.536 3.36-1.216 3.36-1.216a4.354 4.354 0 0 1 .128 3.136a4.628 4.628 0 0 1 1.216 3.168c0 4.672-2.848 5.664-5.536 5.952a2.881 2.881 0 0 1 .832 2.24v3.36c0 .32.224.672.832.576A12 12 0 0 0 12 0z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<p>Login with GitHub</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
|
<div className="mt-4 flex gap-x-2">
|
||||||
|
<a
|
||||||
|
aria-label="Login with GitHub"
|
||||||
|
|
||||||
|
className="justify-left flex w-full items-center space-x-3 rounded-md border border-gray-300 px-5 py-3 hover:bg-gray-50 focus:ring-2 focus:ring-violet-600 focus:ring-offset-1"
|
||||||
|
href={`${startupConfig.serverDomain}/oauth/github`}>
|
||||||
|
<GithubIcon />
|
||||||
|
<p>Login with Github</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{startupConfig?.discordLoginEnabled && startupConfig?.socialLoginEnabled && (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<div className="mt-4 flex gap-x-2">
|
||||||
|
<a
|
||||||
|
aria-label="Login with Discord"
|
||||||
|
className="justify-left flex w-full items-center space-x-3 rounded-md border border-gray-300 px-5 py-3 hover:bg-gray-50 focus:ring-2 focus:ring-violet-600 focus:ring-offset-1"
|
||||||
|
href={`${startupConfig.serverDomain}/oauth/discord`}>
|
||||||
|
<DiscordIcon />
|
||||||
|
<p>Login with Discord</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,9 @@ const setup = ({
|
||||||
openidLabel: 'Test OpenID',
|
openidLabel: 'Test OpenID',
|
||||||
openidImageUrl: 'http://test-server.com',
|
openidImageUrl: 'http://test-server.com',
|
||||||
githubLoginEnabled: true,
|
githubLoginEnabled: true,
|
||||||
|
discordLoginEnabled: true,
|
||||||
registrationEnabled: true,
|
registrationEnabled: true,
|
||||||
|
socialLoginEnabled: true,
|
||||||
serverDomain: 'mock-server'
|
serverDomain: 'mock-server'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,9 @@ const setup = ({
|
||||||
openidLabel: 'Test OpenID',
|
openidLabel: 'Test OpenID',
|
||||||
openidImageUrl: 'http://test-server.com',
|
openidImageUrl: 'http://test-server.com',
|
||||||
githubLoginEnabled: true,
|
githubLoginEnabled: true,
|
||||||
|
discordLoginEnabled: true,
|
||||||
registrationEnabled: true,
|
registrationEnabled: true,
|
||||||
|
socialLoginEnabled: true,
|
||||||
serverDomain: 'mock-server'
|
serverDomain: 'mock-server'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
client/src/components/svg/DiscordIcon.jsx
Normal file
12
client/src/components/svg/DiscordIcon.jsx
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function DiscordIcon() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" id="discord" className="h-6 w-6"
|
||||||
|
>
|
||||||
|
<circle cx="512" cy="512" r="512" fill="#5865f2"/>
|
||||||
|
<path fill="#fff" d="M689.43 349a422.21 422.21 0 0 0-104.22-32.32 1.58 1.58 0 0 0-1.68.79 294.11 294.11 0 0 0-13 26.66 389.78 389.78 0 0 0-117.05 0 269.75 269.75 0 0 0-13.18-26.66 1.64 1.64 0 0 0-1.68-.79A421 421 0 0 0 334.44 349a1.49 1.49 0 0 0-.69.59c-66.37 99.17-84.55 195.9-75.63 291.41a1.76 1.76 0 0 0 .67 1.2 424.58 424.58 0 0 0 127.85 64.63 1.66 1.66 0 0 0 1.8-.59 303.45 303.45 0 0 0 26.15-42.54 1.62 1.62 0 0 0-.89-2.25 279.6 279.6 0 0 1-39.94-19 1.64 1.64 0 0 1-.16-2.72c2.68-2 5.37-4.1 7.93-6.22a1.58 1.58 0 0 1 1.65-.22c83.79 38.26 174.51 38.26 257.31 0a1.58 1.58 0 0 1 1.68.2c2.56 2.11 5.25 4.23 8 6.24a1.64 1.64 0 0 1-.14 2.72 262.37 262.37 0 0 1-40 19 1.63 1.63 0 0 0-.87 2.28 340.72 340.72 0 0 0 26.13 42.52 1.62 1.62 0 0 0 1.8.61 423.17 423.17 0 0 0 128-64.63 1.64 1.64 0 0 0 .67-1.18c10.68-110.44-17.88-206.38-75.7-291.42a1.3 1.3 0 0 0-.63-.63zM427.09 582.85c-25.23 0-46-23.16-46-51.6s20.38-51.6 46-51.6c25.83 0 46.42 23.36 46 51.6.02 28.44-20.37 51.6-46 51.6zm170.13 0c-25.23 0-46-23.16-46-51.6s20.38-51.6 46-51.6c25.83 0 46.42 23.36 46 51.6.01 28.44-20.17 51.6-46 51.6z"></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
12
client/src/components/svg/GithubIcon.jsx
Normal file
12
client/src/components/svg/GithubIcon.jsx
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function GithubIcon() {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="none">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M12 0a12 12 0 0 0-3.84 23.399c.608.112.832-.256.832-.576v-2.015c-3.395.736-4.115-1.632-4.115-1.632a3.241 3.241 0 0 0-1.359-1.792c-1.104-.736.064-.736.064-.736a2.566 2.566 0 0 1 1.824 1.216a2.638 2.638 0 0 0 3.616 1.024a2.607 2.607 0 0 1 .768-1.6c-2.688-.32-5.504-1.344-5.504-5.984a4.677 4.677 0 0 1 1.216-3.168a4.383 4.383 0 0 1 .128-3.136s1.024-.32 3.36 1.216a11.66 11.66 0 0 1 6.112 0c2.336-1.536 3.36-1.216 3.36-1.216a4.354 4.354 0 0 1 .128 3.136a4.628 4.628 0 0 1 1.216 3.168c0 4.672-2.848 5.664-5.536 5.952a2.881 2.881 0 0 1 .832 2.24v3.36c0 .32.224.672.832.576A12 12 0 0 0 12 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
29
client/src/components/svg/GoogleIcon.jsx
Normal file
29
client/src/components/svg/GoogleIcon.jsx
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function GoogleIcon() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
id="google"
|
||||||
|
className="h-5 w-5"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="#fbbb00"
|
||||||
|
d="M113.47 309.408 95.648 375.94l-65.139 1.378C11.042 341.211 0 299.9 0 256c0-42.451 10.324-82.483 28.624-117.732h.014L86.63 148.9l25.404 57.644c-5.317 15.501-8.215 32.141-8.215 49.456.002 18.792 3.406 36.797 9.651 53.408z"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
fill="#518ef8"
|
||||||
|
d="M507.527 208.176C510.467 223.662 512 239.655 512 256c0 18.328-1.927 36.206-5.598 53.451-12.462 58.683-45.025 109.925-90.134 146.187l-.014-.014-73.044-3.727-10.338-64.535c29.932-17.554 53.324-45.025 65.646-77.911h-136.89V208.176h245.899z"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
fill="#28b446"
|
||||||
|
d="m416.253 455.624.014.014C372.396 490.901 316.666 512 256 512c-97.491 0-182.252-54.491-225.491-134.681l82.961-67.91c21.619 57.698 77.278 98.771 142.53 98.771 28.047 0 54.323-7.582 76.87-20.818l83.383 68.262z"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
fill="#f14336"
|
||||||
|
d="m419.404 58.936-82.933 67.896C313.136 112.246 285.552 103.82 256 103.82c-66.729 0-123.429 42.957-143.965 102.724l-83.397-68.276h-.014C71.23 56.123 157.06 0 256 0c62.115 0 119.068 22.126 163.404 58.936z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
11
client/src/components/svg/OpenIDIcon.jsx
Normal file
11
client/src/components/svg/OpenIDIcon.jsx
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function OpenIDIcon() {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" id="openid" className="h-5 w-5">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M271.5 432l-68 32C88.5 453.7 0 392.5 0 318.2c0-71.5 82.5-131 191.7-144.3v43c-71.5 12.5-124 53-124 101.3 0 51 58.5 93.3 135.7 103v-340l68-33.2v384zM448 291l-131.3-28.5 36.8-20.7c-19.5-11.5-43.5-20-70-24.8v-43c46.2 5.5 87.7 19.5 120.3 39.3l35-19.8L448 291z"></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -5,3 +5,7 @@ export { default as CogIcon } from './CogIcon';
|
||||||
export { default as Spinner } from './Spinner';
|
export { default as Spinner } from './Spinner';
|
||||||
export { default as MessagesSquared } from './MessagesSquared';
|
export { default as MessagesSquared } from './MessagesSquared';
|
||||||
export { default as StopGeneratingIcon } from './StopGeneratingIcon';
|
export { default as StopGeneratingIcon } from './StopGeneratingIcon';
|
||||||
|
export { default as GoogleIcon } from './GoogleIcon';
|
||||||
|
export { default as OpenIDIcon } from './OpenIDIcon';
|
||||||
|
export { default as GithubIcon } from './GithubIcon';
|
||||||
|
export { default as DiscordIcon } from './DiscordIcon';
|
||||||
|
|
@ -77,9 +77,29 @@ OPENID_CALLBACK_URL=/oauth/openid/callback
|
||||||
5. Remove the Active checkbox in the Webhook section
|
5. Remove the Active checkbox in the Webhook section
|
||||||
6. Save changes and generate a Client Secret
|
6. Save changes and generate a Client Secret
|
||||||
7. In the Permissions & events tab select, open the Account Permissions and set Email addresses to Read-only
|
7. In the Permissions & events tab select, open the Account Permissions and set Email addresses to Read-only
|
||||||
8. Put the Client ID and Client Secret in the .env file
|
8. Put the Client ID and Client Secret in the .env file:
|
||||||
|
```
|
||||||
|
GITHUB_CLIENT_ID=your_client_id
|
||||||
|
GITHUB_CLIENT_SECRET=your_client_secret
|
||||||
|
GITHUB_CALLBACK_URL=/oauth/github/callback # this should be the same for everyone
|
||||||
|
```
|
||||||
9. Save the .env file
|
9. Save the .env file
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to Set Up Discord Authentication
|
||||||
|
|
||||||
|
1. Go to [Discord Developer Portal](https://discord.com/developers)
|
||||||
|
2. Create a new Application and give it a name
|
||||||
|
4. In the OAuth2 general settings add a redirect URL and set it as "[Your DOMAIN_CLIENT](https://github.com/danny-avila/LibreChat/blob/main/.env.example#L219)/oauth/discord/callback" (example: http://localhost:3080/oauth/discord/callback)
|
||||||
|
5. in the Default Authorization Link set applications.commands
|
||||||
|
6. Save changes and reset the Client Secret
|
||||||
|
7. Put the Client ID and Client Secret in the .env file:
|
||||||
|
```
|
||||||
|
DISCORD_CLIENT_ID=your_client_id
|
||||||
|
DISCORD_CLIENT_SECRET=your_client_secret
|
||||||
|
DISCORD_CALLBACK_URL=/oauth/discord/callback # this should be the same for everyone
|
||||||
|
```
|
||||||
|
8. Save the .env file
|
||||||
---
|
---
|
||||||
## **Email and Password Reset**
|
## **Email and Password Reset**
|
||||||
|
|
||||||
|
|
|
||||||
17
package-lock.json
generated
17
package-lock.json
generated
|
|
@ -17,6 +17,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"passport": "^0.6.0",
|
"passport": "^0.6.0",
|
||||||
|
"passport-discord": "^0.1.4",
|
||||||
"passport-github2": "^0.1.12"
|
"passport-github2": "^0.1.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -20404,6 +20405,14 @@
|
||||||
"url": "https://github.com/sponsors/jaredhanson"
|
"url": "https://github.com/sponsors/jaredhanson"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/passport-discord": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/passport-discord/-/passport-discord-0.1.4.tgz",
|
||||||
|
"integrity": "sha512-VJWPYqSOmh7SaCLw/C+k1ZqCzJnn2frrmQRx1YrcPJ3MQ+Oa31XclbbmqFICSvl8xv3Fqd6YWQ4H4p1MpIN9rA==",
|
||||||
|
"dependencies": {
|
||||||
|
"passport-oauth2": "^1.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/passport-facebook": {
|
"node_modules/passport-facebook": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-3.0.0.tgz",
|
||||||
|
|
@ -41105,6 +41114,14 @@
|
||||||
"utils-merge": "^1.0.1"
|
"utils-merge": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"passport-discord": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/passport-discord/-/passport-discord-0.1.4.tgz",
|
||||||
|
"integrity": "sha512-VJWPYqSOmh7SaCLw/C+k1ZqCzJnn2frrmQRx1YrcPJ3MQ+Oa31XclbbmqFICSvl8xv3Fqd6YWQ4H4p1MpIN9rA==",
|
||||||
|
"requires": {
|
||||||
|
"passport-oauth2": "^1.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"passport-facebook": {
|
"passport-facebook": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-3.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"passport": "^0.6.0",
|
"passport": "^0.6.0",
|
||||||
|
"passport-discord": "^0.1.4",
|
||||||
"passport-github2": "^0.1.12"
|
"passport-github2": "^0.1.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -252,8 +252,10 @@ export type TStartupConfig = {
|
||||||
githubLoginEnabled: boolean;
|
githubLoginEnabled: boolean;
|
||||||
openidLabel: string;
|
openidLabel: string;
|
||||||
openidImageUrl: string;
|
openidImageUrl: string;
|
||||||
|
discordLoginEnabled: boolean;
|
||||||
serverDomain: string;
|
serverDomain: string;
|
||||||
registrationEnabled: boolean;
|
registrationEnabled: boolean;
|
||||||
|
socialLoginEnabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TRefreshTokenResponse = {
|
export type TRefreshTokenResponse = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue