From cb0e631b853ac68ac8814a3db31caf4bc87b0e1d Mon Sep 17 00:00:00 2001 From: Hideki Nakamura Date: Tue, 11 Sep 2018 09:44:18 -0700 Subject: [PATCH] Update the implementation according to the Design notes --- red/api/auth/index.js | 20 +++++++++++--------- red/api/auth/tokens.js | 10 +++++----- red/api/auth/users.js | 23 +++-------------------- settings.js | 19 +++++++++++++++++++ 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/red/api/auth/index.js b/red/api/auth/index.js index c89c8d240..ae7f55818 100644 --- a/red/api/auth/index.js +++ b/red/api/auth/index.js @@ -40,8 +40,9 @@ function init(runtime) { settings = runtime.settings; log = runtime.log; if (settings.adminAuth) { - Users.init(settings.adminAuth,settings.apiAccessTokens); - Tokens.init(settings.adminAuth,runtime.storage,settings.apiAccessTokens); + var mergedAdminAuth = Object.assign(settings.adminAuth, settings.adminAuth.module); + Users.init(mergedAdminAuth); + Tokens.init(mergedAdminAuth,runtime.storage); strategies.init(runtime); } } @@ -81,23 +82,24 @@ function getToken(req,res,next) { function login(req,res) { var response = {}; if (settings.adminAuth) { - if (settings.adminAuth.type === "credentials") { + var mergedAdminAuth = Object.assign(settings.adminAuth, settings.adminAuth.module); + if (mergedAdminAuth.type === "credentials") { response = { "type":"credentials", "prompts":[{id:"username",type:"text",label:"user.username"},{id:"password",type:"password",label:"user.password"}] } - } else if (settings.adminAuth.type === "strategy") { + } else if (mergedAdminAuth.type === "strategy") { var urlPrefix = (settings.httpAdminRoot==='/')?"":settings.httpAdminRoot; response = { "type":"strategy", - "prompts":[{type:"button",label:settings.adminAuth.strategy.label, url: urlPrefix + "auth/strategy"}] + "prompts":[{type:"button",label:mergedAdminAuth.strategy.label, url: urlPrefix + "auth/strategy"}] } - if (settings.adminAuth.strategy.icon) { - response.prompts[0].icon = settings.adminAuth.strategy.icon; + if (mergedAdminAuth.strategy.icon) { + response.prompts[0].icon = mergedAdminAuth.strategy.icon; } - if (settings.adminAuth.strategy.image) { - response.prompts[0].image = theme.serveFile('/login/',settings.adminAuth.strategy.image); + if (mergedAdminAuth.strategy.image) { + response.prompts[0].image = theme.serveFile('/login/',mergedAdminAuth.strategy.image); } } if (theme.context().login && theme.context().login.image) { diff --git a/red/api/auth/tokens.js b/red/api/auth/tokens.js index 054234215..daa058787 100644 --- a/red/api/auth/tokens.js +++ b/red/api/auth/tokens.js @@ -63,7 +63,7 @@ function loadSessions() { } module.exports = { - init: function(adminAuthSettings, _storage, apiAccessTokensSettings) { + init: function(adminAuthSettings, _storage) { storage = _storage; sessionExpiryTime = adminAuthSettings.sessionExpiryTime || 604800; // 1 week in seconds // At this point, storage will not have been initialised, so defer loading @@ -71,11 +71,11 @@ module.exports = { loadedSessions = null; apiAccessTokens = {}; - if ( Array.isArray(apiAccessTokensSettings) ) { - apiAccessTokens = apiAccessTokensSettings.reduce(function(prev, current) { + if ( Array.isArray(adminAuthSettings.tokens) ) { + apiAccessTokens = adminAuthSettings.tokens.reduce(function(prev, current) { prev[current.token] = { - user: current.username, - scope: current.permissions + user: current.user, + scope: current.scope }; return prev; }, {}); diff --git a/red/api/auth/users.js b/red/api/auth/users.js index 4c2aaaf09..24a762958 100644 --- a/red/api/auth/users.js +++ b/red/api/auth/users.js @@ -57,35 +57,18 @@ function getDefaultUser() { } var api = { - get: wrapperGetUserFromSettings(get), + get: get, authenticate: authenticate, default: getDefaultUser } -var apiAccessUsers = {}; -function wrapperGetUserFromSettings (getFunc) { - return function (username) { - if (apiAccessUsers[username]) { - return Promise.resolve(apiAccessUsers[username]); - } else { - return getFunc(username); - } - }; -} - -function init(config, apiAccessTokensSettings) { +function init(config) { users = {}; defaultUser = null; - apiAccessUsers = apiAccessTokensSettings.reduce(function (prev, current) { - if (current.username) { - prev[current.username] = current.username; - } - return prev; - }, {}); if (config.type == "credentials" || config.type == "strategy") { if (config.users) { if (typeof config.users === "function") { - api.get = wrapperGetUserFromSettings(config.users); + api.get = config.users; } else { var us = config.users; /* istanbul ignore else */ diff --git a/settings.js b/settings.js index dc79223fe..90151d32a 100644 --- a/settings.js +++ b/settings.js @@ -124,6 +124,25 @@ module.exports = { // }] //}, + // If you would like to use not only this access token feature but also a Node-RED + // plugin module for authenticatiing users such as node-red-auth-github, + // you can define the module in adminAuth.module property. + //adminAuth: { + // module: require('node-red-auth-github')({ + // clientID: GITHUB_CLIENT_ID, + // clientSecret: GITHUB_CLIENT_SECRET, + // baseURL: "http://localhost:1880/", + // users: [ + // { username: "knolleary",permissions: ["*"]} + // ] + // }) + // tokens: [{ + // token: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", + // user: "knolleary", + // scope: ["*"] + // }] + //}, + // To password protect the node-defined HTTP endpoints (httpNodeRoot), or // the static content (httpStatic), the following properties can be used. // The pass field is a bcrypt hash of the password.