Compare commits
3 Commits
feat_add_d
...
server-bas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6162ecff04 | ||
|
|
19d859e047 | ||
|
|
049d62873e |
@@ -19,6 +19,7 @@ export const configurationSchema = {
|
|||||||
|
|
||||||
class AuthGitHubXoPlugin {
|
class AuthGitHubXoPlugin {
|
||||||
constructor(xo) {
|
constructor(xo) {
|
||||||
|
this._unregisterPassportStrategy = undefined
|
||||||
this._xo = xo
|
this._xo = xo
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ class AuthGitHubXoPlugin {
|
|||||||
load() {
|
load() {
|
||||||
const { _xo: xo } = this
|
const { _xo: xo } = this
|
||||||
|
|
||||||
xo.registerPassportStrategy(
|
this._unregisterPassportStrategy = xo.registerPassportStrategy(
|
||||||
new Strategy(
|
new Strategy(
|
||||||
this._conf,
|
this._conf,
|
||||||
async (accessToken, refreshToken, profile, done) => {
|
async (accessToken, refreshToken, profile, done) => {
|
||||||
@@ -42,6 +43,10 @@ class AuthGitHubXoPlugin {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unload() {
|
||||||
|
this._unregisterPassportStrategy()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export const configurationSchema = {
|
|||||||
class AuthGoogleXoPlugin {
|
class AuthGoogleXoPlugin {
|
||||||
constructor({ xo }) {
|
constructor({ xo }) {
|
||||||
this._conf = null
|
this._conf = null
|
||||||
|
this._unregisterPassportStrategy = undefined
|
||||||
this._xo = xo
|
this._xo = xo
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ class AuthGoogleXoPlugin {
|
|||||||
const conf = this._conf
|
const conf = this._conf
|
||||||
const xo = this._xo
|
const xo = this._xo
|
||||||
|
|
||||||
xo.registerPassportStrategy(
|
this._unregisterPassportStrategy = xo.registerPassportStrategy(
|
||||||
new Strategy(conf, async (accessToken, refreshToken, profile, done) => {
|
new Strategy(conf, async (accessToken, refreshToken, profile, done) => {
|
||||||
try {
|
try {
|
||||||
done(
|
done(
|
||||||
@@ -60,6 +61,10 @@ class AuthGoogleXoPlugin {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unload() {
|
||||||
|
this._unregisterPassportStrategy()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|||||||
3
packages/xo-server-auth-http/.babelrc.js
Normal file
3
packages/xo-server-auth-http/.babelrc.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = require('../../@xen-orchestra/babel-config')(
|
||||||
|
require('./package.json')
|
||||||
|
)
|
||||||
24
packages/xo-server-auth-http/.npmignore
Normal file
24
packages/xo-server-auth-http/.npmignore
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/benchmark/
|
||||||
|
/benchmarks/
|
||||||
|
*.bench.js
|
||||||
|
*.bench.js.map
|
||||||
|
|
||||||
|
/examples/
|
||||||
|
example.js
|
||||||
|
example.js.map
|
||||||
|
*.example.js
|
||||||
|
*.example.js.map
|
||||||
|
|
||||||
|
/fixture/
|
||||||
|
/fixtures/
|
||||||
|
*.fixture.js
|
||||||
|
*.fixture.js.map
|
||||||
|
*.fixtures.js
|
||||||
|
*.fixtures.js.map
|
||||||
|
|
||||||
|
/test/
|
||||||
|
/tests/
|
||||||
|
*.spec.js
|
||||||
|
*.spec.js.map
|
||||||
|
|
||||||
|
__snapshots__/
|
||||||
48
packages/xo-server-auth-http/package.json
Normal file
48
packages/xo-server-auth-http/package.json
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "xo-server-auth-http",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"license": "AGPL-3.0",
|
||||||
|
"description": "Basic HTTP authentication plugin for XO-Server",
|
||||||
|
"keywords": [
|
||||||
|
"authorization",
|
||||||
|
"basic",
|
||||||
|
"http",
|
||||||
|
"orchestra",
|
||||||
|
"plugin",
|
||||||
|
"xen-orchestra",
|
||||||
|
"xen",
|
||||||
|
"xo-server"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server-auth-http",
|
||||||
|
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
|
||||||
|
"repository": {
|
||||||
|
"directory": "packages/xo-server-auth-http",
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/vatesfr/xen-orchestra.git"
|
||||||
|
},
|
||||||
|
"main": "dist/",
|
||||||
|
"files": [
|
||||||
|
"dist/"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.10"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"passport-http": "^0.3.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.7.4",
|
||||||
|
"@babel/core": "^7.7.4",
|
||||||
|
"@babel/preset-env": "^7.7.4",
|
||||||
|
"cross-env": "^6.0.3",
|
||||||
|
"rimraf": "^3.0.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
||||||
|
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
||||||
|
"prebuild": "rimraf dist/",
|
||||||
|
"predev": "yarn run prebuild",
|
||||||
|
"prepublishOnly": "yarn run build"
|
||||||
|
},
|
||||||
|
"private": true
|
||||||
|
}
|
||||||
46
packages/xo-server-auth-http/src/index.js
Normal file
46
packages/xo-server-auth-http/src/index.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { BasicStrategy } from 'passport-http'
|
||||||
|
|
||||||
|
export const configurationSchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
realm: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['realm'],
|
||||||
|
}
|
||||||
|
|
||||||
|
class Plugin {
|
||||||
|
constructor({ xo }) {
|
||||||
|
this._configuration = undefined
|
||||||
|
this._unregisterPassportStrategy = undefined
|
||||||
|
this._xo = xo
|
||||||
|
}
|
||||||
|
|
||||||
|
configure(configuration) {
|
||||||
|
this._configuration = configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
load() {
|
||||||
|
const xo = this._xo
|
||||||
|
this._unregisterPassportStrategy = xo.registerPassportStrategy(
|
||||||
|
new BasicStrategy(
|
||||||
|
this._configuration,
|
||||||
|
async (username, password, done) => {
|
||||||
|
try {
|
||||||
|
const { user } = await xo.authenticateUser({ username, password })
|
||||||
|
done(null, user)
|
||||||
|
} catch (error) {
|
||||||
|
done(null, false, { message: error.message })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
unload() {
|
||||||
|
this._unregisterPassportStrategy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default opts => new Plugin(opts)
|
||||||
@@ -48,6 +48,7 @@ You should try \`http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddr
|
|||||||
class AuthSamlXoPlugin {
|
class AuthSamlXoPlugin {
|
||||||
constructor({ xo }) {
|
constructor({ xo }) {
|
||||||
this._conf = null
|
this._conf = null
|
||||||
|
this._unregisterPassportStrategy = undefined
|
||||||
this._usernameField = null
|
this._usernameField = null
|
||||||
this._xo = xo
|
this._xo = xo
|
||||||
}
|
}
|
||||||
@@ -66,7 +67,7 @@ class AuthSamlXoPlugin {
|
|||||||
load() {
|
load() {
|
||||||
const xo = this._xo
|
const xo = this._xo
|
||||||
|
|
||||||
xo.registerPassportStrategy(
|
this._unregisterPassportStrategy = xo.registerPassportStrategy(
|
||||||
new Strategy(this._conf, async (profile, done) => {
|
new Strategy(this._conf, async (profile, done) => {
|
||||||
const name = profile[this._usernameField]
|
const name = profile[this._usernameField]
|
||||||
if (!name) {
|
if (!name) {
|
||||||
@@ -83,6 +84,10 @@ class AuthSamlXoPlugin {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unload() {
|
||||||
|
this._unregisterPassportStrategy()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import serveStatic from 'serve-static'
|
|||||||
import stoppable from 'stoppable'
|
import stoppable from 'stoppable'
|
||||||
import WebServer from 'http-server-plus'
|
import WebServer from 'http-server-plus'
|
||||||
import WebSocket from 'ws'
|
import WebSocket from 'ws'
|
||||||
import { forOwn, map } from 'lodash'
|
import { forOwn, map, once } from 'lodash'
|
||||||
import { URL } from 'url'
|
import { URL } from 'url'
|
||||||
|
|
||||||
import { compile as compilePug } from 'pug'
|
import { compile as compilePug } from 'pug'
|
||||||
@@ -124,11 +124,19 @@ async function setUpPassport(express, xo, { authentication: authCfg }) {
|
|||||||
strategy,
|
strategy,
|
||||||
{ label = strategy.label, name = strategy.name } = {}
|
{ label = strategy.label, name = strategy.name } = {}
|
||||||
) => {
|
) => {
|
||||||
passport.use(name, strategy)
|
if (name in strategies) {
|
||||||
|
throw new TypeError('duplicate passport strategy ' + name)
|
||||||
|
}
|
||||||
|
|
||||||
|
passport.use(name, strategy)
|
||||||
if (name !== 'local') {
|
if (name !== 'local') {
|
||||||
strategies[name] = label ?? name
|
strategies[name] = label ?? name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return once(() => {
|
||||||
|
passport.unuse(name)
|
||||||
|
delete strategies[name]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registers the sign in form.
|
// Registers the sign in form.
|
||||||
@@ -171,7 +179,9 @@ async function setUpPassport(express, xo, { authentication: authCfg }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (authenticator.check(req.body.otp, user.preferences.otp)) {
|
if (authenticator.check(req.body.otp, user.preferences.otp)) {
|
||||||
setToken(req, res, next)
|
setToken(req, res, next).then(() =>
|
||||||
|
res.redirect(303, req.flash('return-url')[0] || '/')
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
req.flash('error', 'Invalid code')
|
req.flash('error', 'Invalid code')
|
||||||
res.redirect(303, '/signin-otp')
|
res.redirect(303, '/signin-otp')
|
||||||
@@ -183,7 +193,7 @@ async function setUpPassport(express, xo, { authentication: authCfg }) {
|
|||||||
parseDuration
|
parseDuration
|
||||||
)
|
)
|
||||||
const SESSION_VALIDITY = ifDef(authCfg.sessionCookieValidity, parseDuration)
|
const SESSION_VALIDITY = ifDef(authCfg.sessionCookieValidity, parseDuration)
|
||||||
const setToken = async (req, res, next) => {
|
const setToken = async (req, res) => {
|
||||||
const { user, isPersistent } = req.session
|
const { user, isPersistent } = req.session
|
||||||
const token = await xo.createAuthenticationToken({
|
const token = await xo.createAuthenticationToken({
|
||||||
expiresIn: isPersistent ? PERMANENT_VALIDITY : SESSION_VALIDITY,
|
expiresIn: isPersistent ? PERMANENT_VALIDITY : SESSION_VALIDITY,
|
||||||
@@ -200,7 +210,6 @@ async function setUpPassport(express, xo, { authentication: authCfg }) {
|
|||||||
|
|
||||||
delete req.session.isPersistent
|
delete req.session.isPersistent
|
||||||
delete req.session.user
|
delete req.session.user
|
||||||
res.redirect(303, req.flash('return-url')[0] || '/')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SIGNIN_STRATEGY_RE = /^\/signin\/([^/]+)(\/callback)?(:?\?.*)?$/
|
const SIGNIN_STRATEGY_RE = /^\/signin\/([^/]+)(\/callback)?(:?\?.*)?$/
|
||||||
@@ -220,6 +229,12 @@ async function setUpPassport(express, xo, { authentication: authCfg }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
if (typeof info === 'string') {
|
||||||
|
res.statusCode = 401
|
||||||
|
res.setHeader('WWW-Authenticate', info)
|
||||||
|
return res.end('unauthorized')
|
||||||
|
}
|
||||||
|
|
||||||
req.flash('error', info ? info.message : 'Invalid credentials')
|
req.flash('error', info ? info.message : 'Invalid credentials')
|
||||||
return res.redirect(303, '/signin')
|
return res.redirect(303, '/signin')
|
||||||
}
|
}
|
||||||
@@ -232,16 +247,17 @@ async function setUpPassport(express, xo, { authentication: authCfg }) {
|
|||||||
return res.redirect(303, '/signin-otp')
|
return res.redirect(303, '/signin-otp')
|
||||||
}
|
}
|
||||||
|
|
||||||
setToken(req, res, next)
|
await setToken(req, res)
|
||||||
|
res.redirect(303, req.flash('return-url')[0] || '/')
|
||||||
})(req, res, next)
|
})(req, res, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.cookies.token) {
|
if (req.cookies.token) {
|
||||||
next()
|
return next()
|
||||||
} else {
|
|
||||||
req.flash('return-url', url)
|
|
||||||
res.redirect(authCfg.defaultSignInPage)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req.flash('return-url', url)
|
||||||
|
return res.redirect(authCfg.defaultSignInPage)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Install the local strategy.
|
// Install the local strategy.
|
||||||
|
|||||||
13
yarn.lock
13
yarn.lock
@@ -2,7 +2,7 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@babel/cli@^7.0.0", "@babel/cli@^7.1.5", "@babel/cli@^7.4.4", "@babel/cli@^7.7.0":
|
"@babel/cli@^7.0.0", "@babel/cli@^7.1.5", "@babel/cli@^7.4.4", "@babel/cli@^7.7.0", "@babel/cli@^7.7.4":
|
||||||
version "7.7.4"
|
version "7.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.7.4.tgz#38804334c8db40209f88c69a5c90998e60cca18b"
|
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.7.4.tgz#38804334c8db40209f88c69a5c90998e60cca18b"
|
||||||
integrity sha512-O7mmzaWdm+VabWQmxuM8hqNrWGGihN83KfhPUzp2lAW4kzIMwBxujXkZbD4fMwKMYY9FXTbDvXsJqU+5XHXi4A==
|
integrity sha512-O7mmzaWdm+VabWQmxuM8hqNrWGGihN83KfhPUzp2lAW4kzIMwBxujXkZbD4fMwKMYY9FXTbDvXsJqU+5XHXi4A==
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/highlight" "^7.0.0"
|
"@babel/highlight" "^7.0.0"
|
||||||
|
|
||||||
"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.1.5", "@babel/core@^7.1.6", "@babel/core@^7.4.4", "@babel/core@^7.7.2":
|
"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.1.5", "@babel/core@^7.1.6", "@babel/core@^7.4.4", "@babel/core@^7.7.2", "@babel/core@^7.7.4":
|
||||||
version "7.7.4"
|
version "7.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.4.tgz#37e864532200cb6b50ee9a4045f5f817840166ab"
|
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.4.tgz#37e864532200cb6b50ee9a4045f5f817840166ab"
|
||||||
integrity sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==
|
integrity sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==
|
||||||
@@ -740,7 +740,7 @@
|
|||||||
core-js "^2.6.5"
|
core-js "^2.6.5"
|
||||||
regenerator-runtime "^0.13.2"
|
regenerator-runtime "^0.13.2"
|
||||||
|
|
||||||
"@babel/preset-env@^7.0.0", "@babel/preset-env@^7.1.5", "@babel/preset-env@^7.1.6", "@babel/preset-env@^7.4.4", "@babel/preset-env@^7.7.1":
|
"@babel/preset-env@^7.0.0", "@babel/preset-env@^7.1.5", "@babel/preset-env@^7.1.6", "@babel/preset-env@^7.4.4", "@babel/preset-env@^7.7.1", "@babel/preset-env@^7.7.4":
|
||||||
version "7.7.4"
|
version "7.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.4.tgz#ccaf309ae8d1ee2409c85a4e2b5e280ceee830f8"
|
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.4.tgz#ccaf309ae8d1ee2409c85a4e2b5e280ceee830f8"
|
||||||
integrity sha512-Dg+ciGJjwvC1NIe/DGblMbcGq1HOtKbw8RLl4nIjlfcILKEOkWT/vRqPpumswABEBVudii6dnVwrBtzD7ibm4g==
|
integrity sha512-Dg+ciGJjwvC1NIe/DGblMbcGq1HOtKbw8RLl4nIjlfcILKEOkWT/vRqPpumswABEBVudii6dnVwrBtzD7ibm4g==
|
||||||
@@ -10928,6 +10928,13 @@ passport-google-oauth20@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
passport-oauth2 "1.x.x"
|
passport-oauth2 "1.x.x"
|
||||||
|
|
||||||
|
passport-http@^0.3.0:
|
||||||
|
version "0.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/passport-http/-/passport-http-0.3.0.tgz#8ee53d4380be9c60df2151925029826f77115603"
|
||||||
|
integrity sha1-juU9Q4C+nGDfIVGSUCmCb3cRVgM=
|
||||||
|
dependencies:
|
||||||
|
passport-strategy "1.x.x"
|
||||||
|
|
||||||
passport-local@^1.0.0:
|
passport-local@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee"
|
resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee"
|
||||||
|
|||||||
Reference in New Issue
Block a user