Skip to content

Commit

Permalink
Merge branch 'main' into julong/skill-supplement
Browse files Browse the repository at this point in the history
  • Loading branch information
alanlong9278 authored Apr 30, 2021
2 parents e2c7c3e + a3f796f commit 489be5f
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ describe('OneAuth Serivce', () => {
id: 'myAccount',
realm: 'myTenant',
};

const tomorrow = Date.now() + 1000 * 60 * 60 * 24;
const mockCredential = {
expiresOn: 9999,
expiresOn: tomorrow,
value: 'someToken',
};
const mockOneAuth = {
Expand Down Expand Up @@ -255,15 +257,19 @@ describe('OneAuth Serivce', () => {
});

it('should get an ARM token for a tenant', async () => {
mockOneAuth.acquireCredentialSilently.mockReturnValueOnce({ credential: { value: 'someARMToken' } });
(oneAuthService as any).signedInARMAccount = {};
mockOneAuth.acquireCredentialSilently.mockReturnValueOnce({
credential: { value: 'someARMToken', expiresOn: tomorrow },
});
(oneAuthService as any).signedInARMAccount = { id: 'someAccount' };
const result = await oneAuthService.getARMTokenForTenant('someTenant');

expect(result).toBe('someARMToken');
});

it('should get an ARM token for a tenant interactively if interaction is required', async () => {
mockOneAuth.acquireCredentialInteractively.mockReturnValueOnce({ credential: { value: 'someARMToken' } });
mockOneAuth.acquireCredentialInteractively.mockReturnValueOnce({
credential: { value: 'someARMToken', expiresOn: tomorrow },
});
mockOneAuth.acquireCredentialSilently.mockRejectedValueOnce({ error: { status: 2 /* Interaction Required */ } });
(oneAuthService as any).signedInARMAccount = {};
const result = await oneAuthService.getARMTokenForTenant('someTenant');
Expand Down
89 changes: 57 additions & 32 deletions Composer/packages/electron-server/src/auth/oneAuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ export class OneAuthInstance extends OneAuthBase {
private _oneAuth: typeof OneAuth | null = null; //eslint-disable-line
private signedInAccount: OneAuth.Account | undefined;
private signedInARMAccount: OneAuth.Account | undefined;

/** Token solely used to fetch tenants */
private tenantToken: string | undefined;
private tenantTokenExpiresOn: number | undefined;

constructor() {
super();
Expand Down Expand Up @@ -192,13 +194,18 @@ export class OneAuthInstance extends OneAuthBase {
this.initialize();
}

if (!this.signedInARMAccount || !this.tenantToken) {
if (
!this.signedInARMAccount ||
!this.tenantToken ||
(this.tenantTokenExpiresOn && Date.now() >= this.tenantTokenExpiresOn)
) {
// log the user into the infrastructure tenant to get a token that can be used on the "tenants" API
log('Logging user into ARM...');
const signInParams = new this.oneAuth.AuthParameters(DEFAULT_AUTH_SCHEME, ARM_AUTHORITY, ARM_RESOURCE, '', '');
const result: OneAuth.AuthResult = await this.oneAuth.signInInteractively(undefined, signInParams, '');
this.signedInARMAccount = result.account;
this.tenantToken = result.credential.value;
this.tenantTokenExpiresOn = result.credential.expiresOn;
}

// call the tenants API
Expand All @@ -218,47 +225,64 @@ export class OneAuthInstance extends OneAuthBase {
if (!this.initialized) {
this.initialize();
}
// sign in arm account.

// if not signed into the ARM account, sign in.
if (!this.signedInARMAccount) {
const signInParams = new this.oneAuth.AuthParameters(DEFAULT_AUTH_SCHEME, ARM_AUTHORITY, ARM_RESOURCE, '', '');
const result: OneAuth.AuthResult = await this.oneAuth.signInInteractively(undefined, signInParams, '');
if (!result.account) {
return '';
}

this.signedInARMAccount = result.account;
}
if (this.signedInARMAccount) {
try {
log('Getting an ARM token for tenant %s', tenantId);
const tokenParams = new this.oneAuth.AuthParameters(
DEFAULT_AUTH_SCHEME,
`https://login.microsoftonline.com/${tenantId}`,
ARM_RESOURCE,
'',
''
);
const result = await this.oneAuth.acquireCredentialSilently(this.signedInARMAccount.id, tokenParams, '');

// try to get the tenant token silently
try {
log('Getting an ARM token for tenant %s', tenantId);
const tokenParams = new this.oneAuth.AuthParameters(
DEFAULT_AUTH_SCHEME,
`https://login.microsoftonline.com/${tenantId}`,
ARM_RESOURCE,
'',
''
);
const result = await this.oneAuth.acquireCredentialSilently(this.signedInARMAccount.id, tokenParams, '');
if (result.credential.value && Date.now() <= result.credential.expiresOn) {
log('Acquired ARM token for tenant: %s', result.credential.value);
return result.credential.value;
} catch (e) {
if (e.error?.status === Status.InteractionRequired) {
// try again but interactively
log('Acquiring ARM token failed: Interaction required. Trying again interactively to get access token.');
const tokenParams = new this.oneAuth.AuthParameters(
DEFAULT_AUTH_SCHEME,
`https://login.microsoftonline.com/${tenantId}`,
ARM_RESOURCE,
'',
''
);
const result = await this.oneAuth.acquireCredentialInteractively(this.signedInARMAccount.id, tokenParams, '');
if (result.credential && result.credential.value) {
log('Acquired access token interactively. %s', result.credential.value);
return result.credential.value;
}
}
log('There was an error trying to get an ARM token for tenant %s: %O', tenantId, e);
}
} catch (e) {
if (e.error?.status === Status.InteractionRequired) {
log(
'There was an error trying to silently get an ARM token for tenant %s: %O. Trying again interactively to get access token.',
tenantId,
e
);
} else {
throw e;
}
}
return '';

// get the tenant token interactively
try {
const tokenParams = new this.oneAuth.AuthParameters(
DEFAULT_AUTH_SCHEME,
`https://login.microsoftonline.com/${tenantId}`,
ARM_RESOURCE,
'',
''
);
const result = await this.oneAuth.acquireCredentialInteractively(this.signedInARMAccount.id, tokenParams, '');
if (!result.credential.value) {
throw new Error('Interactive sign on returned an empty credential value.');
}
log('Acquired ARM token for tenant: %s', result.credential.value);
return result.credential.value;
} catch (e) {
log('There was an error trying to get an ARM token interactively for tenant %s: %O', tenantId, e);
throw e;
}
}

public shutdown() {
Expand All @@ -275,6 +299,7 @@ export class OneAuthInstance extends OneAuthBase {
this.signedInAccount = undefined;
this.signedInARMAccount = undefined;
this.tenantToken = undefined;
this.tenantTokenExpiresOn = undefined;
log('Signed out user.');
}

Expand Down

0 comments on commit 489be5f

Please sign in to comment.