Some time ago I was asked to implement an autologin feature (password-free login) on Vue Storefront 1, I’ll tell you how I did it partly to explain how authentication works in a headless frontend and partly in case some other legacy software hero has the same problem and wants the work already done.
The context
The requirement was to implement an e-procurement system on the Magento2 store to allow B2B customers to order directly without having to log in and check out manually.
The OCI Punchout plugin has been installed on Magento which requires the user to be authenticated on the frontend directly via OCI Punchout so they don’t have to enter their username and password.
The frontend was Vue Storefront 1, the first legendary PWA for Magento2 (later evolved into Alokai), Version 1 is still used even though it’s a bit old, I talked about it in another post
Autologin
The OCI Punchout plugin has been extended to redirect the user to a dedicated Vue Storefront page with a single-use code that can be exchanged for an access token in the query string after the user logs in via OCI Punchout.
On this page, which contains only a loading spinner, a POST request is made to the /autologin
Vue Storefront API (the Node backend service of Vue Storefront)
m2Api.post('/autologin', (req, res) => {
return request({
url: `${config.magento2.api.url}/V1/vsf-autologin/exchange`,
method: 'POST',
json: true,
headers: { 'Content-Type': 'application/json' },
body: { req.body.code }
}, (error, response, body) => {
if (error || response.statusCode !== 200) {
return apiStatus(res, { response, error }, 500);
}
const customerToken = body;
const secret = config.authHashSecret ? config.authHashSecret : config.objHashSecret;
return apiStatus(res, customerToken, 200, {
refreshToken: encryptToken(jwt.encode({ token: customerToken }, secret), secret)
});
});
});
This endpoint obtains the access token from Magento and returns it to the frontend along with a refresh token,
obtained by encrypting the credentials in a JWT signed with authHashSecret and further encrypted with encryptToken.
This is the stateless, client-side JWT authentication model, which is explained in more detail in the post on authentication secrets.
Once the token is obtained, Vue Storefront behaves as if a normal login had occurred,
for convenience I wrote a dedicated action in the User module:
...
async autologin ({ commit, dispatch }, resp) {
await dispatch('resetUserInvalidation', {}, { root: true })
userHooksExecutors.afterUserAuthorize(resp)
try {
commit(types.USER_TOKEN_CHANGED, { newToken: resp.result, meta: resp.meta })
await dispatch('sessionAfterAuthorized', { refresh: true, useCache: false })
} catch (err) {
await dispatch('clearCurrentUser')
throw new Error(err)
}
return resp
}
The token is saved in local storage and used to authenticate subsequent requests.
That is
The Autologin implementation is complete, a second endpoint to send the cart to Magento without going through the checkout is needed now (but that’s another story)
… and speaking of punchout, have you ever seen Million dollar baby? Great movie.
“Million dollar baby” Clint Eastwood 2004