Skip to content

Commit

Permalink
use client callback to update identity
Browse files Browse the repository at this point in the history
  • Loading branch information
luisthieme committed Nov 6, 2024
1 parent 4db23e4 commit 059ba7a
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 160 deletions.
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"examples": "examples"
},
"dependencies": {
"@5minds/processcube_engine_client": "^5.1.0",
"@5minds/processcube_engine_client": "5.1.0-hotfix-a73235-m346kg1n",
"jwt-decode": "^4.0.0",
"openid-client": "^5.5.0"
},
Expand Down
299 changes: 146 additions & 153 deletions processcube-engine-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,52 +12,8 @@ module.exports = function (RED) {
this.url = RED.util.evaluateNodeProperty(n.url, n.urlType, node);
this.identity = null;

async function startUpdatingCredentialsCycle() {
let retries = 5;
const UPDATE_INTERVAL = 10000;
let previousClientId, previousClientSecret;

const updateCredentials = async () => {
try {
const newClientId = RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node);
const newClientSecret = RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node);

if (newClientId !== previousClientId || newClientSecret !== previousClientSecret) {
if (this.engineClient) this.engineClient.dispose();

this.credentials.clientId = newClientId;
this.credentials.clientSecret = newClientSecret;

this.engineClient = new engine_client.EngineClient(this.url);

if (this.credentials.clientId && this.credentials.clientSecret) {
const authorityUrl = await this.engineClient.applicationInfo.getAuthorityAddress();
startRefreshingIdentityCycle(
this.credentials.clientId,
this.credentials.clientSecret,
authorityUrl,
node
).catch(console.error);
}

previousClientId = newClientId;
previousClientSecret = newClientSecret;
}

retries = 5;
setTimeout(updateCredentials, UPDATE_INTERVAL);
} catch (error) {
if (retries === 0) return console.error('Credential update failed permanently:', error);
console.error('Credential update error, retrying:', { error, retries });
retries--;
setTimeout(updateCredentials, 2000);
}
};

await updateCredentials();
}

console.log('luis888', this.credentials.clientId);
this.credentials.clientId = RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node);
this.credentials.clientSecret = RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node);

this.registerOnIdentityChanged = function (callback) {
identityChangedCallbacks.push(callback);
Expand All @@ -80,39 +36,76 @@ module.exports = function (RED) {
}
};

async function getFreshIdentity(url) {
console.log('luis777');
if (
!RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node) ||
!RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node)
)
return null;
const res = await fetch(url + '/atlas_engine/api/v1/authority', {
method: 'GET',
headers: {
Authorization: `Bearer ZHVtbXlfdG9rZW4=`,
'Content-Type': 'application/json',
},
});

const issuer = await oidc.Issuer.discover(await res.json());

const client = new issuer.Client({
client_id: RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node),
client_secret: RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node),
});

const tokenSet = await client.grant({
grant_type: 'client_credentials',
scope: 'engine_etw engine_read engine_write',
});

const accessToken = tokenSet.access_token;
const decodedToken = jwt.jwtDecode(accessToken);

const freshIdentity = {
token: tokenSet.access_token,
userId: decodedToken.sub,
};

configNode.setIdentity(freshIdentity);

return freshIdentity;
}

node.on('close', async () => {
if (this.engineClient) {
this.engineClient.dispose();
this.engineClient = null;
}
});

startUpdatingCredentialsCycle();

// if (this.credentials.clientId && this.credentials.clientSecret) {
// console.log('luis999', this.credentials.clientId);
// this.engineClient = new engine_client.EngineClient(this.url);

// this.engineClient.applicationInfo
// .getAuthorityAddress()
// .then((authorityUrl) => {
// startRefreshingIdentityCycle(
// this.credentials.clientId,
// this.credentials.clientSecret,
// authorityUrl,
// node
// ).catch((reason) => {
// console.error(reason);
// node.error(reason);
// });
// })
// .catch((reason) => {
// console.error(reason);
// node.error(reason);
// });
// } else {
// this.engineClient = new engine_client.EngineClient(this.url);
// }
if (this.credentials.clientId && this.credentials.clientSecret) {
this.engineClient = new engine_client.EngineClient(this.url, () => getFreshIdentity(this.url));

// this.engineClient.applicationInfo
// .getAuthorityAddress()
// .then((authorityUrl) => {
// startRefreshingIdentityCycle(
// this.credentials.clientId,
// this.credentials.clientSecret,
// authorityUrl,
// node
// ).catch((reason) => {
// console.error(reason);
// node.error(reason);
// });
// })
// .catch((reason) => {
// console.error(reason);
// node.error(reason);
// });
} else {
this.engineClient = new engine_client.EngineClient(this.url);
}
}
RED.nodes.registerType('processcube-engine-config', ProcessCubeEngineNode, {
credentials: {
Expand All @@ -122,84 +115,84 @@ module.exports = function (RED) {
});
};

async function getFreshTokenSet(clientId, clientSecret, authorityUrl) {
const issuer = await oidc.Issuer.discover(authorityUrl);

const client = new issuer.Client({
client_id: clientId,
client_secret: clientSecret,
});

const tokenSet = await client.grant({
grant_type: 'client_credentials',
scope: 'engine_etw engine_read engine_write',
});

return tokenSet;
}

function getIdentityForExternalTaskWorkers(tokenSet) {
const accessToken = tokenSet.access_token;
const decodedToken = jwt.jwtDecode(accessToken);

return {
token: tokenSet.access_token,
userId: decodedToken.sub,
};
}

async function getExpiresInForExternalTaskWorkers(tokenSet) {
let expiresIn = tokenSet.expires_in;

if (!expiresIn && tokenSet.expires_at) {
expiresIn = Math.floor(tokenSet.expires_at - Date.now() / 1000);
}

if (expiresIn === undefined) {
throw new Error('Could not determine the time until the access token for external task workers expires');
}

return expiresIn;
}

/**
* Start refreshing the identity in regular intervals.
* @param {TokenSet | null} tokenSet The token set to refresh the identity for
* @returns {Promise<void>} A promise that resolves when the timer for refreshing the identity is initialized
* */
async function startRefreshingIdentityCycle(clientId, clientSecret, authorityUrl, configNode) {
let retries = 5;

const refresh = async () => {
try {
const newTokenSet = await getFreshTokenSet(clientId, clientSecret, authorityUrl);
const expiresIn = await getExpiresInForExternalTaskWorkers(newTokenSet);
const delay = expiresIn * DELAY_FACTOR * 1000;

freshIdentity = getIdentityForExternalTaskWorkers(newTokenSet);

configNode.setIdentity(freshIdentity);

retries = 5;
setTimeout(refresh, delay);
} catch (error) {
if (retries === 0) {
console.error(
'Could not refresh identity for external task worker processes. Stopping all external task workers.',
{ error }
);
return;
}
console.error('Could not refresh identity for external task worker processes.', {
error,
retryCount: retries,
});
retries--;

const delay = 2 * 1000;
setTimeout(refresh, delay);
}
};

await refresh();
}
// async function getFreshTokenSet(clientId, clientSecret, authorityUrl) {
// const issuer = await oidc.Issuer.discover(authorityUrl);

// const client = new issuer.Client({
// client_id: clientId,
// client_secret: clientSecret,
// });

// const tokenSet = await client.grant({
// grant_type: 'client_credentials',
// scope: 'engine_etw engine_read engine_write',
// });

// return tokenSet;
// }

// function getIdentityForExternalTaskWorkers(tokenSet) {
// const accessToken = tokenSet.access_token;
// const decodedToken = jwt.jwtDecode(accessToken);

// return {
// token: tokenSet.access_token,
// userId: decodedToken.sub,
// };
// }

// async function getExpiresInForExternalTaskWorkers(tokenSet) {
// let expiresIn = tokenSet.expires_in;

// if (!expiresIn && tokenSet.expires_at) {
// expiresIn = Math.floor(tokenSet.expires_at - Date.now() / 1000);
// }

// if (expiresIn === undefined) {
// throw new Error('Could not determine the time until the access token for external task workers expires');
// }

// return expiresIn;
// }

// /**
// * Start refreshing the identity in regular intervals.
// * @param {TokenSet | null} tokenSet The token set to refresh the identity for
// * @returns {Promise<void>} A promise that resolves when the timer for refreshing the identity is initialized
// * */
// async function startRefreshingIdentityCycle(clientId, clientSecret, authorityUrl, configNode) {
// let retries = 5;

// const refresh = async () => {
// try {
// const newTokenSet = await getFreshTokenSet(clientId, clientSecret, authorityUrl);
// const expiresIn = await getExpiresInForExternalTaskWorkers(newTokenSet);
// const delay = expiresIn * DELAY_FACTOR * 1000;

// freshIdentity = getIdentityForExternalTaskWorkers(newTokenSet);

// configNode.setIdentity(freshIdentity);

// retries = 5;
// setTimeout(refresh, delay);
// } catch (error) {
// if (retries === 0) {
// console.error(
// 'Could not refresh identity for external task worker processes. Stopping all external task workers.',
// { error }
// );
// return;
// }
// console.error('Could not refresh identity for external task worker processes.', {
// error,
// retryCount: retries,
// });
// retries--;

// const delay = 2 * 1000;
// setTimeout(refresh, delay);
// }
// };

// await refresh();
// }

0 comments on commit 059ba7a

Please sign in to comment.