OAuthProviders

This commit is contained in:
Erik 2022-11-27 23:19:33 +02:00
parent e4ee428a14
commit 820e05ba2a
Signed by: Navy.gif
GPG Key ID: 811EC0CD80E7E5FB
2 changed files with 56 additions and 5 deletions

View File

@ -58,6 +58,7 @@ class Server extends EventEmitter {
this.registrationEnabled = options.registrationEnabled;
// Only lets people with valid registration urls to register
this.requireCodeForRegister = options.requireCodeForRegister;
this.OAuthProviders = options.OAuthProviders;
this.server = null;
this.app = express();
@ -194,10 +195,15 @@ class Server extends EventEmitter {
const { DISCORD_ID, DISCORD_SECRET } = process.env;
const { callbackURL, discord } = this._options;
const authParams = {
clientID: DISCORD_ID,
clientSecret: DISCORD_SECRET,
callbackURL: this.baseURL + callbackURL + '/discord',
scope: discord.scope,
version: discord.version
};
this.authenticator.addStrategy('discord', new DiscordStrategy({
clientID: DISCORD_ID, clientSecret: DISCORD_SECRET, callbackURL: this.baseURL + callbackURL + '/discord', scope: discord.scope, version: discord.version
}, async (accessToken, refreshToken, profile, callback) => {
this.authenticator.addStrategy('discord', new DiscordStrategy(authParams, async (accessToken, refreshToken, profile, callback) => {
this.logger.info(`${profile.username} (${profile.id}) is logging in.`);
// We don't need this here
delete profile.accessToken;
@ -205,7 +211,7 @@ class Server extends EventEmitter {
let err = null;
if (!user) err = new Error('No such user');
callback(err, user);
}), { successRedirect: '/home' });
}), { successRedirect: '/home', authParams });
this.authenticator.addStrategy('local', new LocalStrategy(async (username, password, callback) => {
const user = await this.userDatabase.findUser(username);
@ -222,6 +228,16 @@ class Server extends EventEmitter {
}
get clientSettings () {
return {
registrationEnabled: this.registrationEnabled,
requireCodeForRegister: this.requireCodeForRegister,
OAuthProviders: this.OAuthProviders.map(provider => {
return { name: provider.name, icon: provider.iconURL, url: `/api/user/connect/${provider.name.toLowerCase()}` };
})
};
}
}
process.once('message', (msg) => {

View File

@ -1,3 +1,4 @@
/* eslint-disable camelcase */
const { AbstractUserDatabase } = require('../interfaces');
const { Util } = require('../../util');
@ -5,6 +6,8 @@ const session = require('express-session');
const MongoStore = require('connect-mongo');
const Passport = require('passport');
const OAuthLinks = {};
/**
* Takes care of sessions and authentication
*
@ -61,6 +64,14 @@ class Authenticator {
callback(null, user);
});
// Stores parameters for OAuth requests, such as client id, secret, scope etc
this.OAuthParams = {};
server.OAuthProviders.forEach(provider => {
const providerName = provider.name.toLowerCase();
OAuthLinks[providerName] = provider.authoriseURL;
OAuthLinks[providerName +'Token'] = provider.tokenURL;
});
}
/**
@ -71,9 +82,10 @@ class Authenticator {
* @param {object} [{ failureRedirect = '/api/login/fail', successRedirect = '/home' }={}]
* @memberof Authenticator
*/
addStrategy (name, strategy, { failureRedirect = '/api/login/fail', successRedirect } = {}) {
addStrategy (name, strategy, { failureRedirect = '/api/login/fail', successRedirect, authParams } = {}) {
this.logger.info(`Adding ${name} authentication strategy`);
this.passport.use(name, strategy);
this.OAuthParams[name] = authParams || null;
// Quick access getter to get the middleware for authenticating
Object.defineProperty(this, name, {
get: () => {
@ -171,6 +183,29 @@ class Authenticator {
}
getOAuthLink (service, { ...rest } = {}) {
service = service.toLowerCase();
const link = OAuthLinks[service];
const OAuthParams = this.OAuthParams[service];
const params = {
response_type: 'code',
client_id: OAuthParams.clientID,
redirect_uri: OAuthParams.callbackURL,
scope: OAuthParams.scope.join(' '),
state: null,
...rest
};
return `${link}?${Object.entries(params).filter(([ , v ]) => Boolean(v)).map(([ k, v ]) => `${k}=${v}`).join('&')}`;
}
getOAuthTokenParams (service) {
service = service.toLowerCase();
return {
link: OAuthLinks[service + 'Token'],
...this.OAuthParams[service]
};
}
}
module.exports = Authenticator;