Skip to content

[msal-node][#1] SilentFlow support in msal-common #1711

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 39 commits into from
Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
c201f97
Silent Flow request
sameerag May 24, 2020
42112cf
Merge branch 'msal-node-merge-request' into msal-node-cache-silentFlow
sameerag May 24, 2020
22b0dcb
add environment alias
sameerag May 27, 2020
1afc5e7
Merge branch 'msal-node-merge-request' into msal-node-cache-silentFlow
sameerag May 27, 2020
9dfb0e0
SilentFlow changes
sameerag May 27, 2020
c39ce36
Merge branch 'msal-node-merge-request' into msal-node-cache-silentFlow
sameerag May 27, 2020
728887e
Add error for no account case
sameerag May 27, 2020
5da49cf
Merge branch 'msal-node-merge-request' into msal-node-cache-silentFlow
sameerag Jun 4, 2020
c2db28d
Merge branch 'msal-node-cache-lookup-interface' into msal-node-cache-…
sameerag Jun 4, 2020
2f59909
node compilation issues
sameerag Jun 4, 2020
5da21aa
Merge branch 'msal-node-merge-request' into msal-node-cache-silentFlow
sameerag Jun 4, 2020
8dcfa4b
Introduce IAccount and stabilize Storage interface
sameerag Jun 8, 2020
aaa8e73
IAccount, UnifiedCacheManager modified for generalCache
sameerag Jun 8, 2020
a6d5203
Merge branch 'dev' into msal-node-cache-silentFlow
sameerag Jun 8, 2020
61be9c5
updating lookup to check values instead of keys
sameerag Jun 8, 2020
f7765d5
save uid and utid in the cache unencoded
sameerag Jun 8, 2020
112b417
Fix lookups
sameerag Jun 9, 2020
1443cfa
fixing linter
sameerag Jun 9, 2020
dd9b4bb
remove unused getCacheType
sameerag Jun 9, 2020
6fc0fc0
Silent works / logout works (tested in browser with a PR #1762 built …
sameerag Jun 9, 2020
2537441
Merge branch 'dev' into msal-node-cache-silentFlow
sameerag Jun 10, 2020
a93a41a
Merge branch 'dev' into msal-node-cache-silentFlow
Jun 11, 2020
758ad3f
common tests passing
pkanher617 Jun 13, 2020
3e2b5f1
browser tests passing
pkanher617 Jun 13, 2020
0711093
Update ICacheStorage.ts
pkanher617 Jun 13, 2020
500009f
fixing e2e tests
pkanher617 Jun 15, 2020
976c9e3
Merge branch 'dev' into msal-node-cache-silentFlow
pkanher617 Jun 15, 2020
448b18c
Update sdl-tasks.yml
pkanher617 Jun 15, 2020
62bd83e
Update sdl-tasks.yml
pkanher617 Jun 15, 2020
f22e821
skipping credscan
pkanher617 Jun 15, 2020
ae72882
Update multiple_resources.spec.ts
pkanher617 Jun 15, 2020
247fbf4
Update multiple_resources.spec.ts
pkanher617 Jun 15, 2020
eabc014
Adding feedback from PR
pkanher617 Jun 15, 2020
2108ad6
Merge branch 'dev' into msal-node-cache-silentFlow
pkanher617 Jun 15, 2020
ae20863
Fixing token expiration logic
pkanher617 Jun 15, 2020
b0a20b3
Update SilentFlowClient.ts
pkanher617 Jun 15, 2020
43389e2
Update PopupHandler.spec.ts
pkanher617 Jun 15, 2020
da998f7
Merge branch 'dev' into msal-node-cache-silentFlow
pkanher617 Jun 15, 2020
a156fcf
Update sdl-tasks.yml
pkanher617 Jun 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions build/sdl-tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ steps:
optionsXS: 1
optionsHMENABLE: 0

# - task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@3
# displayName: 'Run CredScan3'
# inputs:
# scanFolder: './'
# debugMode: false
- task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@3
displayName: 'Run CredScan3'
inputs:
scanFolder: './'
debugMode: false

- task: securedevelopmentteam.vss-secure-development-tools.build-task-postanalysis.PostAnalysis@1
displayName: 'Post Analysis'
Expand Down
51 changes: 26 additions & 25 deletions lib/msal-browser/src/app/PublicClientApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License.
*/
import {
Account,
IAccount,
SPAClient,
INetworkModule,
TokenResponse,
Expand All @@ -23,7 +23,10 @@ import {
AuthorizationCodeRequest,
Constants,
ClientAuthError,
AuthorityType
AuthorityType,
AuthenticationResult,
SilentFlowRequest,
AccountEntity
} from "@azure/msal-common";
import { buildConfiguration, Configuration } from "../config/Configuration";
import { BrowserStorage } from "../cache/BrowserStorage";
Expand Down Expand Up @@ -57,7 +60,7 @@ export class PublicClientApplication {
private readonly networkClient: INetworkModule;

// Response promise
private readonly tokenExchangePromise: Promise<TokenResponse>;
private readonly tokenExchangePromise: Promise<AuthenticationResult>;

// Input configuration by developer/user
private config: Configuration;
Expand Down Expand Up @@ -182,7 +185,7 @@ export class PublicClientApplication {
* auth flows.
* @returns token response or null. If the return value is null, then no auth redirect was detected.
*/
async handleRedirectPromise(): Promise<TokenResponse | null> {
async handleRedirectPromise(): Promise<AuthenticationResult | null> {
return this.tokenExchangePromise;
}

Expand All @@ -191,7 +194,7 @@ export class PublicClientApplication {
* - if true, performs logic to cache and navigate
* - if false, handles hash string and parses response
*/
private async handleRedirectResponse(): Promise<TokenResponse> {
private async handleRedirectResponse(): Promise<AuthenticationResult> {
// Get current location hash from window or cache.
const {location: {hash}} = window;
const cachedHash = this.browserStorage.getItem(TemporaryCacheKeys.URL_HASH);
Expand Down Expand Up @@ -244,7 +247,7 @@ export class PublicClientApplication {
* @param responseHash
* @param interactionHandler
*/
private async handleHash(responseHash: string): Promise<TokenResponse> {
private async handleHash(responseHash: string): Promise<AuthenticationResult> {
const interactionHandler = new RedirectHandler(this.authModule, this.browserStorage);
if (!StringUtils.isEmpty(responseHash)) {
// Hash contains known properties - handle and return in callback
Expand Down Expand Up @@ -328,9 +331,9 @@ export class PublicClientApplication {
*
* @param {@link (AuthenticationParameters:type)}
*
* @returns {Promise.<TokenResponse>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
* @returns {Promise.<AuthenticationResult>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
*/
async loginPopup(request: AuthorizationUrlRequest): Promise<TokenResponse> {
async loginPopup(request: AuthorizationUrlRequest): Promise<AuthenticationResult> {
try {
// Preflight request
const validRequest: AuthorizationUrlRequest = this.preflightRequest(request);
Expand All @@ -354,9 +357,9 @@ export class PublicClientApplication {
* @param {@link AuthenticationParameters}
*
* To acquire only idToken, please pass clientId as the only scope in the Authentication Parameters
* @returns {Promise.<TokenResponse>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
* @returns {Promise.<AuthenticationResult>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
*/
async acquireTokenPopup(request: AuthorizationUrlRequest): Promise<TokenResponse> {
async acquireTokenPopup(request: AuthorizationUrlRequest): Promise<AuthenticationResult> {
try {
// Preflight request
const validRequest: AuthorizationUrlRequest = this.preflightRequest(request);
Expand All @@ -379,7 +382,7 @@ export class PublicClientApplication {
* Helper which acquires an authorization code with a popup from given url, and exchanges the code for a set of OAuth tokens.
* @param navigateUrl
*/
private async popupTokenHelper(navigateUrl: string, authCodeRequest: AuthorizationCodeRequest): Promise<TokenResponse> {
private async popupTokenHelper(navigateUrl: string, authCodeRequest: AuthorizationCodeRequest): Promise<AuthenticationResult> {
// Create popup interaction handler.
const interactionHandler = new PopupHandler(this.authModule, this.browserStorage);
// Show the UI once the url has been created. Get the window handle for the popup.
Expand All @@ -405,12 +408,12 @@ export class PublicClientApplication {
*
* If your refresh token has expired, you can use this function to fetch a new set of tokens silently as long as
* you session on the server still exists.
* @param {@link AuthenticationParameters}
* @param {@link AuthorizationUrlRequest}
*
* To renew idToken, please pass clientId as the only scope in the Authentication Parameters.
* @returns {Promise.<TokenResponse>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
* @returns {Promise.<AuthenticationResult>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
*/
async ssoSilent(request: AuthorizationUrlRequest): Promise<TokenResponse> {
async ssoSilent(request: AuthorizationUrlRequest): Promise<AuthenticationResult> {
// block the reload if it occurred inside a hidden iframe
BrowserUtils.blockReloadInHiddenIframes();

Expand Down Expand Up @@ -454,19 +457,18 @@ export class PublicClientApplication {
* @returns {Promise.<TokenResponse>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
*
*/
async acquireTokenSilent(silentRequest: TokenRenewParameters): Promise<TokenResponse> {
async acquireTokenSilent(silentRequest: SilentFlowRequest): Promise<AuthenticationResult> {
// block the reload if it occurred inside a hidden iframe
BrowserUtils.blockReloadInHiddenIframes();

const tokenRequest: AuthorizationUrlRequest = {
...silentRequest,
redirectUri: "",
scopes: silentRequest.scopes || []
};

try {
// Send request to renew token. Auth module will throw errors if token cannot be renewed.
return await this.authModule.getValidToken(tokenRequest, silentRequest.account, silentRequest.forceRefresh);
return await this.authModule.getValidToken(silentRequest);
} catch (e) {
const isServerError = e instanceof ServerError;
const isInteractionRequiredError = e instanceof InteractionRequiredAuthError;
Expand Down Expand Up @@ -499,7 +501,7 @@ export class PublicClientApplication {
* @param navigateUrl
* @param userRequestScopes
*/
private async silentTokenHelper(navigateUrl: string, authCodeRequest: AuthorizationCodeRequest, userRequestScopes: string): Promise<TokenResponse> {
private async silentTokenHelper(navigateUrl: string, authCodeRequest: AuthorizationCodeRequest, userRequestScopes: string): Promise<AuthenticationResult> {
try {
// Create silent handler
const silentHandler = new SilentHandler(this.authModule, this.browserStorage, this.config.system.loadFrameTimeout);
Expand All @@ -522,9 +524,9 @@ export class PublicClientApplication {
* Use to log out the current user, and redirect the user to the postLogoutRedirectUri.
* Default behaviour is to redirect the user to `window.location.href`.
*/
logout(): void {
logout(accountObj: IAccount): void {
// create logout string and navigate user window to logout. Auth module will clear cache.
this.authModule.logout().then((logoutUri: string) => {
this.authModule.logout(accountObj, this.defaultAuthorityInstance).then((logoutUri: string) => {
BrowserUtils.navigateWindow(logoutUri);
});
}
Expand Down Expand Up @@ -560,8 +562,8 @@ export class PublicClientApplication {
* or null when no state is found
* @returns {@link Account} - the account object stored in MSAL
*/
public getAccount(): Account {
return this.authModule.getAccount();
public getAccount(homeAccountId: string): AccountEntity {
return this.authModule.getAccount(homeAccountId);
}

// #endregion
Expand Down Expand Up @@ -599,10 +601,9 @@ export class PublicClientApplication {
const validatedRequest: AuthorizationUrlRequest = {
...request
};

const cachedAccount = this.getAccount();

// Check for ADAL SSO
if (StringUtils.isEmpty(validatedRequest.loginHint) && !cachedAccount) {
if (StringUtils.isEmpty(validatedRequest.loginHint)) {
// Only check for adal token if no SSO params are being used
const adalIdTokenString = this.browserStorage.getItem(PersistentCacheKeys.ADAL_ID_TOKEN);
if (!StringUtils.isEmpty(adalIdTokenString)) {
Expand Down
12 changes: 3 additions & 9 deletions lib/msal-browser/src/cache/BrowserStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { ICacheStorage, Constants, PersistentCacheKeys, InMemoryCache, StringUtils, AuthorizationCodeRequest, ICrypto } from "@azure/msal-common";
import { ICacheStorage, Constants, PersistentCacheKeys, StringUtils, AuthorizationCodeRequest, ICrypto } from "@azure/msal-common";
import { CacheOptions } from "../config/Configuration";
import { BrowserAuthError } from "../error/BrowserAuthError";
import { BrowserConfigurationAuthError } from "../error/BrowserConfigurationAuthError";
Expand Down Expand Up @@ -256,14 +256,8 @@ export class BrowserStorage implements ICacheStorage {
/**
* Dummy implementation until browser cache is migrated
*/
getCache(): InMemoryCache {
return {
accounts: {},
idTokens: {},
accessTokens: {},
refreshTokens: {},
appMetadata: {}
};
getCache(): object {
return this.windowStorage;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { SPAClient, TokenResponse, StringUtils, AuthorizationCodeRequest, ProtocolUtils } from "@azure/msal-common";
import { SPAClient, TokenResponse, StringUtils, AuthorizationCodeRequest, ProtocolUtils, AuthenticationResult } from "@azure/msal-common";
import { BrowserStorage } from "../cache/BrowserStorage";
import { BrowserAuthError } from "../error/BrowserAuthError";
import { TemporaryCacheKeys } from "../utils/BrowserConstants";
Expand Down Expand Up @@ -31,7 +31,7 @@ export abstract class InteractionHandler {
* Function to handle response parameters from hash.
* @param locationHash
*/
async handleCodeResponse(locationHash: string): Promise<TokenResponse> {
async handleCodeResponse(locationHash: string): Promise<AuthenticationResult> {
// Check that location hash isn't empty.
if (StringUtils.isEmpty(locationHash)) {
throw BrowserAuthError.createEmptyHashError(locationHash);
Expand Down
4 changes: 2 additions & 2 deletions lib/msal-browser/src/interaction_handler/RedirectHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { StringUtils, TokenResponse, AuthorizationCodeRequest, ICrypto, ProtocolUtils } from "@azure/msal-common";
import { StringUtils, TokenResponse, AuthorizationCodeRequest, ICrypto, ProtocolUtils, AuthenticationResult } from "@azure/msal-common";
import { InteractionHandler } from "./InteractionHandler";
import { BrowserAuthError } from "../error/BrowserAuthError";
import { BrowserConstants, TemporaryCacheKeys } from "../utils/BrowserConstants";
Expand Down Expand Up @@ -42,7 +42,7 @@ export class RedirectHandler extends InteractionHandler {
* Handle authorization code response in the window.
* @param hash
*/
async handleCodeResponse(locationHash: string, browserCrypto?: ICrypto): Promise<TokenResponse> {
async handleCodeResponse(locationHash: string, browserCrypto?: ICrypto): Promise<AuthenticationResult> {
// Check that location hash isn't empty.
if (StringUtils.isEmpty(locationHash)) {
throw BrowserAuthError.createEmptyHashError(locationHash);
Expand Down
4 changes: 2 additions & 2 deletions lib/msal-browser/src/types/AuthCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { AuthError, TokenResponse } from "@azure/msal-common";
import { AuthError, AuthenticationResult } from "@azure/msal-common";

/**
* A type alias for an authResponseCallback function.
* {@link (authResponseCallback:type)}
* @param authErr error created for failure cases
* @param response response containing token strings in success cases, or just state value in error cases
*/
export type AuthCallback = (authErr: AuthError, response?: TokenResponse) => void;
export type AuthCallback = (authErr: AuthError, response?: AuthenticationResult) => void;
Loading