fix(core.gbapp): #387 adding /setupSecurity multiple tokens. @othonlima.
This commit is contained in:
parent
863591741d
commit
6483f589ea
5 changed files with 124 additions and 71 deletions
|
@ -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'];
|
||||||
step.activeDialog.state.clientId = min.core.getParam<string>(min.instance, `${tokenName} Client ID`, null),
|
if (tokenName) {
|
||||||
step.activeDialog.state.clientSecret = min.core.getParam<string>(min.instance, `${tokenName} Client Secret`, null),
|
step.activeDialog.state.clientId = min.core.getParam<string>(min.instance, `${tokenName} Client ID`, 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,20 +422,15 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
await min.adminService.updateSecurityInfo(
|
await min.adminService.updateSecurityInfo(
|
||||||
min.instance.instanceId,
|
min.instance.instanceId,
|
||||||
tokenName? step.activeDialog.state.tenant:step.activeDialog.state.authenticatorTenant,
|
tokenName ? step.activeDialog.state.tenant : step.activeDialog.state.authenticatorTenant,
|
||||||
tokenName?step.activeDialog.state.host:step.activeDialog.state.authenticatorAuthorityHostUrl
|
tokenName ? step.activeDialog.state.host : step.activeDialog.state.authenticatorAuthorityHostUrl
|
||||||
);
|
);
|
||||||
|
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
|
@ -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,
|
||||||
const scope = tokenName?'': 'https://graph.microsoft.com/.default';
|
tokenName ? `/token?value=${tokenName}` : '/token');
|
||||||
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 scope = tokenName ? '' : 'https://graph.microsoft.com/.default';
|
||||||
|
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));
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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,49 +507,93 @@ 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);
|
||||||
|
|
||||||
const authenticationContext = new AuthenticationContext.AuthenticationContext(
|
if (tokenName) {
|
||||||
urlJoin(
|
const code = req?.query?.code;
|
||||||
tokenName ? host : min.instance.authenticatorAuthorityHostUrl,
|
|
||||||
tokenName ? tenant : min.instance.authenticatorTenant)
|
|
||||||
);
|
|
||||||
const resource = tokenName ? '' : 'https://graph.microsoft.com';
|
|
||||||
|
|
||||||
// Calls MSFT to get token.
|
let url = urlJoin(
|
||||||
|
host,
|
||||||
|
tenant, 'oauth/token');
|
||||||
|
let buff = new Buffer(`${clientId}:${clientSecret}`);
|
||||||
|
const base64 = buff.toString('base64');
|
||||||
|
|
||||||
authenticationContext.acquireTokenWithAuthorizationCode(
|
const options = {
|
||||||
req.query.code,
|
method: 'POST',
|
||||||
urlJoin(process.env.BOT_URL, min.instance.botId, '/token'),
|
headers: {
|
||||||
resource,
|
Accept: '1.0',
|
||||||
tokenName ? clientId : instance.marketplaceId,
|
Authorization: `Basic ${base64}`,
|
||||||
tokenName ? clientSecret : instance.marketplacePassword,
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
async (err, token) => {
|
},
|
||||||
if (err) {
|
body: new URLSearchParams({
|
||||||
|
'grant_type': 'authorization_code',
|
||||||
|
'code': code
|
||||||
|
})
|
||||||
|
};
|
||||||
|
const result = await fetch(url, options);
|
||||||
|
|
||||||
const msg = `handleOAuthTokenRequests: Error acquiring token: ${err}`;
|
if (result.status != 200) {
|
||||||
|
throw new Error(`handleOAuthTokenRequests error: ${result.status}: ${result.statusText}.`)
|
||||||
GBLog.error(msg);
|
|
||||||
res.send(msg);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Saves token to the database.
|
|
||||||
|
|
||||||
await this.adminService.setValue(instance.instanceId, `${tokenName}accessToken`, token['accessToken']);
|
|
||||||
await this.adminService.setValue(instance.instanceId, `${tokenName}refreshToken`, token['refreshToken']);
|
|
||||||
await this.adminService.setValue(instance.instanceId, `${tokenName}expiresOn`, token['expiresOn'].toString());
|
|
||||||
await this.adminService.setValue(instance.instanceId, `${tokenName}AntiCSRFAttackState`, null);
|
|
||||||
|
|
||||||
// Inform the home for default .gbui after finishing token retrival.
|
|
||||||
|
|
||||||
res.redirect(process.env.BOT_URL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
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(
|
||||||
|
urlJoin(
|
||||||
|
tokenName ? host : min.instance.authenticatorAuthorityHostUrl,
|
||||||
|
tokenName ? tenant : min.instance.authenticatorTenant)
|
||||||
|
);
|
||||||
|
const resource = 'https://graph.microsoft.com';
|
||||||
|
|
||||||
|
// Calls MSFT to get token.
|
||||||
|
|
||||||
|
authenticationContext.acquireTokenWithAuthorizationCode(
|
||||||
|
req.query.code,
|
||||||
|
urlJoin(process.env.BOT_URL, min.instance.botId, '/token'),
|
||||||
|
resource,
|
||||||
|
tokenName ? clientId : instance.marketplaceId,
|
||||||
|
tokenName ? clientSecret : instance.marketplacePassword,
|
||||||
|
async (err, token) => {
|
||||||
|
if (err) {
|
||||||
|
|
||||||
|
const msg = `handleOAuthTokenRequests: Error acquiring token: ${err}`;
|
||||||
|
|
||||||
|
GBLog.error(msg);
|
||||||
|
res.send(msg);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Saves token to the database.
|
||||||
|
|
||||||
|
await this.adminService.setValue(instance.instanceId, `${tokenName}accessToken`, token['accessToken']);
|
||||||
|
await this.adminService.setValue(instance.instanceId, `${tokenName}refreshToken`, token['refreshToken']);
|
||||||
|
await this.adminService.setValue(instance.instanceId, `${tokenName}expiresOn`, token['expiresOn'].toString());
|
||||||
|
await this.adminService.setValue(instance.instanceId, `${tokenName}AntiCSRFAttackState`, null);
|
||||||
|
|
||||||
|
// Inform the home for default .gbui after finishing token retrival.
|
||||||
|
|
||||||
|
res.redirect(process.env.BOT_URL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue