mirror of
https://github.com/qlik-oss/nebula.js.git
synced 2025-12-19 17:58:43 -05:00
* fix: client id cache issue * fix: clean cached auth state when deauthorizing * chore: move auth routes into specific router module * chore: update redirect link for OAuth in connection guid * feat: error page for old /login/callback url
122 lines
3.5 KiB
JavaScript
122 lines
3.5 KiB
JavaScript
const express = require('express');
|
|
const { Auth, AuthType } = require('@qlik/sdk');
|
|
|
|
let prevHost = null;
|
|
let prevClientId = null;
|
|
let authInstance = null;
|
|
|
|
const getAuthInstance = (returnToOrigin, host, clientId) => {
|
|
if (authInstance && prevHost === host && prevClientId === clientId) {
|
|
return authInstance;
|
|
}
|
|
|
|
prevHost = host;
|
|
prevClientId = clientId;
|
|
|
|
authInstance = new Auth({
|
|
authType: AuthType.OAuth2,
|
|
host,
|
|
clientId,
|
|
redirectUri: `${returnToOrigin}/auth/login/callback`,
|
|
});
|
|
return authInstance;
|
|
};
|
|
|
|
const OAuthRouter = ({ originUrl }) => {
|
|
const router = express.Router();
|
|
|
|
let cachedHost = null;
|
|
let cachedClientId = null;
|
|
|
|
router.get('/oauth', async (req, res) => {
|
|
const { host: qHost, clientId: qClientId } = req.query;
|
|
if (!cachedHost && !cachedClientId) {
|
|
cachedHost = qHost;
|
|
cachedClientId = qClientId;
|
|
}
|
|
|
|
const returnTo = `${req.protocol}://${req.get('host')}`;
|
|
const instacne = getAuthInstance(returnTo, qHost, qClientId);
|
|
const isAuthorized = await instacne.isAuthorized();
|
|
if (!isAuthorized) {
|
|
const { url: redirectUrl } = await instacne.generateAuthorizationUrl();
|
|
res.status(200).json({ redirectUrl });
|
|
} else {
|
|
const reqHost = req.get('host');
|
|
const redirectUrl = `${req.protocol}://${reqHost}/app-list?engine_url=wss://${cachedHost}&qlik-client-id=${cachedClientId}&shouldFetchAppList=true`;
|
|
|
|
cachedHost = null;
|
|
cachedClientId = null;
|
|
|
|
res.redirect(redirectUrl);
|
|
}
|
|
});
|
|
|
|
router.get('/login/callback', async (req, res) => {
|
|
const authLink = new URL(req.url, `http://${req.headers.host}`).href;
|
|
try {
|
|
// TODO:
|
|
// this is a temp fix in nebula side
|
|
// (temp workaround of not presisting origin while backend tries to authorize user)
|
|
// they need to handle this in qlik-sdk-typescript repo
|
|
// and will notify us about when they got fixed it,
|
|
// but until then, we need to take care of it here!
|
|
authInstance.rest.interceptors.request.use((_req) => {
|
|
// eslint-disable-next-line no-param-reassign, dot-notation
|
|
_req[1]['headers'] = { origin: originUrl };
|
|
return _req;
|
|
});
|
|
await authInstance.authorize(authLink);
|
|
res.redirect(301, `/auth/oauth?host=${cachedHost}&clientId=${cachedClientId}`);
|
|
} catch (err) {
|
|
console.log({ err });
|
|
res.status(401).send({
|
|
message: 'Auth failed in callback redirecting, based on the provided auth link!',
|
|
});
|
|
}
|
|
});
|
|
|
|
router.get('/deauthorize', async (req, res) => {
|
|
try {
|
|
prevHost = null;
|
|
prevClientId = null;
|
|
authInstance = null;
|
|
|
|
cachedHost = null;
|
|
cachedClientId = null;
|
|
await authInstance?.deauthorize();
|
|
|
|
res.status(200).json({
|
|
deauthorize: true,
|
|
});
|
|
} catch (error) {
|
|
console.log({ error });
|
|
}
|
|
});
|
|
|
|
router.get('/isAuthorized', async (req, res) => {
|
|
if (!authInstance) {
|
|
res.status(200).json({
|
|
isAuthorized: false,
|
|
});
|
|
} else {
|
|
const isAuthorized = await authInstance.isAuthorized();
|
|
res.status(200).json({
|
|
isAuthorized,
|
|
});
|
|
}
|
|
});
|
|
|
|
router.get('/getSocketUrl/:appId', async (req, res) => {
|
|
const { appId } = req.params;
|
|
const webSocketUrl = await authInstance.generateWebsocketUrl(appId, true);
|
|
res.status(200).json({ webSocketUrl });
|
|
});
|
|
|
|
return router;
|
|
};
|
|
|
|
const getAvailableAuthInstance = () => authInstance;
|
|
|
|
module.exports = { OAuthRouter, getAvailableAuthInstance };
|