@azure/msal-angular 4.0.13 → 4.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/IMsalService.d.ts +17 -0
- package/README.md +1 -1
- package/constants.d.ts +5 -0
- package/esm2020/IMsalService.mjs +6 -0
- package/esm2020/azure-msal-angular.mjs +5 -0
- package/esm2020/constants.mjs +10 -0
- package/esm2020/msal.broadcast.config.mjs +6 -0
- package/esm2020/msal.broadcast.service.mjs +66 -0
- package/esm2020/msal.guard.config.mjs +6 -0
- package/esm2020/msal.guard.mjs +218 -0
- package/esm2020/msal.interceptor.config.mjs +6 -0
- package/esm2020/msal.interceptor.mjs +270 -0
- package/esm2020/msal.module.mjs +46 -0
- package/esm2020/msal.navigation.client.mjs +53 -0
- package/esm2020/msal.redirect.component.mjs +31 -0
- package/esm2020/msal.service.mjs +88 -0
- package/esm2020/packageMetadata.mjs +4 -0
- package/esm2020/public-api.mjs +18 -0
- package/fesm2015/azure-msal-angular.mjs +762 -0
- package/fesm2015/azure-msal-angular.mjs.map +1 -0
- package/fesm2020/azure-msal-angular.mjs +758 -0
- package/fesm2020/azure-msal-angular.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/msal.broadcast.config.d.ts +3 -0
- package/msal.broadcast.service.d.ts +19 -0
- package/msal.guard.config.d.ts +9 -0
- package/msal.guard.d.ts +43 -0
- package/msal.interceptor.config.d.ts +13 -0
- package/msal.interceptor.d.ts +70 -0
- package/msal.module.d.ts +13 -0
- package/msal.navigation.client.d.ts +19 -0
- package/msal.redirect.component.d.ts +15 -0
- package/msal.service.d.ts +33 -0
- package/package.json +26 -56
- package/packageMetadata.d.ts +2 -0
- package/{src/public-api.ts → public-api.d.ts} +17 -35
- package/.beachballrc +0 -3
- package/.editorconfig +0 -16
- package/.eslintrc.json +0 -3
- package/CHANGELOG.json +0 -2315
- package/CHANGELOG.md +0 -869
- package/FAQ.md +0 -182
- package/angular.json +0 -51
- package/docs/angular-universal.md +0 -64
- package/docs/configuration.md +0 -609
- package/docs/errors.md +0 -89
- package/docs/events.md +0 -262
- package/docs/initialization.md +0 -206
- package/docs/known-issues.md +0 -19
- package/docs/logging.md +0 -47
- package/docs/msal-guard.md +0 -208
- package/docs/msal-interceptor.md +0 -160
- package/docs/multi-tenant.md +0 -90
- package/docs/performance.md +0 -50
- package/docs/public-apis.md +0 -29
- package/docs/redirects.md +0 -257
- package/docs/security.md +0 -4
- package/docs/ssosilent.md +0 -84
- package/docs/v0-v1-upgrade-guide.md +0 -61
- package/docs/v1-v2-upgrade-guide.md +0 -70
- package/docs/v2-v3-upgrade-guide.md +0 -52
- package/docs/v3-v4-upgrade-guide.md +0 -36
- package/karma.conf.js +0 -44
- package/ng-package.json +0 -7
- package/src/IMsalService.ts +0 -34
- package/src/constants.ts +0 -20
- package/src/msal.broadcast.config.ts +0 -8
- package/src/msal.broadcast.service.spec.ts +0 -471
- package/src/msal.broadcast.service.ts +0 -84
- package/src/msal.guard.config.ts +0 -27
- package/src/msal.guard.spec.ts +0 -525
- package/src/msal.guard.ts +0 -290
- package/src/msal.interceptor.config.ts +0 -39
- package/src/msal.interceptor.spec.ts +0 -1168
- package/src/msal.interceptor.ts +0 -388
- package/src/msal.module.ts +0 -51
- package/src/msal.navigation.client.spec.ts +0 -96
- package/src/msal.navigation.client.ts +0 -59
- package/src/msal.redirect.component.spec.ts +0 -64
- package/src/msal.redirect.component.ts +0 -26
- package/src/msal.service.spec.ts +0 -468
- package/src/msal.service.ts +0 -104
- package/src/packageMetadata.ts +0 -3
- package/src/test.ts +0 -19
- package/tsconfig.json +0 -25
- package/tsconfig.lib.json +0 -27
- package/tsconfig.lib.prod.json +0 -10
- package/tsconfig.spec.json +0 -17
- package/typedoc.json +0 -10
package/docs/configuration.md
DELETED
|
@@ -1,609 +0,0 @@
|
|
|
1
|
-
# MSAL Angular Configuration
|
|
2
|
-
|
|
3
|
-
MSAL for Angular can be configured in multiple ways:
|
|
4
|
-
|
|
5
|
-
1. [`MsalModule.forRoot`](#msalmoduleforroot)
|
|
6
|
-
1. [Factory providers](#factory-providers)
|
|
7
|
-
1. [`platformBrowserDynamic`](#platformbrowserdynamic)
|
|
8
|
-
1. [Dynamic configurations using Factory Providers and `APP_INITIALIZER`](#dynamic-configurations-using-factory-providers-and-app_initializer)
|
|
9
|
-
1. [Configurations for Angular apps with standalone components](#configurations-for-angular-apps-with-standalone-components)
|
|
10
|
-
|
|
11
|
-
This guide will detail how to leverage each method for your application.
|
|
12
|
-
|
|
13
|
-
## Configuration Options
|
|
14
|
-
|
|
15
|
-
`@azure/msal-angular` accepts three configuration objects:
|
|
16
|
-
|
|
17
|
-
1. [Configuration](https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_browser.html#configuration): This is the same configuration object that is used for the core `@azure/msal-browser` library. All configuration options can be found [here](https://azuread.github.io/microsoft-authentication-library-for-js/ref/types/_azure_msal_browser.Configuration.html).
|
|
18
|
-
2. [`MsalGuardConfiguration`](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/src/msal.guard.config.ts): A set of options specifically for the Angular guard.
|
|
19
|
-
3. [`MsalInterceptorConfiguration`](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/src/msal.interceptor.config.ts): A set of options specifically for the Angular interceptor.
|
|
20
|
-
|
|
21
|
-
### Angular-specific configurations
|
|
22
|
-
|
|
23
|
-
- An `interactionType` must be specified on `MsalGuardConfiguration` and `MsalInterceptorConfiguration`, and can be set to `Popup` or `Redirect`.
|
|
24
|
-
- The `protectedResourceMap` object on `MsalInterceptorConfiguration` is used to protect routes.
|
|
25
|
-
- An optional `authRequest` object can be specified on `MsalGuardConfiguration` and `MsalInterceptorConfiguration` to set additional options.
|
|
26
|
-
- An optional `loginFailedRoute` string can be set on `MsalGuardConfiguration`. Msal Guard will redirect to this route if login is required and fails.
|
|
27
|
-
|
|
28
|
-
Please see our [MsalInterceptor](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/msal-interceptor.md) and [MsalGuard](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/msal-guard.md) docs for more details on configurations, usage, and differences to MSAL Angular v1.
|
|
29
|
-
|
|
30
|
-
### Configuration for redirects
|
|
31
|
-
|
|
32
|
-
We recommend importing `MsalRedirectComponent` and bootstrapping with the `AppComponent` if you intend to use redirects. Please see the [redirect documentation](https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-angular/docs/redirects.md) for more details.
|
|
33
|
-
|
|
34
|
-
**Note:** As of MSAL v3.x, initialization of the application object is now required. See the [v2-v3 upgrade guide](https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-angular/docs/v2-v3-upgrade-guide.md) for more details.
|
|
35
|
-
|
|
36
|
-
## MsalModule.forRoot
|
|
37
|
-
|
|
38
|
-
The `MsalModule` class contains a static method that can be called in your `app.module.ts` file:
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
import { NgModule } from "@angular/core";
|
|
42
|
-
import { HTTP_INTERCEPTORS } from "@angular/common/http";
|
|
43
|
-
import { AppComponent } from "./app.component";
|
|
44
|
-
import { MsalModule, MsalService, MsalGuard, MsalInterceptor, MsalBroadcastService, MsalRedirectComponent } from "@azure/msal-angular";
|
|
45
|
-
import { PublicClientApplication, InteractionType, BrowserCacheLocation } from "@azure/msal-browser";
|
|
46
|
-
|
|
47
|
-
@NgModule({
|
|
48
|
-
imports: [
|
|
49
|
-
MsalModule.forRoot(
|
|
50
|
-
new PublicClientApplication({
|
|
51
|
-
// MSAL Configuration
|
|
52
|
-
auth: {
|
|
53
|
-
clientId: "clientid",
|
|
54
|
-
authority: "https://login.microsoftonline.com/common/",
|
|
55
|
-
redirectUri: "http://localhost:4200/",
|
|
56
|
-
postLogoutRedirectUri: "http://localhost:4200/",
|
|
57
|
-
navigateToLoginRequestUrl: true,
|
|
58
|
-
},
|
|
59
|
-
cache: {
|
|
60
|
-
cacheLocation: BrowserCacheLocation.LocalStorage,
|
|
61
|
-
storeAuthStateInCookie: true, // Deprecated, will be removed in the next major version
|
|
62
|
-
},
|
|
63
|
-
system: {
|
|
64
|
-
loggerOptions: {
|
|
65
|
-
loggerCallback: () => {},
|
|
66
|
-
piiLoggingEnabled: false,
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
}),
|
|
70
|
-
{
|
|
71
|
-
interactionType: InteractionType.Popup, // MSAL Guard Configuration
|
|
72
|
-
authRequest: {
|
|
73
|
-
scopes: ["user.read"],
|
|
74
|
-
},
|
|
75
|
-
loginFailedRoute: "/login-failed",
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
interactionType: InteractionType.Redirect, // MSAL Interceptor Configuration
|
|
79
|
-
protectedResourceMap,
|
|
80
|
-
}
|
|
81
|
-
),
|
|
82
|
-
],
|
|
83
|
-
providers: [
|
|
84
|
-
{
|
|
85
|
-
provide: HTTP_INTERCEPTORS,
|
|
86
|
-
useClass: MsalInterceptor,
|
|
87
|
-
multi: true,
|
|
88
|
-
},
|
|
89
|
-
MsalGuard,
|
|
90
|
-
],
|
|
91
|
-
bootstrap: [AppComponent, MsalRedirectComponent],
|
|
92
|
-
})
|
|
93
|
-
export class AppModule {}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Factory Providers
|
|
97
|
-
|
|
98
|
-
You may also provide the configuration options via factory providers.
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
import { MsalModule, MsalService, MsalInterceptor, MsalInterceptorConfiguration, MsalGuard, MsalGuardConfiguration, MsalBroadcastService, MsalRedirectComponent } from "@azure/msal-angular";
|
|
102
|
-
import { IPublicClientApplication, PublicClientApplication, InteractionType, BrowserCacheLocation } from "@azure/msal-browser";
|
|
103
|
-
|
|
104
|
-
export function MSALInstanceFactory(): IPublicClientApplication {
|
|
105
|
-
return new PublicClientApplication({
|
|
106
|
-
auth: {
|
|
107
|
-
clientId: "b5c2e510-4a17-4feb-b219-e55aa5b74144",
|
|
108
|
-
redirectUri: "http://localhost:4200",
|
|
109
|
-
postLogoutRedirectUri: "http://localhost:4200",
|
|
110
|
-
},
|
|
111
|
-
cache: {
|
|
112
|
-
cacheLocation: BrowserCacheLocation.LocalStorage,
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
|
|
118
|
-
const protectedResourceMap = new Map<string, Array<string>>();
|
|
119
|
-
protectedResourceMap.set("https://graph.microsoft.com/v1.0/me", ["user.read"]);
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
interactionType: InteractionType.Redirect,
|
|
123
|
-
protectedResourceMap,
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
|
|
128
|
-
return {
|
|
129
|
-
interactionType: InteractionType.Redirect,
|
|
130
|
-
authRequest: {
|
|
131
|
-
scopes: ["user.read"],
|
|
132
|
-
},
|
|
133
|
-
loginFailedRoute: "./login-failed",
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
@NgModule({
|
|
138
|
-
imports: [MsalModule],
|
|
139
|
-
providers: [
|
|
140
|
-
{
|
|
141
|
-
provide: HTTP_INTERCEPTORS,
|
|
142
|
-
useClass: MsalInterceptor,
|
|
143
|
-
multi: true,
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
provide: MSAL_INSTANCE,
|
|
147
|
-
useFactory: MSALInstanceFactory,
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
provide: MSAL_GUARD_CONFIG,
|
|
151
|
-
useFactory: MSALGuardConfigFactory,
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
provide: MSAL_INTERCEPTOR_CONFIG,
|
|
155
|
-
useFactory: MSALInterceptorConfigFactory,
|
|
156
|
-
},
|
|
157
|
-
MsalGuard,
|
|
158
|
-
MsalBroadcastService,
|
|
159
|
-
MsalService,
|
|
160
|
-
],
|
|
161
|
-
bootstrap: [AppComponent, MsalRedirectComponent],
|
|
162
|
-
})
|
|
163
|
-
export class AppModule {}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## platformBrowserDynamic
|
|
167
|
-
|
|
168
|
-
If you need to dynamically configure MSAL Angular (e.g. based on values returned from an API), you can use `platformBrowserDynamic`. `platformBrowserDynamic` is a platform factory, used to bootstrap the application, and is able to take in configuration options. `platformBrowserDynamic` should already be present when the Angular application is set up.
|
|
169
|
-
|
|
170
|
-
The following is an example of how to dynamically configure `@azure/msal-angular` with `platformBrowserDynamic` and a json file:
|
|
171
|
-
|
|
172
|
-
`app.module.ts`
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
import { MsalModule, MsalInterceptor, MsalService } from "@azure/msal-angular";
|
|
176
|
-
|
|
177
|
-
@NgModule({
|
|
178
|
-
imports: [MsalModule],
|
|
179
|
-
providers: [
|
|
180
|
-
{
|
|
181
|
-
provide: HTTP_INTERCEPTORS,
|
|
182
|
-
useClass: MsalInterceptor,
|
|
183
|
-
multi: true,
|
|
184
|
-
},
|
|
185
|
-
MsalService,
|
|
186
|
-
],
|
|
187
|
-
bootstrap: [AppComponent],
|
|
188
|
-
})
|
|
189
|
-
export class AppModule {}
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
`main.ts`
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
import { enableProdMode } from "@angular/core";
|
|
196
|
-
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
|
|
197
|
-
|
|
198
|
-
import { AppModule } from "./app/app.module";
|
|
199
|
-
import { environment } from "./environments/environment";
|
|
200
|
-
import { MSAL_INSTANCE, MSAL_GUARD_CONFIG, MSAL_INTERCEPTOR_CONFIG } from "@azure/msal-angular";
|
|
201
|
-
import { PublicClientApplication, Configuration } from "@azure/msal-browser";
|
|
202
|
-
|
|
203
|
-
if (environment.production) {
|
|
204
|
-
enableProdMode();
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function loggerCallback(logLevel: LogLevel, message: string) {
|
|
208
|
-
console.log("MSAL Angular: ", message);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
fetch("/assets/configuration.json")
|
|
212
|
-
.then((response) => response.json())
|
|
213
|
-
.then((json) => {
|
|
214
|
-
platformBrowserDynamic([
|
|
215
|
-
{
|
|
216
|
-
provide: MSAL_INSTANCE,
|
|
217
|
-
useValue: new PublicClientApplication({
|
|
218
|
-
auth: json.msal.auth,
|
|
219
|
-
cache: json.msal.cache,
|
|
220
|
-
system: {
|
|
221
|
-
loggerOptions: {
|
|
222
|
-
loggerCallback,
|
|
223
|
-
logLevel: LogLevel.Info,
|
|
224
|
-
piiLoggingEnabled: false,
|
|
225
|
-
},
|
|
226
|
-
},
|
|
227
|
-
}),
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
provide: MSAL_GUARD_CONFIG,
|
|
231
|
-
useValue: {
|
|
232
|
-
interactionType: json.guard.interactionType,
|
|
233
|
-
authRequest: json.guard.authRequest,
|
|
234
|
-
loginFailedRoute: json.guard.loginFailedRoute,
|
|
235
|
-
} as MsalGuardConfiguration,
|
|
236
|
-
},
|
|
237
|
-
{
|
|
238
|
-
provide: MSAL_INTERCEPTOR_CONFIG,
|
|
239
|
-
useValue: {
|
|
240
|
-
interactionType: json.interceptor.interactionType,
|
|
241
|
-
protectedResourceMap: new Map(json.interceptor.protectedResourceMap),
|
|
242
|
-
} as MsalInterceptorConfiguration,
|
|
243
|
-
},
|
|
244
|
-
])
|
|
245
|
-
.bootstrapModule(AppModule)
|
|
246
|
-
.catch((err) => console.error(err));
|
|
247
|
-
});
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
`src/assets/configuration.json`
|
|
251
|
-
|
|
252
|
-
```json
|
|
253
|
-
{
|
|
254
|
-
"msal": {
|
|
255
|
-
"auth": {
|
|
256
|
-
"clientId": "clientid",
|
|
257
|
-
"authority": "https://login.microsoftonline.com/common/",
|
|
258
|
-
"redirectUri": "http://localhost:4200/",
|
|
259
|
-
"postLogoutRedirectUri": "http://localhost:4200/",
|
|
260
|
-
"navigateToLoginRequestUrl": true
|
|
261
|
-
},
|
|
262
|
-
"cache": {
|
|
263
|
-
"cacheLocation": "localStorage",
|
|
264
|
-
"storeAuthStateInCookie": true
|
|
265
|
-
}
|
|
266
|
-
},
|
|
267
|
-
"guard": {
|
|
268
|
-
"interactionType": "redirect",
|
|
269
|
-
"authRequest": {
|
|
270
|
-
"scopes": ["user.read"]
|
|
271
|
-
},
|
|
272
|
-
"loginFailedRoute": "/login-failed"
|
|
273
|
-
},
|
|
274
|
-
"interceptor": {
|
|
275
|
-
"interactionType": "redirect",
|
|
276
|
-
"protectedResourceMap": [["https://graph.microsoft.com/v1.0/me", ["user.read"]]]
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
## Dynamic configurations using Factory Providers and APP_INITIALIZER
|
|
282
|
-
|
|
283
|
-
To dynamically configure MSAL Angular, you can use the Factory Providers with APP_INITIALIZER.
|
|
284
|
-
|
|
285
|
-
`src/app/config.service.ts`
|
|
286
|
-
|
|
287
|
-
```typescript
|
|
288
|
-
import { Injectable } from "@angular/core";
|
|
289
|
-
import { HttpClient, HttpBackend } from "@angular/common/http";
|
|
290
|
-
import { map } from "rxjs/operators";
|
|
291
|
-
|
|
292
|
-
@Injectable({
|
|
293
|
-
providedIn: "root",
|
|
294
|
-
})
|
|
295
|
-
export class ConfigService {
|
|
296
|
-
private settings: any;
|
|
297
|
-
private http: HttpClient;
|
|
298
|
-
|
|
299
|
-
constructor(private readonly httpHandler: HttpBackend) {
|
|
300
|
-
this.http = new HttpClient(httpHandler);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
init(endpoint: string): Promise<boolean> {
|
|
304
|
-
return new Promise<boolean>((resolve, reject) => {
|
|
305
|
-
this.http
|
|
306
|
-
.get(endpoint)
|
|
307
|
-
.pipe(map((result) => result))
|
|
308
|
-
.subscribe(
|
|
309
|
-
(value) => {
|
|
310
|
-
this.settings = value;
|
|
311
|
-
resolve(true);
|
|
312
|
-
},
|
|
313
|
-
(error) => {
|
|
314
|
-
reject(error);
|
|
315
|
-
}
|
|
316
|
-
);
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
getSettings(key?: string | Array<string>): any {
|
|
321
|
-
if (!key || (Array.isArray(key) && !key[0])) {
|
|
322
|
-
return this.settings;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (!Array.isArray(key)) {
|
|
326
|
-
key = key.split(".");
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
let result = key.reduce((account: any, current: string) => account && account[current], this.settings);
|
|
330
|
-
|
|
331
|
-
return result;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
`src/app/msal-config-dynamic.module.ts`
|
|
337
|
-
|
|
338
|
-
```typescript
|
|
339
|
-
import { InjectionToken, NgModule, APP_INITIALIZER } from "@angular/core";
|
|
340
|
-
import { IPublicClientApplication, PublicClientApplication, LogLevel } from "@azure/msal-browser";
|
|
341
|
-
import { MsalGuard, MsalInterceptor, MsalBroadcastService, MsalInterceptorConfiguration, MsalModule, MsalService, MSAL_GUARD_CONFIG, MSAL_INSTANCE, MSAL_INTERCEPTOR_CONFIG, MsalGuardConfiguration } from "@azure/msal-angular";
|
|
342
|
-
import { HTTP_INTERCEPTORS } from "@angular/common/http";
|
|
343
|
-
import { ConfigService } from "./config.service";
|
|
344
|
-
|
|
345
|
-
const AUTH_CONFIG_URL_TOKEN = new InjectionToken<string>("AUTH_CONFIG_URL");
|
|
346
|
-
|
|
347
|
-
export function initializerFactory(env: ConfigService, configUrl: string): any {
|
|
348
|
-
const promise = env.init(configUrl).then((value) => {
|
|
349
|
-
console.log("finished getting configurations dynamically.");
|
|
350
|
-
});
|
|
351
|
-
return () => promise;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
export function loggerCallback(logLevel: LogLevel, message: string) {
|
|
355
|
-
console.log(message);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
export function MSALInstanceFactory(config: ConfigService): IPublicClientApplication {
|
|
359
|
-
return new PublicClientApplication({
|
|
360
|
-
auth: config.getSettings("msal").auth,
|
|
361
|
-
cache: config.getSettings("msal").cache,
|
|
362
|
-
system: {
|
|
363
|
-
loggerOptions: {
|
|
364
|
-
loggerCallback,
|
|
365
|
-
logLevel: LogLevel.Info,
|
|
366
|
-
piiLoggingEnabled: false,
|
|
367
|
-
},
|
|
368
|
-
},
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
export function MSALInterceptorConfigFactory(config: ConfigService): MsalInterceptorConfiguration {
|
|
373
|
-
const protectedResourceMap = new Map<string, Array<string>>(config.getSettings("interceptor").protectedResourceMap);
|
|
374
|
-
|
|
375
|
-
return {
|
|
376
|
-
interactionType: config.getSettings("interceptor").interactionType,
|
|
377
|
-
protectedResourceMap,
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
export function MSALGuardConfigFactory(config: ConfigService): MsalGuardConfiguration {
|
|
382
|
-
return {
|
|
383
|
-
interactionType: config.getSettings("guard").interactionType,
|
|
384
|
-
authRequest: config.getSettings("guard").authRequest,
|
|
385
|
-
loginFailedRoute: config.getSettings("guard").loginFailedRoute,
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
@NgModule({
|
|
390
|
-
providers: [],
|
|
391
|
-
imports: [MsalModule],
|
|
392
|
-
})
|
|
393
|
-
export class MsalConfigDynamicModule {
|
|
394
|
-
static forRoot(configFile: string) {
|
|
395
|
-
return {
|
|
396
|
-
ngModule: MsalConfigDynamicModule,
|
|
397
|
-
providers: [
|
|
398
|
-
ConfigService,
|
|
399
|
-
{ provide: AUTH_CONFIG_URL_TOKEN, useValue: configFile },
|
|
400
|
-
{ provide: APP_INITIALIZER, useFactory: initializerFactory, deps: [ConfigService, AUTH_CONFIG_URL_TOKEN], multi: true },
|
|
401
|
-
{
|
|
402
|
-
provide: MSAL_INSTANCE,
|
|
403
|
-
useFactory: MSALInstanceFactory,
|
|
404
|
-
deps: [ConfigService],
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
provide: MSAL_GUARD_CONFIG,
|
|
408
|
-
useFactory: MSALGuardConfigFactory,
|
|
409
|
-
deps: [ConfigService],
|
|
410
|
-
},
|
|
411
|
-
{
|
|
412
|
-
provide: MSAL_INTERCEPTOR_CONFIG,
|
|
413
|
-
useFactory: MSALInterceptorConfigFactory,
|
|
414
|
-
deps: [ConfigService],
|
|
415
|
-
},
|
|
416
|
-
MsalService,
|
|
417
|
-
MsalGuard,
|
|
418
|
-
MsalBroadcastService,
|
|
419
|
-
{
|
|
420
|
-
provide: HTTP_INTERCEPTORS,
|
|
421
|
-
useClass: MsalInterceptor,
|
|
422
|
-
multi: true,
|
|
423
|
-
},
|
|
424
|
-
],
|
|
425
|
-
};
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
`src/app/app.module.ts`
|
|
431
|
-
|
|
432
|
-
```typescript
|
|
433
|
-
import { BrowserModule } from "@angular/platform-browser";
|
|
434
|
-
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
|
435
|
-
import { NgModule } from "@angular/core";
|
|
436
|
-
|
|
437
|
-
import { MatButtonModule } from "@angular/material/button";
|
|
438
|
-
import { MatToolbarModule } from "@angular/material/toolbar";
|
|
439
|
-
import { MatListModule } from "@angular/material/list";
|
|
440
|
-
|
|
441
|
-
import { AppRoutingModule } from "./app-routing.module";
|
|
442
|
-
import { AppComponent } from "./app.component";
|
|
443
|
-
import { HomeComponent } from "./home/home.component";
|
|
444
|
-
import { ProfileComponent } from "./profile/profile.component";
|
|
445
|
-
|
|
446
|
-
import { HttpClientModule } from "@angular/common/http";
|
|
447
|
-
import { MsalRedirectComponent } from "@azure/msal-angular";
|
|
448
|
-
import { DetailComponent } from "./detail/detail.component";
|
|
449
|
-
import { MsalConfigDynamicModule } from "./msal-config-dynamic.module";
|
|
450
|
-
|
|
451
|
-
@NgModule({
|
|
452
|
-
declarations: [AppComponent, HomeComponent, ProfileComponent, DetailComponent],
|
|
453
|
-
imports: [BrowserModule, BrowserAnimationsModule, AppRoutingModule, MatButtonModule, MatToolbarModule, MatListModule, HttpClientModule, MsalConfigDynamicModule.forRoot("assets/configuration.json")],
|
|
454
|
-
providers: [],
|
|
455
|
-
bootstrap: [AppComponent, MsalRedirectComponent],
|
|
456
|
-
})
|
|
457
|
-
export class AppModule {}
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
`src/assets/configuration.json`
|
|
461
|
-
|
|
462
|
-
```json
|
|
463
|
-
{
|
|
464
|
-
"msal": {
|
|
465
|
-
"auth": {
|
|
466
|
-
"clientId": "clientid",
|
|
467
|
-
"authority": "https://login.microsoftonline.com/common/",
|
|
468
|
-
"redirectUri": "http://localhost:4200/",
|
|
469
|
-
"postLogoutRedirectUri": "http://localhost:4200/",
|
|
470
|
-
"navigateToLoginRequestUrl": true
|
|
471
|
-
},
|
|
472
|
-
"cache": {
|
|
473
|
-
"cacheLocation": "localStorage",
|
|
474
|
-
"storeAuthStateInCookie": true
|
|
475
|
-
}
|
|
476
|
-
},
|
|
477
|
-
"guard": {
|
|
478
|
-
"interactionType": "redirect",
|
|
479
|
-
"authRequest": {
|
|
480
|
-
"scopes": ["user.read"]
|
|
481
|
-
},
|
|
482
|
-
"loginFailedRoute": "/login-failed"
|
|
483
|
-
},
|
|
484
|
-
"interceptor": {
|
|
485
|
-
"interactionType": "redirect",
|
|
486
|
-
"protectedResourceMap": [["https://graph.microsoft.com/v1.0/me", ["user.read"]]]
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
### MsalGuard - Dynamic auth request
|
|
492
|
-
|
|
493
|
-
The **MsalGuard** also allows you to dynamically change the **authRequest** at runtime. This allow you to pick a different authority for a route, or to dynamically add scopes based on the **RouterStateSnapshot**.
|
|
494
|
-
|
|
495
|
-
```js
|
|
496
|
-
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
|
|
497
|
-
return {
|
|
498
|
-
interactionType: InteractionType.Redirect,
|
|
499
|
-
authRequest: (authService, state) => {
|
|
500
|
-
return {
|
|
501
|
-
scopes: state.root.url.some((x) => x.path === "calendar") ? ["user.read", " Calendars.Read"] : ["user.read"],
|
|
502
|
-
};
|
|
503
|
-
},
|
|
504
|
-
loginFailedRoute: "./login-failed",
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
## Configurations for Angular apps with standalone components
|
|
510
|
-
|
|
511
|
-
Angular applications using standalone components can be used with [factory providers](#factory-providers) as above in the `app.config.ts` file, which is then imported into `main.ts` for bootstrapping.
|
|
512
|
-
|
|
513
|
-
Please see our [Angular Standalone Sample](https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/samples/msal-angular-samples/angular-standalone-sample) for usage.
|
|
514
|
-
|
|
515
|
-
```ts
|
|
516
|
-
// app.config.ts
|
|
517
|
-
import { ApplicationConfig, importProvidersFrom } from "@angular/core";
|
|
518
|
-
import { provideRouter } from "@angular/router";
|
|
519
|
-
import { routes } from "./app.routes";
|
|
520
|
-
import { BrowserModule } from "@angular/platform-browser";
|
|
521
|
-
import { provideHttpClient, withInterceptorsFromDi, HTTP_INTERCEPTORS, withFetch, withInterceptors } from "@angular/common/http";
|
|
522
|
-
import { provideNoopAnimations } from "@angular/platform-browser/animations";
|
|
523
|
-
import { IPublicClientApplication, PublicClientApplication, InteractionType, BrowserCacheLocation, LogLevel } from "@azure/msal-browser";
|
|
524
|
-
import { MsalInterceptor, MSAL_INSTANCE, MsalInterceptorConfiguration, MsalGuardConfiguration, MSAL_GUARD_CONFIG, MSAL_INTERCEPTOR_CONFIG, MsalService, MsalGuard, MsalBroadcastService } from "@azure/msal-angular";
|
|
525
|
-
|
|
526
|
-
export function loggerCallback(logLevel: LogLevel, message: string) {
|
|
527
|
-
console.log(message);
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
export function MSALInstanceFactory(): IPublicClientApplication {
|
|
531
|
-
return new PublicClientApplication({
|
|
532
|
-
auth: {
|
|
533
|
-
clientId: "clientid",
|
|
534
|
-
authority: "https://login.microsoftonline.com/common/",
|
|
535
|
-
redirectUri: "/",
|
|
536
|
-
postLogoutRedirectUri: "/",
|
|
537
|
-
},
|
|
538
|
-
cache: {
|
|
539
|
-
cacheLocation: BrowserCacheLocation.LocalStorage,
|
|
540
|
-
},
|
|
541
|
-
system: {
|
|
542
|
-
allowPlatformBroker: false, // Disables WAM Broker
|
|
543
|
-
loggerOptions: {
|
|
544
|
-
loggerCallback,
|
|
545
|
-
logLevel: LogLevel.Info,
|
|
546
|
-
piiLoggingEnabled: false,
|
|
547
|
-
},
|
|
548
|
-
},
|
|
549
|
-
});
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
|
|
553
|
-
const protectedResourceMap = new Map<string, Array<string>>();
|
|
554
|
-
protectedResourceMap.set("https://graph.microsoft.com/v1.0/me", ["user.read"]);
|
|
555
|
-
|
|
556
|
-
return {
|
|
557
|
-
interactionType: InteractionType.Redirect,
|
|
558
|
-
protectedResourceMap,
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
|
|
563
|
-
return {
|
|
564
|
-
interactionType: InteractionType.Redirect,
|
|
565
|
-
authRequest: {
|
|
566
|
-
scopes: ["user.read"],
|
|
567
|
-
},
|
|
568
|
-
loginFailedRoute: "/login-failed",
|
|
569
|
-
};
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
export const appConfig: ApplicationConfig = {
|
|
573
|
-
providers: [
|
|
574
|
-
provideRouter(routes),
|
|
575
|
-
importProvidersFrom(BrowserModule),
|
|
576
|
-
provideNoopAnimations(),
|
|
577
|
-
provideHttpClient(withInterceptorsFromDi(), withFetch()),
|
|
578
|
-
{
|
|
579
|
-
provide: HTTP_INTERCEPTORS,
|
|
580
|
-
useClass: MsalInterceptor,
|
|
581
|
-
multi: true,
|
|
582
|
-
},
|
|
583
|
-
{
|
|
584
|
-
provide: MSAL_INSTANCE,
|
|
585
|
-
useFactory: MSALInstanceFactory,
|
|
586
|
-
},
|
|
587
|
-
{
|
|
588
|
-
provide: MSAL_GUARD_CONFIG,
|
|
589
|
-
useFactory: MSALGuardConfigFactory,
|
|
590
|
-
},
|
|
591
|
-
{
|
|
592
|
-
provide: MSAL_INTERCEPTOR_CONFIG,
|
|
593
|
-
useFactory: MSALInterceptorConfigFactory,
|
|
594
|
-
},
|
|
595
|
-
MsalService,
|
|
596
|
-
MsalGuard,
|
|
597
|
-
MsalBroadcastService,
|
|
598
|
-
],
|
|
599
|
-
};
|
|
600
|
-
```
|
|
601
|
-
|
|
602
|
-
```ts
|
|
603
|
-
// main.ts
|
|
604
|
-
import { bootstrapApplication } from "@angular/platform-browser";
|
|
605
|
-
import { appConfig } from "./app/app.config";
|
|
606
|
-
import { AppComponent } from "./app/app.component";
|
|
607
|
-
|
|
608
|
-
bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));
|
|
609
|
-
```
|
package/docs/errors.md
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# MSAL Angular Errors
|
|
2
|
-
|
|
3
|
-
***
|
|
4
|
-
|
|
5
|
-
**[BrowserAuthErrors](#browserautherrors)**
|
|
6
|
-
|
|
7
|
-
1. [interaction_in_progress](#interaction_in_progress)
|
|
8
|
-
|
|
9
|
-
**[Additional Errors](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/errors.md)**
|
|
10
|
-
|
|
11
|
-
***
|
|
12
|
-
|
|
13
|
-
## BrowserAuthErrors
|
|
14
|
-
|
|
15
|
-
### Interaction_in_progress
|
|
16
|
-
|
|
17
|
-
**Error Message**: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API.
|
|
18
|
-
|
|
19
|
-
This error is thrown when an interactive API (`loginPopup`, `loginRedirect`, `acquireTokenPopup`, `acquireTokenRedirect`) is invoked while another interactive API is still in progress. The login and acquireToken APIs are async so you will need to ensure that the resulting promises have resolved before invoking another one.
|
|
20
|
-
|
|
21
|
-
In `@azure/msal-angular` there are 2 common scenarios when this can happen:
|
|
22
|
-
|
|
23
|
-
1. Your application is not handling redirects correctly. The error then occurs when either the app or the user tries to call an interactive API.
|
|
24
|
-
1. Your application is calling one of the above APIs without first checking if interaction is already in progress elsewhere.
|
|
25
|
-
|
|
26
|
-
Redirects **must** be handled either with the `MsalRedirectComponent` or with calling `handleRedirectObservable()`. Not handling redirects explicitly with either of these two approaches will result in the error above. See our docs on redirects [here](https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-angular/docs/redirects.md) for more information on both approaches.
|
|
27
|
-
|
|
28
|
-
Additionally, any interaction should be done after subscribing to the `inProgress$` observable and filtering for `InteractionStatus.None`. Attempting interaction while another is in progress is not supported and will result in the error above. Checking for `InteractionStatus.None` is how you ensure this does not happen. Please see our [events doc](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/events.md#the-inprogress-observable) for more details.
|
|
29
|
-
|
|
30
|
-
Please see the [`@azure/msal-browser` error doc](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/errors.md) for more information on this error.
|
|
31
|
-
|
|
32
|
-
❌ The following example will throw this error when another component has already invoked an interactive API that is in progress:
|
|
33
|
-
|
|
34
|
-
```javascript
|
|
35
|
-
import { Component, OnInit } from '@angular/core';
|
|
36
|
-
import { MsalService, MsalBroadcastService, InteractionStatus } from '@azure/msal-angular';
|
|
37
|
-
import { filter } from 'rxjs/operators';
|
|
38
|
-
|
|
39
|
-
@Component()
|
|
40
|
-
export class ExampleComponent implements OnInit {
|
|
41
|
-
|
|
42
|
-
constructor(
|
|
43
|
-
private msalBroadcastService: MsalBroadcastService,
|
|
44
|
-
private authService: MsalService
|
|
45
|
-
) {}
|
|
46
|
-
|
|
47
|
-
ngOnInit(): void {
|
|
48
|
-
this.authService.loginRedirect();
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
✔️ To fix the previous example, check that no other interaction is in progress before invoking `loginRedirect`:
|
|
53
|
-
|
|
54
|
-
```javascript
|
|
55
|
-
import { Component, OnInit } from '@angular/core';
|
|
56
|
-
import { InteractionStatus } from '@azure/msal-browser';
|
|
57
|
-
import { MsalService, MsalBroadcastService } from '@azure/msal-angular';
|
|
58
|
-
import { filter } from 'rxjs/operators';
|
|
59
|
-
|
|
60
|
-
@Component()
|
|
61
|
-
export class ExampleComponent implements OnInit {
|
|
62
|
-
|
|
63
|
-
constructor(
|
|
64
|
-
private msalBroadcastService: MsalBroadcastService,
|
|
65
|
-
private authService: MsalService
|
|
66
|
-
) {}
|
|
67
|
-
|
|
68
|
-
ngOnInit(): void {
|
|
69
|
-
this.msalBroadcastService.inProgress$
|
|
70
|
-
.pipe(
|
|
71
|
-
filter((status: InteractionStatus) => status === InteractionStatus.None),
|
|
72
|
-
)
|
|
73
|
-
.subscribe(() => {
|
|
74
|
-
this.authService.loginRedirect();
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
#### Troubleshooting Steps
|
|
80
|
-
|
|
81
|
-
- [Enable verbose logging](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/configuration.md#using-the-config-object) and trace the order of events. Verify that an interactive API is not invoked before another has resolved.
|
|
82
|
-
- If using the redirect flow make sure `MsalRedirectComponet` is correctly bootstrapped or `handleRedirectObservable` is being called on every page which may be redirected to.
|
|
83
|
-
|
|
84
|
-
If you are unable to figure out why this error is being thrown please [open an issue](https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/new/choose) and be prepared to share the following information:
|
|
85
|
-
|
|
86
|
-
- Verbose logs
|
|
87
|
-
- A sample app and/or code snippets that we can use to reproduce the issue
|
|
88
|
-
- Refresh the page. Does the error go away?
|
|
89
|
-
- Open your application in a new tab. Does the error go away?
|