diff --git a/packages/strapi-admin/config/routes.json b/packages/strapi-admin/config/routes.json index 952c8fb10b..7f3d800bc6 100644 --- a/packages/strapi-admin/config/routes.json +++ b/packages/strapi-admin/config/routes.json @@ -59,6 +59,11 @@ "path": "/login", "handler": "authentication.login" }, + { + "method": "POST", + "path": "/renew-token", + "handler": "authentication.renewToken" + }, { "method": "POST", "path": "/auth/local/register", diff --git a/packages/strapi-admin/controllers/authentication.js b/packages/strapi-admin/controllers/authentication.js index 7b7de857e3..43ca3ca9b5 100644 --- a/packages/strapi-admin/controllers/authentication.js +++ b/packages/strapi-admin/controllers/authentication.js @@ -3,31 +3,51 @@ const passport = require('koa-passport'); const compose = require('koa-compose'); -const login = compose([ - (ctx, next) => { - return passport.authenticate('local', { session: false }, (err, user, info) => { - if (err) { - ctx.body = { error: 'Internal server error' }; - } else if (!user) { - ctx.body = { error: info.error }; - } else { +module.exports = { + login: compose([ + (ctx, next) => { + return passport.authenticate('local', { session: false }, (err, user, info) => { + if (err) { + return ctx.badImplementation(); + } + + if (!user) { + return ctx.badRequest(info.error); + } + ctx.state.user = user; return next(); - } - })(ctx, next); - }, - ctx => { - const { user } = ctx.state; + })(ctx, next); + }, + ctx => { + const { user } = ctx.state; + + ctx.body = { + data: { + token: strapi.admin.services.auth.createJwtToken(user), + user: strapi.admin.services.auth.sanitizeUser(ctx.state.user), // TODO: fetch more detailed info + }, + }; + }, + ]), + + renewToken(ctx) { + const { token } = ctx.request.body; + + if (token === undefined) { + return ctx.badRequest('Token is required.'); + } + + const { isValid, payload } = strapi.admin.services.auth.decodeToken(token); + + if (!isValid) { + return ctx.badRequest('Invalid token.'); + } ctx.body = { data: { - token: strapi.admin.services.auth.createJwtToken(user), - user: strapi.admin.services.auth.sanitizeUser(ctx.state.user), // TODO: fetch more detailed info + token: strapi.admin.services.auth.createJwtToken(payload.id), }, }; }, -]); - -module.exports = { - login, }; diff --git a/packages/strapi-admin/services/auth.js b/packages/strapi-admin/services/auth.js index eaa05433b9..4b25dfbfa7 100644 --- a/packages/strapi-admin/services/auth.js +++ b/packages/strapi-admin/services/auth.js @@ -8,7 +8,7 @@ const sanitizeUser = user => { return _.omit(user, ['password', 'resetPasswordToken']); }; -const defaultOptions = { expiresIn: '30d' }; +const defaultOptions = { expiresIn: '1s' }; const getJWTOptions = () => { const { options, secret } = strapi.config.get('server.admin.jwt', {}); @@ -78,6 +78,17 @@ const checkCredentials = async ({ email, password }) => { return [null, user]; }; +const decodeToken = token => { + const { secret } = getJWTOptions(); + + try { + const payload = jwt.verify(token, secret); + return { payload, isValid: true }; + } catch (err) { + return { payloda: null, isValid: false }; + } +}; + module.exports = { checkCredentials, createJwtToken, @@ -85,4 +96,5 @@ module.exports = { validatePassword, hashPassword, getJWTOptions, + decodeToken, };