Add LTI support, and tidy OIDC code
parent
d1039411a4
commit
e8731a37e5
|
|
@ -1,26 +1,38 @@
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
{
|
|
||||||
// oAuth2 conf
|
|
||||||
/* auth :
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Auth conf
|
||||||
|
/*
|
||||||
|
auth :
|
||||||
|
{
|
||||||
|
lti :
|
||||||
|
{
|
||||||
|
consumerKey : 'key',
|
||||||
|
consumerSecret : 'secret'
|
||||||
|
},
|
||||||
|
oidc:
|
||||||
|
{
|
||||||
// The issuer URL for OpenID Connect discovery
|
// The issuer URL for OpenID Connect discovery
|
||||||
// The OpenID Provider Configuration Document
|
// The OpenID Provider Configuration Document
|
||||||
// could be discovered on:
|
// could be discovered on:
|
||||||
// issuerURL + '/.well-known/openid-configuration'
|
// issuerURL + '/.well-known/openid-configuration'
|
||||||
|
|
||||||
// issuerURL : 'https://example.com',
|
issuerURL : 'https://example.com',
|
||||||
// clientOptions :
|
clientOptions :
|
||||||
// {
|
{
|
||||||
client_id : '',
|
client_id : '',
|
||||||
client_secret : '',
|
client_secret : '',
|
||||||
scope : 'openid email profile',
|
scope : 'openid email profile',
|
||||||
// where client.example.com is your multiparty meeting server
|
// where client.example.com is your multiparty meeting server
|
||||||
redirect_uri : 'https://client.example.com/auth/callback'
|
redirect_uri : 'https://client.example.com/auth/callback'
|
||||||
}
|
}
|
||||||
},*/
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
redisOptions: {}
|
redisOptions: {}
|
||||||
// session cookie secret
|
// session cookie secret
|
||||||
cookieSecret : 'T0P-S3cR3t_cook!e',
|
cookieSecret : 'T0P-S3cR3t_cook!e',
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,11 @@
|
||||||
"express-session": "^1.17.0",
|
"express-session": "^1.17.0",
|
||||||
"express-socket.io-session": "^1.3.5",
|
"express-socket.io-session": "^1.3.5",
|
||||||
"helmet": "^3.21.2",
|
"helmet": "^3.21.2",
|
||||||
|
"ims-lti": "^3.0.2",
|
||||||
"mediasoup": "^3.0.12",
|
"mediasoup": "^3.0.12",
|
||||||
"openid-client": "^3.7.3",
|
"openid-client": "^3.7.3",
|
||||||
"passport": "^0.4.0",
|
"passport": "^0.4.0",
|
||||||
|
"passport-lti": "0.0.7",
|
||||||
"redis": "^2.8.0",
|
"redis": "^2.8.0",
|
||||||
"socket.io": "^2.3.0",
|
"socket.io": "^2.3.0",
|
||||||
"spdy": "^4.0.1"
|
"spdy": "^4.0.1"
|
||||||
|
|
|
||||||
134
server/server.js
134
server/server.js
|
|
@ -17,14 +17,17 @@ const Room = require('./lib/Room');
|
||||||
const Peer = require('./lib/Peer');
|
const Peer = require('./lib/Peer');
|
||||||
const base64 = require('base-64');
|
const base64 = require('base-64');
|
||||||
const helmet = require('helmet');
|
const helmet = require('helmet');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
loginHelper,
|
loginHelper,
|
||||||
logoutHelper
|
logoutHelper
|
||||||
} = require('./httpHelper');
|
} = require('./httpHelper');
|
||||||
// auth
|
// auth
|
||||||
const passport = require('passport');
|
const passport = require('passport');
|
||||||
|
const LTIStrategy = require('passport-lti');
|
||||||
|
const imsLti = require('ims-lti');
|
||||||
const redis = require('redis');
|
const redis = require('redis');
|
||||||
const client = redis.createClient(config.redisOptions);
|
const redisClient = redis.createClient(config.redisOptions);
|
||||||
const { Issuer, Strategy } = require('openid-client');
|
const { Issuer, Strategy } = require('openid-client');
|
||||||
const expressSession = require('express-session');
|
const expressSession = require('express-session');
|
||||||
const RedisStore = require('connect-redis')(expressSession);
|
const RedisStore = require('connect-redis')(expressSession);
|
||||||
|
|
@ -87,7 +90,7 @@ const session = expressSession({
|
||||||
name : config.cookieName,
|
name : config.cookieName,
|
||||||
resave : true,
|
resave : true,
|
||||||
saveUninitialized : true,
|
saveUninitialized : true,
|
||||||
store : new RedisStore({ client }),
|
store : new RedisStore({ client: redisClient }),
|
||||||
cookie : {
|
cookie : {
|
||||||
secure : true,
|
secure : true,
|
||||||
httpOnly : true,
|
httpOnly : true,
|
||||||
|
|
@ -112,38 +115,16 @@ let io;
|
||||||
let oidcClient;
|
let oidcClient;
|
||||||
let oidcStrategy;
|
let oidcStrategy;
|
||||||
|
|
||||||
const auth = config.auth;
|
|
||||||
|
|
||||||
async function run()
|
async function run()
|
||||||
{
|
{
|
||||||
if (
|
if ( typeof(config.auth) === 'undefined' )
|
||||||
typeof(auth) !== 'undefined' &&
|
|
||||||
typeof(auth.issuerURL) !== 'undefined' &&
|
|
||||||
typeof(auth.clientOptions) !== 'undefined'
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
Issuer.discover(auth.issuerURL).then(async (oidcIssuer) =>
|
logger.warn('Auth is not configured properly!');
|
||||||
{
|
|
||||||
// Setup authentication
|
|
||||||
await setupAuth(oidcIssuer);
|
|
||||||
|
|
||||||
// Run a mediasoup Worker.
|
|
||||||
await runMediasoupWorkers();
|
|
||||||
|
|
||||||
// Run HTTPS server.
|
|
||||||
await runHttpsServer();
|
|
||||||
|
|
||||||
// Run WebSocketServer.
|
|
||||||
await runWebSocketServer();
|
|
||||||
})
|
|
||||||
.catch((err) =>
|
|
||||||
{
|
|
||||||
logger.error(err);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.error('Auth is not configure properly!');
|
await setupAuth();
|
||||||
|
}
|
||||||
|
|
||||||
// Run a mediasoup Worker.
|
// Run a mediasoup Worker.
|
||||||
await runMediasoupWorkers();
|
await runMediasoupWorkers();
|
||||||
|
|
@ -153,7 +134,6 @@ async function run()
|
||||||
|
|
||||||
// Run WebSocketServer.
|
// Run WebSocketServer.
|
||||||
await runWebSocketServer();
|
await runWebSocketServer();
|
||||||
}
|
|
||||||
|
|
||||||
// Log rooms status every 30 seconds.
|
// Log rooms status every 30 seconds.
|
||||||
setInterval(() =>
|
setInterval(() =>
|
||||||
|
|
@ -174,16 +154,67 @@ async function run()
|
||||||
}, 10000);
|
}, 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setupAuth(oidcIssuer)
|
function setupLTI(ltiConfig)
|
||||||
{
|
{
|
||||||
oidcClient = new oidcIssuer.Client(auth.clientOptions);
|
|
||||||
|
// Add redis nonce store
|
||||||
|
ltiConfig.nonceStore = new imsLti.Stores.RedisStore(ltiConfig.consumerKey, redisClient);
|
||||||
|
ltiConfig.passReqToCallback= true;
|
||||||
|
|
||||||
|
const ltiStrategy = new LTIStrategy(
|
||||||
|
ltiConfig,
|
||||||
|
function(req, lti, done)
|
||||||
|
{
|
||||||
|
// LTI launch parameters
|
||||||
|
if (lti)
|
||||||
|
{
|
||||||
|
const user = {};
|
||||||
|
|
||||||
|
if (lti.user_id && lti.custom_room)
|
||||||
|
{
|
||||||
|
user.id = lti.user_id;
|
||||||
|
user._lti = lti;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lti.custom_room)
|
||||||
|
{
|
||||||
|
user.room = lti.custom_room;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user.room = '';
|
||||||
|
}
|
||||||
|
if (lti.lis_person_name_full)
|
||||||
|
{
|
||||||
|
user.displayName=lti.lis_person_name_full;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform local authentication if necessary
|
||||||
|
return done(null, user);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return done('LTI error');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
passport.use('lti', ltiStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupOIDC(oidcIssuer)
|
||||||
|
{
|
||||||
|
|
||||||
|
oidcClient = new oidcIssuer.Client(config.auth.oidc.clientOptions);
|
||||||
|
|
||||||
// ... any authorization request parameters go here
|
// ... any authorization request parameters go here
|
||||||
// client_id defaults to client.client_id
|
// client_id defaults to client.client_id
|
||||||
// redirect_uri defaults to client.redirect_uris[0]
|
// redirect_uri defaults to client.redirect_uris[0]
|
||||||
// response type defaults to client.response_types[0], then 'code'
|
// response type defaults to client.response_types[0], then 'code'
|
||||||
// scope defaults to 'openid'
|
// scope defaults to 'openid'
|
||||||
const params = auth.clientOptions;
|
const params = config.auth.oidc.clientOptions;
|
||||||
|
|
||||||
// optional, defaults to false, when true req is passed as a first
|
// optional, defaults to false, when true req is passed as a first
|
||||||
// argument to verify fn
|
// argument to verify fn
|
||||||
|
|
@ -257,6 +288,31 @@ async function setupAuth(oidcIssuer)
|
||||||
|
|
||||||
passport.use('oidc', oidcStrategy);
|
passport.use('oidc', oidcStrategy);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setupAuth()
|
||||||
|
{
|
||||||
|
// LTI
|
||||||
|
if (
|
||||||
|
typeof(config.auth.lti) !== 'undefined' &&
|
||||||
|
typeof(config.auth.lti.consumerKey) !== 'undefined' &&
|
||||||
|
typeof(config.auth.lti.consumerSecret) !== 'undefined'
|
||||||
|
) setupLTI(config.auth.lti);
|
||||||
|
|
||||||
|
// OIDC
|
||||||
|
if (
|
||||||
|
typeof(config.auth.oidc) !== 'undefined' &&
|
||||||
|
typeof(config.auth.oidc.issuerURL) !== 'undefined' &&
|
||||||
|
typeof(config.auth.oidc.clientOptions) !== 'undefined'
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const oidcIssuer = await Issuer.discover(config.auth.oidc.issuerURL);
|
||||||
|
|
||||||
|
// Setup authentication
|
||||||
|
setupOIDC(oidcIssuer);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
app.use(passport.initialize());
|
app.use(passport.initialize());
|
||||||
app.use(passport.session());
|
app.use(passport.session());
|
||||||
|
|
||||||
|
|
@ -270,6 +326,15 @@ async function setupAuth(oidcIssuer)
|
||||||
})(req, res, next);
|
})(req, res, next);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// lti launch
|
||||||
|
app.post('/auth/lti',
|
||||||
|
passport.authenticate('lti', { failureRedirect: '/' }),
|
||||||
|
function(req, res)
|
||||||
|
{
|
||||||
|
res.redirect(`/${req.user.room}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// logout
|
// logout
|
||||||
app.get('/auth/logout', (req, res) =>
|
app.get('/auth/logout', (req, res) =>
|
||||||
{
|
{
|
||||||
|
|
@ -325,6 +390,11 @@ async function runHttpsServer()
|
||||||
{
|
{
|
||||||
if (req.secure)
|
if (req.secure)
|
||||||
{
|
{
|
||||||
|
if (req.isAuthenticated && req.user && req.user._lti)
|
||||||
|
{
|
||||||
|
logger.error(req.user._lti);
|
||||||
|
}
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue