-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathscript-strategy.js
More file actions
84 lines (79 loc) · 2.1 KB
/
script-strategy.js
File metadata and controls
84 lines (79 loc) · 2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
* Script strategy that calls a local script to verify provided credentials.
*
* See: https://github.com/gbv/login-server/issues/117
*
* Requires a local path to the script.
*/
/**
* Module dependencies.
*/
import passport from "passport-strategy"
import util from "node:util"
import { exec as cpexec } from "node:child_process"
/**
* A wrapper around child_process' exec function for async/await.
*
* @param {*} command
* @param {*} options
*/
async function exec(command, options) {
return new Promise((resolve, reject) => {
cpexec(command, options || {}, (error, stdout, stderr) => {
if (error) {
error.stdout = stdout
error.stderr = stderr
return reject(error)
}
resolve(stdout)
})
})
}
/**
* `Strategy` constructor.
*
* @param {Object} options
* @param {Function} callback
* @api public
*/
export function Strategy({ script, passReqToCallback }, callback) {
if (!script) {
throw new TypeError("Script strategy requires a script to run")
}
passport.Strategy.call(this)
this.name = "script"
this._passReqToCallback = passReqToCallback
this._script = script
this._cb = callback
}
/**
* Inherit from `passport.Strategy`.
*/
util.inherits(Strategy, passport.Strategy)
/**
* Authenticate using supplied user.
*
* @param {Object} req
* @api protected
*/
Strategy.prototype.authenticate = async function(req) {
let username = (req.body && req.body.username) || req.query.username
let password = (req.body && req.body.password) || req.query.password
if (!username || !password) {
return this.fail({ message: "Missing credentials" }, 400)
}
try {
const result = JSON.parse(await exec(this._script, { env: { ...process.env, USERNAME: username, PASSWORD: password }}))
if (!result?.id) {
throw new Error(result.message || "Wrong credentials")
}
const user = result
let args = this._passReqToCallback ? [req] : []
args = args.concat([null, null, user, (error, user) => {
this.success(user)
}])
this._cb(...args)
} catch (error) {
return this.fail({ message: error.message }, 400)
}
}