Skip to content

Commit

Permalink
Supported for multiple OIDC authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
ggtakec committed Aug 15, 2023
1 parent 83751c0 commit d56b4b1
Show file tree
Hide file tree
Showing 26 changed files with 687 additions and 142 deletions.
16 changes: 12 additions & 4 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,28 @@ app.use('/status.html', express.static(__dirname + '/public/status.html'));
// Setup extension router
//
var cfgExtRouter= appConf.getExtRouter();

if(r3util.isSafeEntity(cfgExtRouter)){
var routerObject = {};
Object.keys(cfgExtRouter).forEach(function(routername){
// check name/path
if(r3util.isSafeString(cfgExtRouter[routername].name) && r3util.isSafeString(cfgExtRouter[routername].path)){
var entry = require('./routes/' + cfgExtRouter[routername].name);
var routerTypeName = cfgExtRouter[routername].name;

if(!r3util.isSafeEntity(routerObject[routerTypeName])){
routerObject[routerTypeName] = require('./routes/' + cfgExtRouter[routername].name);
}

// check setConfig function
if(r3util.isSafeEntity(entry.setConfig) && 'function' == typeof entry.setConfig){
if(r3util.isSafeEntity(routerObject[routerTypeName].setConfig) && 'function' == typeof routerObject[routerTypeName].setConfig){
var routerConfig = r3util.isSafeEntity(cfgExtRouter[routername].config) ? cfgExtRouter[routername].config : null;
if(!entry.setConfig(routerConfig)){
if(!routerObject[routerTypeName].setConfig(routerConfig, routername)){
console.error('failed to set configuration for extension router(name=' + JSON.stringify(cfgExtRouter[routername].name) + ', path=' + JSON.stringify(cfgExtRouter[routername].path) + ').');
}
}

// set router
app.use(cfgExtRouter[routername].path, entry.router);
app.use(cfgExtRouter[routername].path, routerObject[routerTypeName].router);
console.log('success set extension router(name=' + JSON.stringify(cfgExtRouter[routername].name) + ', path=' + JSON.stringify(cfgExtRouter[routername].path) + ').');
}else{
console.error('something wrong extrouter configration(name=' + JSON.stringify(cfgExtRouter[routername].name) + ', path=' + JSON.stringify(cfgExtRouter[routername].path) + ').');
Expand Down
22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.1",
"@mui/material": "^5.14.1",
"@mui/icons-material": "^5.14.3",
"@mui/material": "^5.14.5",
"ajv": "^8.12.0",
"body-parser": "^1.20.2",
"config": "^3.3.9",
Expand Down Expand Up @@ -42,21 +42,21 @@
"views": "views"
},
"devDependencies": {
"@babel/core": "^7.22.9",
"@babel/eslint-parser": "^7.22.9",
"@babel/core": "^7.22.10",
"@babel/eslint-parser": "^7.22.10",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-private-methods": "^7.18.6",
"@babel/plugin-proposal-decorators": "^7.22.7",
"@babel/plugin-proposal-decorators": "^7.22.10",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/preset-env": "^7.22.9",
"@babel/preset-env": "^7.22.10",
"@babel/preset-react": "^7.22.5",
"babel-jest": "^29.6.1",
"babel-jest": "^29.6.2",
"babel-loader": "^9.1.3",
"css-loader": "^6.8.1",
"eslint": "^8.45.0",
"eslint-plugin-react": "^7.33.0",
"jest": "^29.6.1",
"jest-environment-jsdom": "^29.6.1",
"eslint": "^8.47.0",
"eslint-plugin-react": "^7.33.1",
"jest": "^29.6.2",
"jest-environment-jsdom": "^29.6.2",
"license-checker": "^25.0.1",
"react-test-context-provider": "^2.2.0",
"react-test-renderer": "^18.2.0",
Expand Down
6 changes: 4 additions & 2 deletions routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ router.get('/', function(req, res, next) // eslint-disable-line no-unused-
var signintype = tokensObj.getSignInType();
var signinurl = tokensObj.getSignInUrl();
var signouturl = tokensObj.getSignOutUrl();
var configname = tokensObj.getConfigName(); // If using ExtRouter(ex. OIDC) and has a token, the config name that created the token is set.
var uselocaltenant = _appConf.useLocalTenant();
var lang = _appConf.getLang();
var dbgheader = '';
Expand All @@ -102,8 +103,9 @@ router.get('/', function(req, res, next) // eslint-disable-line no-unused-
username: username,
unscopedtoken: token,
signintype: signintype,
signinurl: signinurl,
signouturl: signouturl,
signinurl: escape(JSON.stringify(signinurl)),
signouturl: escape(JSON.stringify(signouturl)),
configname: escape(JSON.stringify(configname)),
uselocaltenant: uselocaltenant,
lang: lang,
dbgheader: dbgheader,
Expand Down
20 changes: 15 additions & 5 deletions routes/lib/libr3tokens.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ var R3UserToken = (function()
}else{
this.sinintype = null;
}
if(r3util.isSafeEntity(this.appConfig.getUserValidatorObj().getSginInUri)){
this.signinUrl = this.appConfig.getUserValidatorObj().getSginInUri(req);
if(r3util.isSafeEntity(this.appConfig.getUserValidatorObj().getSignInUri)){
this.signinUrl = this.appConfig.getUserValidatorObj().getSignInUri(req);
}else{
this.signinUrl = null;
}
if(r3util.isSafeEntity(this.appConfig.getUserValidatorObj().getSginOutUri)){
this.signoutUrl = this.appConfig.getUserValidatorObj().getSginOutUri(req);
if(r3util.isSafeEntity(this.appConfig.getUserValidatorObj().getSignOutUri)){
this.signoutUrl = this.appConfig.getUserValidatorObj().getSignOutUri(req);
}else{
this.signoutUrl = null;
}
Expand All @@ -68,6 +68,11 @@ var R3UserToken = (function()
}else{
this.otherToken = null;
}
if(r3util.isSafeEntity(this.appConfig.getUserValidatorObj().getConfigName)){
this.configName = this.appConfig.getUserValidatorObj().getConfigName(req);
}else{
this.configName = null;
}
};

var proto = R3UserToken.prototype;
Expand Down Expand Up @@ -226,10 +231,15 @@ var R3UserToken = (function()
return (null !== this.rawExtractUserToken(req));
};

proto.getConfigName = function()
{
return this.configName;
};

proto.getUnscopedUserToken = function(callback)
{
if(!r3util.isSafeString(this.username)){
var errobj = new Error('User name is not specified(not found backyard cookie)');
var errobj = new Error('User name is not specified(not found authentication cookie)');
console.error(errobj.message);
callback(errobj, null);
return;
Expand Down
4 changes: 2 additions & 2 deletions routes/lib/userValidateCredential.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ exports.getUserName = function(req) // eslint-disable-line no-unused-vars
return null;
};

exports.getSginInUri = function(req) // eslint-disable-line no-unused-vars
exports.getSignInUri = function(req) // eslint-disable-line no-unused-vars
{
return null;
};

exports.getSginOutUri = function(req) // eslint-disable-line no-unused-vars
exports.getSignOutUri = function(req) // eslint-disable-line no-unused-vars
{
return null;
};
Expand Down
149 changes: 118 additions & 31 deletions routes/lib/userValidateOidc.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,39 +30,46 @@ var { decode } = require('jose').base64url;
//
var rawGetOtherToken = function(req)
{
var config = oidc.getConfig();
if( !r3util.isSafeEntity(config) ||
!r3util.isSafeEntity(config.params) ||
!r3util.isSafeEntity(config.params.cookiename) )
var configName = rawGetOidcConfigName(req);
var config = oidc.getConfig();

if( !r3util.isSafeString(configName) ||
!r3util.isSafeEntity(config) ||
!r3util.isSafeEntity(config[configName]) ||
!r3util.isSafeEntity(config[configName].params) ||
!r3util.isSafeEntity(config[configName].params.cookiename) )
{
console.error('Not find cookie name in configuration.');
return null;
}
var cookieName = config[configName].params.cookiename;

if( !r3util.isSafeEntity(req) ||
!r3util.isSafeEntity(req.cookies) ||
!r3util.isSafeEntity(req.cookies[config.params.cookiename]))
if( !r3util.isSafeEntity(req) ||
!r3util.isSafeEntity(req.cookies) ||
!r3util.isSafeEntity(req.cookies[cookieName]) )
{
return null;
}

return req.cookies[config.params.cookiename];
return req.cookies[cookieName];
};

//
// rawGetOidcUsername
//
var rawGetOidcUsername = function(req)
{
var config = oidc.getConfig();
if( !r3util.isSafeEntity(config) ||
!r3util.isSafeEntity(config.params) ||
!r3util.isSafeEntity(config.params.cookiename) ||
!r3util.isSafeEntity(config.params.usernamekey) )
var configName = rawGetOidcConfigName(req);
var config = oidc.getConfig();
if( !r3util.isSafeString(configName) ||
!r3util.isSafeEntity(config) ||
!r3util.isSafeEntity(config[configName]) ||
!r3util.isSafeEntity(config[configName].params) ||
!r3util.isSafeEntity(config[configName].params.usernamekey) )
{
console.error('Not find cookie/user name key in configuration.');
console.error('Not find user name key in configuration.');
return null;
}
var userNameKey = config[configName].params.usernamekey;

var oidc_token = rawGetOtherToken(req);
if(!r3util.isSafeString(oidc_token)){
Expand All @@ -83,13 +90,38 @@ var rawGetOidcUsername = function(req)
}

var payload = JSON.parse(raw_payload);
if(!r3util.isSafeEntity(payload) || !r3util.isSafeEntity(payload[config.params.usernamekey])){
console.error('payload does not have user name key(' + config.params.usernamekey + ')');
if(!r3util.isSafeEntity(payload) || !r3util.isSafeEntity(payload[userNameKey])){
console.error('payload does not have user name key(' + userNameKey + ')');
return null;
}
return payload[userNameKey];
};

//
// rawGetOidcConfigName
//
var rawGetOidcConfigName = function(req)
{
if( !r3util.isSafeEntity(req) ||
!r3util.isSafeEntity(req.cookies) ||
!r3util.isSafeEntity(req.cookies[oidc.oidcConfigCookieName]))
{
return null;
}
return payload[config.params.usernamekey];
return req.cookies[oidc.oidcConfigCookieName];
};

//
// Return object or null:
// {
// '<oidc name>': {
// 'display': '<display name>',
// 'url': '<signin URL>'
// },
// ...
// ...
// }
//
var rawGetSignInUrl = function(req)
{
if( !r3util.isSafeEntity(req) ||
Expand All @@ -101,16 +133,49 @@ var rawGetSignInUrl = function(req)
}

var config = oidc.getConfig();
if( r3util.isSafeEntity(config) &&
r3util.isSafeEntity(config.params) &&
r3util.isSafeEntity(config.params.redirectUrl) )

if(!r3util.isSafeEntity(config)){
console.error('no valid SignInUrl');
return null;
}

var allSignUrls = {};
var isSet = false;

Object.keys(config).forEach(function(oidcName)
{
return config.params.redirectUrl;
if(r3util.isSafeEntity(config[oidcName].params) && r3util.isSafeEntity(config[oidcName].params.redirectUrl)){
var oneOidc = {};
oneOidc.url = config[oidcName].params.redirectUrl;

if(r3util.isSafeString(config[oidcName].displayName)){
oneOidc.display = config[oidcName].displayName;
}else{
oneOidc.display = oidcName;
}
allSignUrls[oidcName] = oneOidc;
isSet = true;
}else{
console.error('no valid SignInUrl for ' + oidcName + ' in config, so skip this');
}
});

if(!isSet){
console.error('no valid SignInUrl');
return null;
}
console.error('no valid SignInUrl');
return null;

return allSignUrls;
};

//
// Return object or null:
// {
// '<oidc name>': '<signout URL>',
// ...
// ...
// }
//
var rawGetSignOutUrl = function(req)
{
if( !r3util.isSafeEntity(req) ||
Expand All @@ -122,13 +187,30 @@ var rawGetSignOutUrl = function(req)
}

var config = oidc.getConfig();
if( r3util.isSafeEntity(config) &&
r3util.isSafeEntity(config.logoutUrl) )

if(!r3util.isSafeEntity(config)){
console.error('no valid SignOutUrl');
return null;
}

var allSignUrls = {};
var isSet = false;

Object.keys(config).forEach(function(oidcName)
{
return config.logoutUrl;
if(r3util.isSafeString(config[oidcName].logoutUrl)){
allSignUrls[oidcName] = config[oidcName].logoutUrl;
isSet = true;
}else{
console.error('no valid SignOutUrl for ' + oidcName + ' in config, so skip this');
}
});

if(!isSet){
console.error('no valid SignInUrl');
return null;
}
console.error('no valid SignOutUrl');
return null;
return allSignUrls;
};

//---------------------------------------------------------
Expand All @@ -144,12 +226,17 @@ exports.getUserName = function(req)
return rawGetOidcUsername(req);
};

exports.getSginInUri = function(req)
exports.getConfigName = function(req)
{
return rawGetOidcConfigName(req);
};

exports.getSignInUri = function(req)
{
return rawGetSignInUrl(req);
};

exports.getSginOutUri = function(req)
exports.getSignOutUri = function(req)
{
return rawGetSignOutUrl(req);
};
Expand Down
Loading

0 comments on commit d56b4b1

Please sign in to comment.