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:
Marco Beretta 2023-07-11 23:17:58 +02:00 committed by GitHub
parent c17c1488ca
commit 747e087cf5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 328 additions and 144 deletions

View file

@ -75,6 +75,11 @@ const userSchema = mongoose.Schema(
unique: true,
sparse: true
},
discordId: {
type: String,
unique: true,
sparse: true
},
plugins: {
type: Array,
default: []

View file

@ -45,6 +45,9 @@ config.validate(); // Validate the config
if (process.env.GITHUB_CLIENT_ID && process.env.GITHUB_CLIENT_SECRET) {
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 &&
process.env.OPENID_ISSUER && process.env.OPENID_SCOPE &&
process.env.OPENID_SESSION_SECRET) {

View file

@ -16,8 +16,11 @@ afterEach(() => {
delete process.env.OPENID_AUTH_URL;
delete process.env.GITHUB_CLIENT_ID;
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.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.
@ -36,8 +39,11 @@ describe.skip('GET /', () => {
process.env.OPENID_AUTH_URL= 'http://test-server.com';
process.env.GITHUB_CLIENT_ID = 'Test Github client Id';
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.ALLOW_REGISTRATION = 'true';
process.env.ALLOW_SOCIAL_LOGIN = 'true';
const response = await request(app).get('/');
@ -49,8 +55,10 @@ describe.skip('GET /', () => {
openidLabel: 'Test OpenID',
openidImageUrl: 'http://test-server.com',
githubLoginEnabled: true,
discordLoginEnabled: true,
serverDomain: 'http://test-server.com',
registrationEnabled: 'true',
socialLoginEnabled: 'true',
});
});
});

View file

@ -12,10 +12,24 @@ router.get('/', async function (req, res) {
const openidLabel = process.env.OPENID_BUTTON_LABEL || 'Login with OpenID';
const openidImageUrl = process.env.OPENID_IMAGE_URL;
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 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) {
console.error(err);
return res.status(500).send({error: err.message});

View file

@ -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;

View 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);

View file

@ -33,7 +33,7 @@ const githubLogin = new GitHubStrategy(
email,
emailVerified: profile.emails[0].verified,
name: profile.displayName,
avatar: profile.photos[0].value
avatar: profile.photos[0].value
}).save();
cb(null, newUser);