feat(xo-server): web signin with auth token in query string (#7314)

Potential issue: the token stays in the browser history.
This commit is contained in:
Julien Fontanet 2024-01-24 10:02:38 +01:00 committed by GitHub
parent 5f73f09f59
commit c6fdef33c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -170,13 +170,31 @@ async function setUpPassport(express, xo, { authentication: authCfg, http: { coo
// Registers the sign in form.
const signInPage = compilePug(await fse.readFile(new URL('../signin.pug', import.meta.url)))
express.get('/signin', (req, res, next) => {
res.send(
signInPage({
error: req.flash('error')[0],
strategies,
})
)
express.get('/signin', async (req, res, next) => {
try {
let errorMsg
const tokenId = req.query.token
if (tokenId !== undefined) {
try {
const token = await xo.getAuthenticationToken(tokenId)
req.session.isPersistent = req.query
return saveToken(token, req, res, next)
} catch (error) {
errorMsg = error.message
}
} else {
errorMsg = req.flash('error')[0]
}
res.send(
signInPage({
error: errorMsg,
strategies,
})
)
} catch (error) {
next(error)
}
})
express.get('/signout', (req, res) => {
@ -206,7 +224,7 @@ async function setUpPassport(express, xo, { authentication: authCfg, http: { coo
}
if (await verifyTotp(req.body.otp, { secret: user.preferences.otp })) {
setToken(req, res, next)
createAndSaveToken(req, res, next)
} else {
req.flash('error', 'Invalid code')
res.redirect(303, '/signin-otp')
@ -216,7 +234,7 @@ async function setUpPassport(express, xo, { authentication: authCfg, http: { coo
const PERMANENT_VALIDITY = ifDef(authCfg.permanentCookieValidity, parseDuration)
const SESSION_VALIDITY = ifDef(authCfg.sessionCookieValidity, parseDuration)
const TEN_YEARS = 10 * 365 * 24 * 60 * 60 * 1e3
const setToken = async (req, res, next) => {
const createAndSaveToken = async (req, res, next) => {
let { clientId } = req.cookies
if (clientId === undefined) {
clientId = Math.random().toString(36).slice(2)
@ -237,17 +255,20 @@ async function setUpPassport(express, xo, { authentication: authCfg, http: { coo
expiresIn: isPersistent ? PERMANENT_VALIDITY : SESSION_VALIDITY,
userId: user.id,
})
delete req.session.user
return saveToken(token, req, res, next)
}
const saveToken = async (token, req, res, next) => {
res.cookie('token', token.id, {
...cookieCfg,
// a session (non-permanent) cookie must not have an expiration date
// because it must not survive browser restart
...(isPersistent ? { expires: new Date(token.expiration) } : undefined),
...(req.session.isPersistent ? { expires: new Date(token.expiration) } : undefined),
})
delete req.session.isPersistent
delete req.session.user
res.redirect(303, req.flash('return-url')[0] || '/')
}
@ -288,7 +309,7 @@ async function setUpPassport(express, xo, { authentication: authCfg, http: { coo
return res.redirect(303, '/signin-otp')
}
setToken(req, res, next)
createAndSaveToken(req, res, next)
})(req, res, next)
}