commit
e9b946ba93
|
|
@ -253,14 +253,14 @@ export default class RoomClient
|
|||
|
||||
login()
|
||||
{
|
||||
const url = `/login?roomId=${this._room.roomId}&peerName=${this._peerName}`;
|
||||
const url = `/auth/login?roomId=${this._room.roomId}&peerName=${this._peerName}`;
|
||||
|
||||
this._loginWindow = window.open(url, 'loginWindow');
|
||||
}
|
||||
|
||||
logout()
|
||||
{
|
||||
window.location = '/logout';
|
||||
window.location = '/auth/logout';
|
||||
}
|
||||
|
||||
closeLoginWindow()
|
||||
|
|
|
|||
|
|
@ -1,12 +1,26 @@
|
|||
module.exports =
|
||||
{
|
||||
// oAuth2 conf
|
||||
oauth2 :
|
||||
auth :
|
||||
{
|
||||
clientID : '',
|
||||
clientSecret : '',
|
||||
callbackURL : 'https://mYDomainName:port/auth-callback'
|
||||
/*
|
||||
The issuer URL for OpenID Connect discovery
|
||||
The OpenID Provider Configuration Document
|
||||
could be discovered on:
|
||||
issuerURL + '/.well-known/openid-configuration'
|
||||
*/
|
||||
issuerURL : 'https://example.com'
|
||||
clientOptions :
|
||||
{
|
||||
client_id : '',
|
||||
client_secret : '',
|
||||
scope : 'openid email profile'
|
||||
// where client.example.com is your multiparty meeting server
|
||||
redirect_uri : 'https://client.example.com/auth/callback'
|
||||
}
|
||||
},
|
||||
// session cookie secret
|
||||
cookieSecret : 'T0P-S3cR3t_cook!e',
|
||||
// Listening hostname for `gulp live|open`.
|
||||
domain : 'localhost',
|
||||
tls :
|
||||
|
|
|
|||
|
|
@ -12,9 +12,12 @@
|
|||
"compression": "^1.7.3",
|
||||
"debug": "^4.1.0",
|
||||
"express": "^4.16.3",
|
||||
"express-session": "^1.16.1",
|
||||
"mediasoup": "^2.6.11",
|
||||
"passport-dataporten": "^1.3.0",
|
||||
"socket.io": "^2.1.1"
|
||||
"openid-client": "^2.5.0",
|
||||
"passport": "^0.4.0",
|
||||
"socket.io": "^2.1.1",
|
||||
"spdy": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gulp": "^4.0.0",
|
||||
|
|
|
|||
241
server/server.js
241
server/server.js
|
|
@ -6,15 +6,18 @@ process.title = 'multiparty-meeting-server';
|
|||
|
||||
const config = require('./config/config');
|
||||
const fs = require('fs');
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
const spdy = require('spdy');
|
||||
const express = require('express');
|
||||
const compression = require('compression');
|
||||
const Logger = require('./lib/Logger');
|
||||
const Room = require('./lib/Room');
|
||||
const Dataporten = require('passport-dataporten');
|
||||
const utils = require('./util');
|
||||
const base64 = require('base-64');
|
||||
// auth
|
||||
const passport = require('passport');
|
||||
const { Issuer, Strategy } = require('openid-client');
|
||||
const session = require('express-session')
|
||||
|
||||
/* eslint-disable no-console */
|
||||
console.log('- process.env.DEBUG:', process.env.DEBUG);
|
||||
|
|
@ -37,58 +40,152 @@ const tls =
|
|||
key : fs.readFileSync(config.tls.key)
|
||||
};
|
||||
|
||||
const app = express();
|
||||
let app = express();
|
||||
let httpsServer;
|
||||
let oidcClient;
|
||||
let oidcStrategy;
|
||||
|
||||
app.use(compression());
|
||||
|
||||
const dataporten = new Dataporten.Setup(config.oauth2);
|
||||
|
||||
app.all('*', (req, res, next) =>
|
||||
passport.serializeUser(function(user, done)
|
||||
{
|
||||
if (req.secure)
|
||||
{
|
||||
return next();
|
||||
}
|
||||
|
||||
res.redirect(`https://${req.hostname}${req.url}`);
|
||||
done(null, user);
|
||||
});
|
||||
|
||||
app.use(dataporten.passport.initialize());
|
||||
app.use(dataporten.passport.session());
|
||||
|
||||
app.get('/login', (req, res, next) =>
|
||||
passport.deserializeUser(function(user, done)
|
||||
{
|
||||
dataporten.passport.authenticate('dataporten', {
|
||||
done(null, user);
|
||||
});
|
||||
|
||||
const auth=config.auth;
|
||||
|
||||
function setupAuth(oidcIssuer)
|
||||
{
|
||||
oidcClient = new oidcIssuer.Client(auth.clientOptions);
|
||||
const params =
|
||||
{
|
||||
...auth.clientOptions
|
||||
// ... any authorization request parameters go here
|
||||
// client_id defaults to client.client_id
|
||||
// redirect_uri defaults to client.redirect_uris[0]
|
||||
// response type defaults to client.response_types[0], then 'code'
|
||||
// scope defaults to 'openid'
|
||||
};
|
||||
|
||||
// optional, defaults to false, when true req is passed as a first
|
||||
// argument to verify fn
|
||||
const passReqToCallback = false;
|
||||
|
||||
// optional, defaults to false, when true the code_challenge_method will be
|
||||
// resolved from the issuer configuration, instead of true you may provide
|
||||
// any of the supported values directly, i.e. "S256" (recommended) or "plain"
|
||||
const usePKCE = false;
|
||||
const client=oidcClient;
|
||||
|
||||
oidcStrategy = new Strategy(
|
||||
{ client, params, passReqToCallback, usePKCE },
|
||||
(tokenset, userinfo, done) =>
|
||||
{
|
||||
let user = {
|
||||
id : tokenset.claims.sub,
|
||||
provider : tokenset.claims.iss,
|
||||
_userinfo : userinfo,
|
||||
_claims : tokenset.claims,
|
||||
};
|
||||
|
||||
|
||||
if ( typeof(userinfo.picture) !== 'undefined' ){
|
||||
if ( ! userinfo.picture.match(/^http/g) ) {
|
||||
user.Photos = [ { value: `data:image/jpeg;base64, ${userinfo.picture}` } ];
|
||||
} else {
|
||||
user.Photos= [ { value: userinfo.picture } ];
|
||||
}
|
||||
}
|
||||
|
||||
if ( typeof(userinfo.nickname) !== 'undefined' ){
|
||||
user.displayName=userinfo.nickname;
|
||||
}
|
||||
|
||||
if ( typeof(userinfo.name) !== 'undefined' ){
|
||||
user.displayName=userinfo.name;
|
||||
}
|
||||
|
||||
if ( typeof(userinfo.email) !== 'undefined' ){
|
||||
user.emails=[{value: userinfo.email}];
|
||||
}
|
||||
|
||||
if ( typeof(userinfo.given_name) !== 'undefined' ){
|
||||
user.name={givenName: userinfo.given_name};
|
||||
}
|
||||
|
||||
if ( typeof(userinfo.family_name) !== 'undefined' ){
|
||||
user.name={familyName: userinfo.family_name};
|
||||
}
|
||||
|
||||
if ( typeof(userinfo.middle_name) !== 'undefined' ){
|
||||
user.name={middleName: userinfo.middle_name};
|
||||
}
|
||||
|
||||
|
||||
return done(null, user);
|
||||
}
|
||||
);
|
||||
passport.use('oidc', oidcStrategy);
|
||||
|
||||
app.use(session({
|
||||
secret: config.cookieSecret,
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
cookie: { secure: true }
|
||||
}));
|
||||
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
// login
|
||||
app.get('/auth/login', (req, res, next) =>
|
||||
{
|
||||
passport.authenticate('oidc', {
|
||||
state : base64.encode(JSON.stringify({
|
||||
roomId : req.query.roomId,
|
||||
peerName : req.query.peerName,
|
||||
code : utils.random(10)
|
||||
}))
|
||||
|
||||
})(req, res, next);
|
||||
});
|
||||
});
|
||||
|
||||
dataporten.setupLogout(app, '/logout');
|
||||
|
||||
app.get('/', (req, res) =>
|
||||
{
|
||||
res.sendFile(`${__dirname}/public/chooseRoom.html`);
|
||||
});
|
||||
|
||||
app.get(
|
||||
'/auth-callback',
|
||||
dataporten.passport.authenticate('dataporten', { failureRedirect: '/login' }),
|
||||
// logout
|
||||
app.get('/auth/logout', function(req, res)
|
||||
{
|
||||
req.logout();
|
||||
res.redirect('/');
|
||||
}
|
||||
);
|
||||
// callback
|
||||
app.get(
|
||||
'/auth/callback',
|
||||
passport.authenticate('oidc', { failureRedirect: '/auth/login' }),
|
||||
(req, res) =>
|
||||
{
|
||||
const state = JSON.parse(base64.decode(req.query.state));
|
||||
|
||||
if (rooms.has(state.roomId))
|
||||
{
|
||||
let displayName,photo
|
||||
if (typeof(req.user) !== 'undefined'){
|
||||
if (typeof(req.user.displayName) !== 'undefined') displayName=req.user.displayName;
|
||||
else displayName="";
|
||||
if (
|
||||
typeof(req.user.Photos) !== 'undefined' &&
|
||||
typeof(req.user.Photos[0]) !== 'undefined' &&
|
||||
typeof(req.user.Photos[0].value) !== 'undefined'
|
||||
) photo=req.user.Photos[0].value;
|
||||
else photo="/static/media/buddy.403cb9f6.svg";
|
||||
}
|
||||
|
||||
const data =
|
||||
{
|
||||
peerName : state.peerName,
|
||||
name : req.user.data.displayName,
|
||||
picture : req.user.data.photos[0]
|
||||
name : displayName,
|
||||
picture : photo
|
||||
};
|
||||
|
||||
const room = rooms.get(state.roomId);
|
||||
|
|
@ -98,32 +195,53 @@ app.get(
|
|||
|
||||
res.send('');
|
||||
}
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
// Serve all files in the public folder as static files.
|
||||
app.use(express.static('public'));
|
||||
function setupWebServer() {
|
||||
app.use(compression());
|
||||
|
||||
app.use((req, res) => res.sendFile(`${__dirname}/public/index.html`));
|
||||
app.all('*', (req, res, next) =>
|
||||
{
|
||||
if (req.secure)
|
||||
{
|
||||
return next();
|
||||
}
|
||||
|
||||
const httpsServer = https.createServer(tls, app);
|
||||
res.redirect(`https://${req.hostname}${req.url}`);
|
||||
});
|
||||
|
||||
httpsServer.listen(config.listeningPort, '0.0.0.0', () =>
|
||||
{
|
||||
app.get('/', (req, res) =>
|
||||
{
|
||||
res.sendFile(`${__dirname}/public/chooseRoom.html`);
|
||||
});
|
||||
|
||||
// Serve all files in the public folder as static files.
|
||||
app.use(express.static('public'));
|
||||
|
||||
app.use((req, res) => res.sendFile(`${__dirname}/public/index.html`));
|
||||
|
||||
httpsServer = spdy.createServer(tls, app);
|
||||
|
||||
httpsServer.listen(config.listeningPort, '0.0.0.0', () =>
|
||||
{
|
||||
logger.info('Server running on port: ', config.listeningPort);
|
||||
});
|
||||
});
|
||||
|
||||
const httpServer = http.createServer(app);
|
||||
const httpServer = http.createServer(app);
|
||||
|
||||
httpServer.listen(config.listeningRedirectPort, '0.0.0.0', () =>
|
||||
{
|
||||
httpServer.listen(config.listeningRedirectPort, '0.0.0.0', () =>
|
||||
{
|
||||
logger.info('Server redirecting port: ', config.listeningRedirectPort);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const io = require('socket.io')(httpsServer);
|
||||
function setupSocketIO(){
|
||||
const io = require('socket.io')(httpsServer);
|
||||
|
||||
// Handle connections from clients.
|
||||
io.on('connection', (socket) =>
|
||||
{
|
||||
// Handle connections from clients.
|
||||
io.on('connection', (socket) =>
|
||||
{
|
||||
const { roomId, peerName } = socket.handshake.query;
|
||||
|
||||
if (!roomId || !peerName)
|
||||
|
|
@ -181,4 +299,27 @@ io.on('connection', (socket) =>
|
|||
socket.room = roomId;
|
||||
|
||||
room.handleConnection(peerName, socket);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (
|
||||
typeof(auth) !== 'undefined' &&
|
||||
typeof(auth.issuerURL) !== 'undefined' &&
|
||||
typeof(auth.clientOptions) !== 'undefined'
|
||||
)
|
||||
{
|
||||
Issuer.discover(auth.issuerURL).then((oidcIssuer) =>
|
||||
{
|
||||
setupAuth(oidcIssuer);
|
||||
setupWebServer();
|
||||
setupSocketIO();
|
||||
}).catch((err) => {
|
||||
logger.error(err);
|
||||
}
|
||||
);
|
||||
} else
|
||||
{
|
||||
logger.error('Auth is not configure properly!');
|
||||
setupWebServer();
|
||||
setupSocketIO();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue