fix(core.gbapp): #387 adding /setupSecurity multiple tokens. @othonlima.

This commit is contained in:
Rodrigo Rodriguez 2023-11-19 17:56:13 -03:00
parent 863591741d
commit 6483f589ea
5 changed files with 124 additions and 71 deletions

View file

@ -383,12 +383,12 @@ export class AdminDialog extends IGBDialog {
min.dialogs.add( min.dialogs.add(
new WaterfallDialog('/setupSecurity', [ new WaterfallDialog('/setupSecurity', [
async step => { async step => {
const tokenName = step.activeDialog.state.tokenName = step.options['tokenName']; const tokenName = step.activeDialog.state.tokenName = step.options['args'];
if (tokenName) {
step.activeDialog.state.clientId = min.core.getParam<string>(min.instance, `${tokenName} Client ID`, null), step.activeDialog.state.clientId = min.core.getParam<string>(min.instance, `${tokenName} Client ID`, null),
step.activeDialog.state.clientSecret = min.core.getParam<string>(min.instance, `${tokenName} Client Secret`, null),
step.activeDialog.state.host = min.core.getParam<string>(min.instance, `${tokenName} Host`, null), step.activeDialog.state.host = min.core.getParam<string>(min.instance, `${tokenName} Host`, null),
step.activeDialog.state.tenant = min.core.getParam<string>(min.instance, `${tokenName} Tenant`, null) step.activeDialog.state.tenant = min.core.getParam<string>(min.instance, `${tokenName} Tenant`, null)
}
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) { if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
return await step.beginDialog('/auth'); return await step.beginDialog('/auth');
} else { } else {
@ -422,12 +422,7 @@ export class AdminDialog extends IGBDialog {
const tokenName = step.activeDialog.state.tokenName; const tokenName = step.activeDialog.state.tokenName;
if (tokenName){ if (!tokenName) {
step.activeDialog.state.clientId
step.activeDialog.state.clientSecret
step.activeDialog.state.tenant
}
else{
min.instance.authenticatorAuthorityHostUrl = step.activeDialog.state.authenticatorAuthorityHostUrl; min.instance.authenticatorAuthorityHostUrl = step.activeDialog.state.authenticatorAuthorityHostUrl;
min.instance.authenticatorTenant = step.activeDialog.state.authenticatorTenant; min.instance.authenticatorTenant = step.activeDialog.state.authenticatorTenant;
} }
@ -444,9 +439,14 @@ export class AdminDialog extends IGBDialog {
min.adminService.setValue(min.instance.instanceId, `${tokenName}AntiCSRFAttackState`, state); min.adminService.setValue(min.instance.instanceId, `${tokenName}AntiCSRFAttackState`, state);
const redirectUri = urlJoin(process.env.BOT_URL, min.instance.botId, `/token?value=${tokenName}`); const redirectUri = urlJoin(process.env.BOT_URL, min.instance.botId,
tokenName ? `/token?value=${tokenName}` : '/token');
const scope = tokenName ? '' : 'https://graph.microsoft.com/.default'; const scope = tokenName ? '' : 'https://graph.microsoft.com/.default';
const url = `https://login.microsoftonline.com/${step.activeDialog.state.authenticatorTenant}/oauth2/authorize?client_id=${min.instance.marketplaceId}&response_type=code&redirect_uri=${redirectUri}&scope=${scope}&state=${state}&response_mode=query`; const host = tokenName ? step.activeDialog.state.host : 'https://login.microsoftonline.com'
const tenant = tokenName ? step.activeDialog.state.tenant : min.instance.authenticatorTenant;
const clientId = tokenName ? step.activeDialog.state.clientId : min.instance.marketplaceId;
const oauth2 = tokenName ? 'oauth' : 'oauth2';
const url = `${host}/${tenant}/${oauth2}/authorize?client_id=${clientId}&response_type=code&redirect_uri=${redirectUri}&scope=${scope}&state=${state}&response_mode=query`;
await min.conversationalService.sendText(min, step, Messages[locale].consent(url)); await min.conversationalService.sendText(min, step, Messages[locale].consent(url));

View file

@ -231,7 +231,7 @@ export class GBAdminService implements IGBAdminService {
} }
public async acquireElevatedToken(instanceId: number, root: boolean = false, public async acquireElevatedToken(instanceId: number, root: boolean = false,
tokenName: string = null, tokenName: string = '',
clientId: string = null, clientId: string = null,
clientSecret: string = null, clientSecret: string = null,
host: string = null, host: string = null,
@ -259,20 +259,21 @@ export class GBAdminService implements IGBAdminService {
const accessToken = await this.getValue(instanceId, `${tokenName}accessToken`); const accessToken = await this.getValue(instanceId, `${tokenName}accessToken`);
resolve(accessToken); resolve(accessToken);
} else { } else {
const oauth2 = tokenName ? 'oauth' : 'oauth2';
const authorizationUrl = urlJoin( const authorizationUrl = urlJoin(
host ? host : instance.authenticatorAuthorityHostUrl, tokenName ? host : instance.authenticatorAuthorityHostUrl,
tenant ? tenant : instance.authenticatorTenant, tokenName ? tenant : instance.authenticatorTenant,
'/oauth2/authorize' `/${oauth2}/authorize`
); );
const refreshToken = await this.getValue(instanceId, `${tokenName}refreshToken`); const refreshToken = await this.getValue(instanceId, `${tokenName}refreshToken`);
const resource = clientId? '': 'https://graph.microsoft.com'; const resource = tokenName ? '' : 'https://graph.microsoft.com';
const authenticationContext = new AuthenticationContext(authorizationUrl); const authenticationContext = new AuthenticationContext(authorizationUrl);
authenticationContext.acquireTokenWithRefreshToken( authenticationContext.acquireTokenWithRefreshToken(
refreshToken, refreshToken,
clientId ? clientId : instance.marketplaceId, tokenName ? clientId : instance.marketplaceId,
clientId ? clientSecret : instance.marketplacePassword, tokenName ? clientSecret : instance.marketplacePassword,
resource, resource,
async (err, res) => { async (err, res) => {
if (err !== null) { if (err !== null) {

View file

@ -728,8 +728,9 @@ export class GBVMService extends GBService {
await CollectionUtil.asyncForEach(tokens,async t => { await CollectionUtil.asyncForEach(tokens,async t => {
const tokenName = t.replace(strFind, ''); const tokenName = t.replace(strFind, '');
try { try {
variables[t] = await (min.adminService as any)['acquireElevatedToken'] variables[tokenName] = await (min.adminService as any)['acquireElevatedToken']
(min.instance.instanceId, false, (min.instance.instanceId, false,
tokenName,
min.core.getParam<string>(min.instance, `${tokenName} Client ID`, null), min.core.getParam<string>(min.instance, `${tokenName} Client ID`, null),
min.core.getParam<string>(min.instance, `${tokenName} Client Secret`, null), min.core.getParam<string>(min.instance, `${tokenName} Client Secret`, null),
min.core.getParam<string>(min.instance, `${tokenName} Host`, null), min.core.getParam<string>(min.instance, `${tokenName} Host`, null),

View file

@ -695,6 +695,9 @@ ENDPOINT_UPDATE=true
value = minBoot.instance[name]; value = minBoot.instance[name];
} }
} }
if (value === undefined) {
value = null;
}
return value; return value;
} }
@ -710,7 +713,7 @@ ENDPOINT_UPDATE=true
} }
Object.keys(params).forEach(e => { Object.keys(params).forEach(e => {
if (criteria.toLowerCase().indexOf(e.toLowerCase())) { if (e.toLowerCase().indexOf(criteria.toLowerCase()) !== -1) {
list.push(e); list.push(e);
} }
}); });

View file

@ -490,9 +490,13 @@ export class GBMinService {
* on https://<gbhost>/<BotId>/token URL. * on https://<gbhost>/<BotId>/token URL.
*/ */
private handleOAuthTokenRequests(server: any, min: GBMinInstance, instance: IGBInstance) { private handleOAuthTokenRequests(server: any, min: GBMinInstance, instance: IGBInstance) {
server.get(`/${min.instance.botId}/token`, async (req, res) => { server.get(`/${min.instance.botId}/token`, async (req, res) => {
const tokenName = req.params['value']; let tokenName = req.query['value'];
if (!tokenName) {
tokenName = '';
}
// Checks request state by reading AntiCSRFAttackState from GB Admin infrastructure. // Checks request state by reading AntiCSRFAttackState from GB Admin infrastructure.
@ -503,17 +507,60 @@ export class GBMinService {
throw new Error(msg); throw new Error(msg);
} }
const clientId = min.core.getParam<string>(min.instance, `${tokenName} Client ID`, null), const clientId = min.core.getParam<string>(min.instance, `${tokenName} Client ID`, null);
const clientSecret = min.core.getParam<string>(min.instance, `${tokenName} Client Secret`, null), const clientSecret = min.core.getParam<string>(min.instance, `${tokenName} Client Secret`, null);
const host = min.core.getParam<string>(min.instance, `${tokenName} Host`, null), const host = min.core.getParam<string>(min.instance, `${tokenName} Host`, null);
const tenant = min.core.getParam<string>(min.instance, `${tokenName} Tenant`, null) const tenant = min.core.getParam<string>(min.instance, `${tokenName} Tenant`, null);
if (tokenName) {
const code = req?.query?.code;
let url = urlJoin(
host,
tenant, 'oauth/token');
let buff = new Buffer(`${clientId}:${clientSecret}`);
const base64 = buff.toString('base64');
const options = {
method: 'POST',
headers: {
Accept: '1.0',
Authorization: `Basic ${base64}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
'grant_type': 'authorization_code',
'code': code
})
};
const result = await fetch(url, options);
if (result.status != 200) {
throw new Error(`handleOAuthTokenRequests error: ${result.status}: ${result.statusText}.`)
}
const text = await result.text();
const token = JSON.parse(text);
// Saves token to the database.
await this.adminService.setValue(instance.instanceId,
`${tokenName}accessToken`, token['accessToken']?token['accessToken']:token['access_token']);
await this.adminService.setValue(instance.instanceId,
`${tokenName}refreshToken`, token['refreshToken']?token['refreshToken']:token['refresh_token']);
await this.adminService.setValue(instance.instanceId,
`${tokenName}expiresOn`, token['expiresOn']?token['expiresOn'].toString():token['expires_in'].toString());
await this.adminService.setValue(instance.instanceId, `${tokenName}AntiCSRFAttackState`, null);
}
else {
const authenticationContext = new AuthenticationContext.AuthenticationContext( const authenticationContext = new AuthenticationContext.AuthenticationContext(
urlJoin( urlJoin(
tokenName ? host : min.instance.authenticatorAuthorityHostUrl, tokenName ? host : min.instance.authenticatorAuthorityHostUrl,
tokenName ? tenant : min.instance.authenticatorTenant) tokenName ? tenant : min.instance.authenticatorTenant)
); );
const resource = tokenName ? '' : 'https://graph.microsoft.com'; const resource = 'https://graph.microsoft.com';
// Calls MSFT to get token. // Calls MSFT to get token.
@ -546,6 +593,7 @@ export class GBMinService {
} }
} }
); );
}
}); });
} }