Login to Strapi's Admin Dashboard using the API Token
This post was inspired by the discussion in the Strapi Forum.
Part 1: Create the endpoint to get user info and JWT token.
In the original discussion, it was achieved by passing a JWT token and user info as the query param to log in to the admin user. But what if we want to login using a static token generated inside the admin dashboard?
First, we need to create a new API using the following command.
yarn strapi generate
On the generated files, change src/api/teleport/routes/teleport.js
module.exports = {
routes: [
{
method: 'GET',
path: '/teleport',
handler: 'teleport.login',
config: {
policies: [],
middlewares: [],
},
},
],
};
, then add the functionality in src/api/teleport/controllers/teleport.js
'use strict';
/**
* A set of functions called "actions" for `teleport`
*/
const ADMIN_EMAIL = '[email protected]'
module.exports = {
login: async (ctx, next) => {
const hasToken = ctx.request.query && ctx.request.query.token;
const token = hasToken ? ctx.request.query.token : null;
if (!hasToken) {
ctx.status = 404;
return;
}
// check token
const apiTokenService = strapi.services['admin::api-token'];
const accessKey = await apiTokenService.hash(token);
const storedToken = await apiTokenService.getBy({accessKey: accessKey});
if (!storedToken) {
ctx.status = 404;
return;
}
// Deny access if expired.
if (storedToken.expiresAt && storedToken.expiresAt < new Date()) {
ctx.status = 404;
return;
}
// only full-access token
if (storedToken.type != 'full-access') {
ctx.status = 404;
return;
}
// get admin user
const user = await strapi.db.query('admin::user').findOne({
where: {
email: ADMIN_EMAIL
}
})
// hide sensitive data
delete user.password;
delete user.resetPasswordToken;
delete user.registrationToken;
const jwtToken = strapi.plugins['users-permissions'].services.jwt.issue({
id: user.id
});
const payload = JSON.stringify({
user: user,
jwtToken
});
ctx.redirect('/admin/auth/login?payload=' + payload);
return
}
};
In the admin dashboard, we have to set the API to public. and generate a full-access
token for later use. Therefore, when we access $URL/api/teleport?token=${token}
, it will redirect us to the admin login page, with the payload containing user data and token as the query param.
Part 2: Login the user with the credential previously obtained
Now we need to customize the login page logic, to check if we have payload
as a parameter inside the url. However, unlike v3 version, in Strapi v4, we need to do the following works to customize:
First, we need the patch-package
package as a dependency.
yarn install patch-package
Editnode_modules/@strapi/admin/admin/src/pages/AuthPage/index.js
after installing the package. Add the following lines below the "Redirect the user to the login page if the endpoint does not exist or there is already an admin user or the user is already logged in" code block.
// if url param has payload
if (search) {
const params = new URLSearchParams(search);
const payload = params.get('payload');
if (payload) {
const { user, jwtToken } = JSON.parse(payload)
auth.setToken(jwtToken, false);
auth.setUserInfo(user, false);
return <Redirect to="/" />;
}
else {
return <Redirect to="/auth/login" />;
}
}
A patch file will be generated inside the patches
folder, and run yarn build
to rebuild the admin dashboard. Open $url/api/teleport?token=${token}
again and you should notice it will redirect to the admin dashboard and log in the admin user.
Part 3: Don't forget to apply the patch!
When you are going to deploy Strapi to the server, remember to run the yarn patch-package
command to apply the patch before rebuilding the resources.