Skip to content

Commit

Permalink
When rendered in an iframe, silent rejects
Browse files Browse the repository at this point in the history
... with an appropriate error.
* Get rid of the decorator function because it is only used once
* Add EnvironmentError
* tests

resolves #902
  • Loading branch information
DarylThayil committed Aug 2, 2019
1 parent 3288ca8 commit 394486f
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 23 deletions.
27 changes: 4 additions & 23 deletions lib/msal-core/src/UserAgentApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { InteractionRequiredAuthError } from "./error/InteractionRequiredAuthErr
import { AuthResponse, buildResponseStateOnly } from "./AuthResponse";
import TelemetryManager from "./telemetry/TelemetryManager";
import { TelemetryPlatform, TelemetryConfig } from './telemetry/TelemetryTypes';
import { EnvironmentError } from "./error/EnvironmentError";


// default authority
Expand Down Expand Up @@ -111,27 +112,6 @@ export type tokenReceivedCallback = (response: AuthResponse) => void;
*/
export type errorReceivedCallback = (authErr: AuthError, accountState: string) => void;

/**
* @hidden
* @ignore
* A wrapper to handle the token response/error within the iFrame always
*
* @param target
* @param propertyKey
* @param descriptor
*/
const resolveTokenOnlyIfOutOfIframe = (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
const tokenAcquisitionMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
return this.isInIframe()
? new Promise(() => {
return;
})
: tokenAcquisitionMethod.apply(this, args);
};
return descriptor;
};

/**
* UserAgentApplication class
*
Expand Down Expand Up @@ -561,13 +541,14 @@ export class UserAgentApplication {
* @returns {Promise.<AuthResponse>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
*
*/
@resolveTokenOnlyIfOutOfIframe
acquireTokenSilent(request: AuthenticationParameters): Promise<AuthResponse> {
if (!request) {
throw ClientConfigurationError.createEmptyRequestError();
}
return new Promise<AuthResponse>((resolve, reject) => {

if (this.isInIframe()) {
reject(EnvironmentError.createNoResolveInIframeError());
}
// Validate and filter scopes (the validate function will throw if validation fails)
this.validateInputScope(request.scopes, true);

Expand Down
33 changes: 33 additions & 0 deletions lib/msal-core/src/error/EnvironmentError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { AuthError } from "./AuthError";
import { IdToken } from "../IdToken";
import { StringUtils } from "../utils/StringUtils";

export const EnvironmentErrorMessage = {
noResolveInIframe: {
code: "no_resolve_in_iframe",
desc: `Msal.js does not currently support resolving a silent token request in an iframe`
}
};

/**
* Error thrown when there is an error in the client code running on the browser.
*/
export class EnvironmentError extends AuthError {

constructor(errorCode: string, errorMessage?: string) {
super(errorCode, errorMessage);
this.name = "EnvironmentError";

Object.setPrototypeOf(this, EnvironmentError.prototype);
}

static createNoResolveInIframeError(): EnvironmentError {
const { code, desc } = EnvironmentErrorMessage.noResolveInIframe
return new EnvironmentError(code, desc);
}


}
26 changes: 26 additions & 0 deletions lib/msal-core/test/UserAgentApplication.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { ServerRequestParameters } from "../src/ServerRequestParameters";
import { TEST_URIS, TEST_DATA_CLIENT_INFO, TEST_HASHES, TEST_TOKENS, TEST_CONFIG, TEST_TOKEN_LIFETIMES } from "./TestConstants";
import { IdToken } from "../src/IdToken";
import { TimeUtils } from "../src/utils/TimeUtils";
import { EnvironmentError } from "../src/error/EnvironmentError";

type kv = {
[key: string]: string;
Expand Down Expand Up @@ -1416,4 +1417,29 @@ describe("UserAgentApplication.ts Class", function () {
});

});


describe("iframe resolution of silent token request", () => {
beforeEach(function() {
const config: Configuration = {
auth: {
clientId: TEST_CONFIG.MSAL_CLIENT_ID,
redirectUri: TEST_URIS.TEST_REDIR_URI
}
};
msal = new UserAgentApplication(config);
});
it("throws an EnvironmentError if rendred in an iframe", done => {
sinon.stub(msal, "isInIframe").returns(true);
msal.acquireTokenSilent({scopes: [TEST_CONFIG.MSAL_CLIENT_ID]})
.then(() => {
done("acquireTokenSilent Should not resolve if rendered in an iframe");``
})
.catch((err) => {
expect(err).to.be.instanceOf(EnvironmentError);
done();
});
});
});
});

50 changes: 50 additions & 0 deletions lib/msal-core/test/error/EnvironmentError.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as mocha from "mocha";
import { expect } from "chai";
import { EnvironmentError, EnvironmentErrorMessage } from "../../src/error/EnvironmentError";
import { AuthError } from "../../src";

describe("EnvironmentError.ts Class", () => {
it("EnvironmentError object can be created", () => {

const TEST_ERROR_CODE: string = "test";
const TEST_ERROR_MSG: string = "This is a test error";
let environmentError = new EnvironmentError(TEST_ERROR_CODE, TEST_ERROR_MSG);
let err: EnvironmentError;

try {
throw environmentError;
} catch (error) {
err = error;
}

expect(err instanceof EnvironmentError).to.be.true;
expect(err instanceof AuthError).to.be.true;
expect(err instanceof Error).to.be.true;
expect(err.errorCode).to.equal(TEST_ERROR_CODE);
expect(err.errorMessage).to.equal(TEST_ERROR_MSG);
expect(err.message).to.equal(TEST_ERROR_MSG);
expect(err.name).to.equal("EnvironmentError");
expect(err.stack).to.include("EnvironmentError.spec.js");
});

it("createNoResolveInIframeError creates a EnvironmentError object", () => {

const serverUnavailableError = EnvironmentError.createNoResolveInIframeError();
let err: EnvironmentError;

try {
throw serverUnavailableError;
} catch (error) {
err = error;
}

expect(err.errorCode).to.equal(EnvironmentErrorMessage.noResolveInIframe.code);
expect(err.errorMessage).to.equal(EnvironmentErrorMessage.noResolveInIframe.desc);
expect(err.message).to.equal(EnvironmentErrorMessage.noResolveInIframe.desc);
expect(err.name).to.equal("EnvironmentError");
expect(err.stack).to.include("EnvironmentError.spec.js");
});


});

0 comments on commit 394486f

Please sign in to comment.