Skip to content

Commit 7d13c0d

Browse files
authored
EAR Protocol Request (#7633)
Adds protocol implementation (request properties and generation and response properties) for the new EAR flow. Response handling will be added in a separate PR as this one is already fairly large
1 parent 68e963c commit 7d13c0d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+848
-325
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Fix request type for ssoSilent",
4+
"packageName": "@azure/msal-angular",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "minor",
3+
"comment": "EAR protocol request support",
4+
"packageName": "@azure/msal-browser",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "minor",
3+
"comment": "EAR protocol request support",
4+
"packageName": "@azure/msal-common",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Minor updates to Authorize query string generation",
4+
"packageName": "@azure/msal-node",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

Diff for: lib/msal-angular/src/IMsalService.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55

66
import {
77
EndSessionRequest,
8-
AuthorizationUrlRequest,
98
AuthenticationResult,
109
PopupRequest,
1110
RedirectRequest,
1211
SilentRequest,
1312
Logger,
13+
SsoSilentRequest,
1414
} from "@azure/msal-browser";
1515
import { Observable } from "rxjs";
1616

@@ -25,7 +25,7 @@ export interface IMsalService {
2525
loginPopup(request?: PopupRequest): Observable<AuthenticationResult>;
2626
loginRedirect(request?: RedirectRequest): Observable<void>;
2727
logout(logoutRequest?: EndSessionRequest): Observable<void>;
28-
ssoSilent(request: AuthorizationUrlRequest): Observable<AuthenticationResult>;
28+
ssoSilent(request: SsoSilentRequest): Observable<AuthenticationResult>;
2929
getLogger(): Logger;
3030
setLogger(logger: Logger): void;
3131
}

Diff for: lib/msal-browser/apiReview/msal-browser.api.md

+11-8
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,8 @@ export type AuthorizationCodeRequest = Partial<Omit<CommonAuthorizationCodeReque
126126

127127
// Warning: (ae-missing-release-tag) "AuthorizationUrlRequest" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
128128
//
129-
// @public
130-
export type AuthorizationUrlRequest = Omit<CommonAuthorizationUrlRequest, "state" | "nonce" | "requestedClaimsHash" | "platformBroker"> & {
131-
state: string;
132-
nonce: string;
133-
};
129+
// @public @deprecated
130+
export type AuthorizationUrlRequest = Omit<CommonAuthorizationUrlRequest, "requestedClaimsHash" | "platformBroker">;
134131

135132
// Warning: (ae-missing-release-tag) "authRequestNotSetError" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
136133
//
@@ -190,6 +187,7 @@ export class BrowserAuthError extends AuthError {
190187
declare namespace BrowserAuthErrorCodes {
191188
export {
192189
pkceNotCreated,
190+
earJwkEmpty,
193191
cryptoNonExistent,
194192
emptyNavigateUri,
195193
hashEmptyError,
@@ -718,6 +716,11 @@ const databaseUnavailable = "database_unavailable";
718716
// @public (undocumented)
719717
export const DEFAULT_IFRAME_TIMEOUT_MS = 10000;
720718

719+
// Warning: (ae-missing-release-tag) "earJwkEmpty" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
720+
//
721+
// @public (undocumented)
722+
const earJwkEmpty = "ear_jwk_empty";
723+
721724
// Warning: (ae-missing-release-tag) "emptyNavigateUri" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
722725
//
723726
// @public (undocumented)
@@ -1338,7 +1341,7 @@ export type PopupPosition = {
13381341
// Warning: (ae-missing-release-tag) "PopupRequest" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
13391342
//
13401343
// @public
1341-
export type PopupRequest = Partial<Omit<CommonAuthorizationUrlRequest, "responseMode" | "scopes" | "codeChallenge" | "codeChallengeMethod" | "requestedClaimsHash" | "platformBroker">> & {
1344+
export type PopupRequest = Partial<Omit<CommonAuthorizationUrlRequest, "responseMode" | "scopes" | "earJwk" | "codeChallenge" | "codeChallengeMethod" | "requestedClaimsHash" | "platformBroker">> & {
13421345
scopes: Array<string>;
13431346
popupWindowAttributes?: PopupWindowAttributes;
13441347
popupWindowParent?: Window;
@@ -1595,7 +1598,7 @@ function redirectPreflightCheck(initialized: boolean, config: BrowserConfigurati
15951598
// Warning: (ae-missing-release-tag) "RedirectRequest" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
15961599
//
15971600
// @public
1598-
export type RedirectRequest = Partial<Omit<CommonAuthorizationUrlRequest, "responseMode" | "scopes" | "codeChallenge" | "codeChallengeMethod" | "requestedClaimsHash" | "platformBroker">> & {
1601+
export type RedirectRequest = Partial<Omit<CommonAuthorizationUrlRequest, "responseMode" | "scopes" | "earJwk" | "codeChallenge" | "codeChallengeMethod" | "requestedClaimsHash" | "platformBroker">> & {
15991602
scopes: Array<string>;
16001603
redirectStartPage?: string;
16011604
onRedirectNavigate?: (url: string) => boolean | void;
@@ -1687,7 +1690,7 @@ const spaCodeAndNativeAccountIdPresent = "spa_code_and_nativeAccountId_present";
16871690
// Warning: (ae-missing-release-tag) "SsoSilentRequest" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
16881691
//
16891692
// @public
1690-
export type SsoSilentRequest = Partial<Omit<CommonAuthorizationUrlRequest, "responseMode" | "codeChallenge" | "codeChallengeMethod" | "requestedClaimsHash" | "platformBroker">>;
1693+
export type SsoSilentRequest = Partial<Omit<CommonAuthorizationUrlRequest, "responseMode" | "earJwk" | "codeChallenge" | "codeChallengeMethod" | "requestedClaimsHash" | "platformBroker">>;
16911694

16921695
// Warning: (ae-missing-release-tag) "stateInteractionTypeMismatch" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
16931696
//

Diff for: lib/msal-browser/src/config/Configuration.ts

+14-2
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,10 @@ export function buildConfiguration(
377377
);
378378
}
379379

380-
// Throw an error if user has set allowPlatformBroker to true without being in AAD protocol mode
380+
// Throw an error if user has set allowPlatformBroker to true with OIDC protocol mode
381381
if (
382382
userInputAuth?.protocolMode &&
383-
userInputAuth.protocolMode !== ProtocolMode.AAD &&
383+
userInputAuth.protocolMode === ProtocolMode.OIDC &&
384384
providedSystemOptions?.allowPlatformBroker
385385
) {
386386
throw createClientConfigurationError(
@@ -402,5 +402,17 @@ export function buildConfiguration(
402402
telemetry: { ...DEFAULT_TELEMETRY_OPTIONS, ...userInputTelemetry },
403403
};
404404

405+
/**
406+
* Temporarily disable EAR until implementation is complete
407+
* TODO: Remove this
408+
*/
409+
if (overlayedConfig.auth.protocolMode === ProtocolMode.EAR) {
410+
const logger = new Logger(providedSystemOptions.loggerOptions);
411+
logger.warning(
412+
"EAR Protocol Mode is not yet supported. Overriding to use PKCE auth"
413+
);
414+
overlayedConfig.auth.protocolMode = ProtocolMode.AAD;
415+
}
416+
405417
return overlayedConfig;
406418
}

Diff for: lib/msal-browser/src/controllers/NestedAppAuthController.ts

+2
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ export class NestedAppAuthController implements IController {
599599
CommonAuthorizationUrlRequest,
600600
| "requestedClaimsHash"
601601
| "responseMode"
602+
| "earJwk"
602603
| "codeChallenge"
603604
| "codeChallengeMethod"
604605
| "platformBroker"
@@ -792,6 +793,7 @@ export class NestedAppAuthController implements IController {
792793
CommonAuthorizationUrlRequest,
793794
| "requestedClaimsHash"
794795
| "responseMode"
796+
| "earJwk"
795797
| "codeChallenge"
796798
| "codeChallengeMethod"
797799
| "platformBroker"

Diff for: lib/msal-browser/src/controllers/UnknownOperatingContextController.ts

+2
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ export class UnknownOperatingContextController implements IController {
186186
Omit<
187187
CommonAuthorizationUrlRequest,
188188
| "responseMode"
189+
| "earJwk"
189190
| "codeChallenge"
190191
| "codeChallengeMethod"
191192
| "requestedClaimsHash"
@@ -293,6 +294,7 @@ export class UnknownOperatingContextController implements IController {
293294
Omit<
294295
CommonAuthorizationUrlRequest,
295296
| "responseMode"
297+
| "earJwk"
296298
| "codeChallenge"
297299
| "codeChallengeMethod"
298300
| "requestedClaimsHash"

Diff for: lib/msal-browser/src/crypto/BrowserCrypto.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
PerformanceEvents,
1313
} from "@azure/msal-common/browser";
1414
import { KEY_FORMAT_JWK } from "../utils/BrowserConstants.js";
15-
import { urlEncodeArr } from "../encode/Base64Encode.js";
15+
import { base64Encode, urlEncodeArr } from "../encode/Base64Encode.js";
1616
import { base64DecToArr } from "../encode/Base64Decode.js";
1717

1818
/**
@@ -226,6 +226,22 @@ export async function sign(
226226
) as Promise<ArrayBuffer>;
227227
}
228228

229+
/**
230+
* Generates Base64 encoded jwk used in the Encrypted Authorize Response (EAR) flow
231+
*/
232+
export async function generateEarKey(): Promise<string> {
233+
const key = await generateBaseKey();
234+
const keyStr = urlEncodeArr(new Uint8Array(key));
235+
236+
const jwk = {
237+
alg: "dir",
238+
kty: "oct",
239+
k: keyStr,
240+
};
241+
242+
return base64Encode(JSON.stringify(jwk));
243+
}
244+
229245
/**
230246
* Generates symmetric base encryption key. This may be stored as all encryption/decryption keys will be derived from this one.
231247
*/

Diff for: lib/msal-browser/src/error/BrowserAuthError.ts

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const ErrorLink = "For more visit: aka.ms/msaljs/browser-errors";
1515
export const BrowserAuthErrorMessages = {
1616
[BrowserAuthErrorCodes.pkceNotCreated]:
1717
"The PKCE code challenge and verifier could not be generated.",
18+
[BrowserAuthErrorCodes.earJwkEmpty]:
19+
"No EAR encryption key provided. This is unexpected.",
1820
[BrowserAuthErrorCodes.cryptoNonExistent]:
1921
"The crypto object or function is not available.",
2022
[BrowserAuthErrorCodes.emptyNavigateUri]:

Diff for: lib/msal-browser/src/error/BrowserAuthErrorCodes.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
export const pkceNotCreated = "pkce_not_created";
7+
export const earJwkEmpty = "ear_jwk_empty";
78
export const cryptoNonExistent = "crypto_nonexistent";
89
export const emptyNavigateUri = "empty_navigate_uri";
910
export const hashEmptyError = "hash_empty_error";

0 commit comments

Comments
 (0)