Skip to content

Commit c6912e7

Browse files
committed
Upgrade MSAL to 2.1
Refactored code as needed
1 parent 3acc97d commit c6912e7

File tree

8 files changed

+68
-50
lines changed

8 files changed

+68
-50
lines changed

demo/README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,14 @@ If you don't have a Microsoft account, there are a couple of options to get a fr
2626

2727
- Set **Name** to `React Graph Tutorial`.
2828
- Set **Supported account types** to **Accounts in any organizational directory and personal Microsoft accounts**.
29-
- Under **Redirect URI**, set the first drop-down to `Web` and set the value to `http://localhost:3000`.
29+
- Under **Redirect URI**, set the first drop-down to `Single-page application (SPA)` and set the value to `http://localhost:3000`.
3030

3131
![A screenshot of the Register an application page](/tutorial/images/aad-register-an-app.png)
3232

3333
1. Choose **Register**. On the **Angular Graph Tutorial** page, copy the value of the **Application (client) ID** and save it, you will need it in the next step.
3434

3535
![A screenshot of the application ID of the new app registration](/tutorial/images/aad-application-id.png)
3636

37-
1. Select **Authentication** under **Manage**. Locate the **Implicit grant** section and enable **Access tokens** and **ID tokens**. Choose **Save**.
38-
39-
![A screenshot of the Implicit grant section](/tutorial/images/aad-implicit-grant.png)
40-
4137
## Configure the sample
4238

4339
1. Rename the `./graph-tutorial/src/Config.ts.example` file to `./graph-tutorial/src/Config.ts`.

demo/graph-tutorial/package-lock.json

Lines changed: 16 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

demo/graph-tutorial/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6+
"@azure/msal-browser": "^2.1.0",
67
"@fortawesome/fontawesome-free": "^5.14.0",
78
"@microsoft/microsoft-graph-client": "^2.0.0",
89
"@testing-library/jest-dom": "^4.2.4",
@@ -18,7 +19,6 @@
1819
"bootstrap": "^4.5.2",
1920
"moment": "^2.27.0",
2021
"moment-timezone": "^0.5.31",
21-
"msal": "^1.4.0",
2222
"react": "^16.13.1",
2323
"react-dom": "^16.13.1",
2424
"react-router-dom": "^5.2.0",

demo/graph-tutorial/src/AuthProvider.tsx

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33
import React from 'react';
4-
import { UserAgentApplication } from 'msal';
4+
import { PublicClientApplication } from '@azure/msal-browser';
55

66
import { config } from './Config';
77
import { getUserDetails } from './GraphService';
@@ -25,7 +25,7 @@ interface AuthProviderState {
2525
export default function withAuthProvider<T extends React.Component<AuthComponentProps>>
2626
(WrappedComponent: new (props: AuthComponentProps, context?: any) => T): React.ComponentClass {
2727
return class extends React.Component<any, AuthProviderState> {
28-
private userAgentApplication: UserAgentApplication;
28+
private publicClientApplication: PublicClientApplication;
2929

3030
constructor(props: any) {
3131
super(props);
@@ -36,7 +36,7 @@ export default function withAuthProvider<T extends React.Component<AuthComponent
3636
};
3737

3838
// Initialize the MSAL application object
39-
this.userAgentApplication = new UserAgentApplication({
39+
this.publicClientApplication = new PublicClientApplication({
4040
auth: {
4141
clientId: config.appId,
4242
redirectUri: config.redirectUri
@@ -51,9 +51,9 @@ export default function withAuthProvider<T extends React.Component<AuthComponent
5151
componentDidMount() {
5252
// If MSAL already has an account, the user
5353
// is already logged in
54-
var account = this.userAgentApplication.getAccount();
54+
const accounts = this.publicClientApplication.getAllAccounts();
5555

56-
if (account) {
56+
if (accounts && accounts.length > 0) {
5757
// Enhance user object with data from Graph
5858
this.getUserProfile();
5959
}
@@ -74,11 +74,12 @@ export default function withAuthProvider<T extends React.Component<AuthComponent
7474
async login() {
7575
try {
7676
// Login via popup
77-
await this.userAgentApplication.loginPopup(
77+
await this.publicClientApplication.loginPopup(
7878
{
7979
scopes: config.scopes,
8080
prompt: "select_account"
8181
});
82+
8283
// After login, get the user's profile
8384
await this.getUserProfile();
8485
}
@@ -92,27 +93,34 @@ export default function withAuthProvider<T extends React.Component<AuthComponent
9293
}
9394

9495
logout() {
95-
this.userAgentApplication.logout();
96+
this.publicClientApplication.logout();
9697
}
9798

9899
async getAccessToken(scopes: string[]): Promise<string> {
99100
try {
101+
const accounts = this.publicClientApplication
102+
.getAllAccounts();
103+
104+
if (accounts.length <= 0) throw new Error('login_required');
100105
// Get the access token silently
101106
// If the cache contains a non-expired token, this function
102107
// will just return the cached token. Otherwise, it will
103108
// make a request to the Azure OAuth endpoint to get a token
104-
var silentResult = await this.userAgentApplication.acquireTokenSilent({
105-
scopes: scopes
106-
});
109+
var silentResult = await this.publicClientApplication
110+
.acquireTokenSilent({
111+
scopes: scopes,
112+
account: accounts[0]
113+
});
107114

108115
return silentResult.accessToken;
109116
} catch (err) {
110117
// If a silent request fails, it may be because the user needs
111118
// to login or grant consent to one or more of the requested scopes
112119
if (this.isInteractionRequired(err)) {
113-
var interactiveResult = await this.userAgentApplication.acquireTokenPopup({
114-
scopes: scopes
115-
});
120+
var interactiveResult = await this.publicClientApplication
121+
.acquireTokenPopup({
122+
scopes: scopes
123+
});
116124

117125
return interactiveResult.accessToken;
118126
} else {
@@ -181,7 +189,8 @@ export default function withAuthProvider<T extends React.Component<AuthComponent
181189
return (
182190
error.message.indexOf('consent_required') > -1 ||
183191
error.message.indexOf('interaction_required') > -1 ||
184-
error.message.indexOf('login_required') > -1
192+
error.message.indexOf('login_required') > -1 ||
193+
error.message.indexOf('no_account_in_silent_request') > -1
185194
);
186195
}
187196
}

tutorial/02-create-app.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ Before moving on, install some additional packages that you will use later:
2626
- [fontawesome-free](https://github.com/FortAwesome/Font-Awesome) for icons.
2727
- [moment](https://github.com/moment/moment) for formatting dates and times.
2828
- [windows-iana](https://github.com/rubenillodo/windows-iana) for translating Windows time zones to IANA format.
29-
- [msal](https://github.com/AzureAD/microsoft-authentication-library-for-js) for authenticating to Azure Active Directory and retrieving access tokens.
29+
- [msal-browser](https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-browser) for authenticating to Azure Active Directory and retrieving access tokens.
3030
- [microsoft-graph-client](https://github.com/microsoftgraph/msgraph-sdk-javascript) for making calls to Microsoft Graph.
3131
3232
Run the following command in your CLI.
3333
3434
```Shell
3535
36-
36+
3737
```
3838
3939
## Design the app

tutorial/03-register-app.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,10 @@ In this exercise, you will create a new Azure AD web application registration us
1515

1616
- Set **Name** to `React Graph Tutorial`.
1717
- Set **Supported account types** to **Accounts in any organizational directory and personal Microsoft accounts**.
18-
- Under **Redirect URI**, set the first drop-down to `Web` and set the value to `http://localhost:3000`.
18+
- Under **Redirect URI**, set the first drop-down to `Single-page application (SPA)` and set the value to `http://localhost:3000`.
1919

2020
![A screenshot of the Register an application page](./images/aad-register-an-app.png)
2121

2222
1. Choose **Register**. On the **React Graph Tutorial** page, copy the value of the **Application (client) ID** and save it, you will need it in the next step.
2323

2424
![A screenshot of the application ID of the new app registration](./images/aad-application-id.png)
25-
26-
1. Select **Authentication** under **Manage**. Locate the **Implicit grant** section and enable **Access tokens** and **ID tokens**. Choose **Save**.
27-
28-
![A screenshot of the Implicit grant section](./images/aad-implicit-grant.png)

tutorial/04-add-aad-auth.md

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ In this section you'll create an authentication provider and implement sign-in a
1919

2020
```typescript
2121
import React from 'react';
22-
import { UserAgentApplication } from 'msal';
22+
import { PublicClientApplication } from '@azure/msal-browser';
2323

2424
import { config } from './Config';
2525

@@ -42,7 +42,7 @@ In this section you'll create an authentication provider and implement sign-in a
4242
export default function withAuthProvider<T extends React.Component<AuthComponentProps>>
4343
(WrappedComponent: new(props: AuthComponentProps, context?: any) => T): React.ComponentClass {
4444
return class extends React.Component<any, AuthProviderState> {
45-
private userAgentApplication: UserAgentApplication;
45+
private publicClientApplication: PublicClientApplication;
4646

4747
constructor(props: any) {
4848
super(props);
@@ -53,7 +53,7 @@ In this section you'll create an authentication provider and implement sign-in a
5353
};
5454

5555
// Initialize the MSAL application object
56-
this.userAgentApplication = new UserAgentApplication({
56+
this.publicClientApplication = new PublicClientApplication({
5757
auth: {
5858
clientId: config.appId,
5959
redirectUri: config.redirectUri
@@ -68,9 +68,9 @@ In this section you'll create an authentication provider and implement sign-in a
6868
componentDidMount() {
6969
// If MSAL already has an account, the user
7070
// is already logged in
71-
var account = this.userAgentApplication.getAccount();
71+
const accounts = this.publicClientApplication.getAllAccounts();
7272

73-
if (account) {
73+
if (accounts && accounts.length > 0) {
7474
// Enhance user object with data from Graph
7575
this.getUserProfile();
7676
}
@@ -91,11 +91,12 @@ In this section you'll create an authentication provider and implement sign-in a
9191
async login() {
9292
try {
9393
// Login via popup
94-
await this.userAgentApplication.loginPopup(
94+
await this.publicClientApplication.loginPopup(
9595
{
9696
scopes: config.scopes,
9797
prompt: "select_account"
9898
});
99+
99100
// After login, get the user's profile
100101
await this.getUserProfile();
101102
}
@@ -109,27 +110,34 @@ In this section you'll create an authentication provider and implement sign-in a
109110
}
110111

111112
logout() {
112-
this.userAgentApplication.logout();
113+
this.publicClientApplication.logout();
113114
}
114115

115116
async getAccessToken(scopes: string[]): Promise<string> {
116117
try {
118+
const accounts = this.publicClientApplication
119+
.getAllAccounts();
120+
121+
if (accounts.length <= 0) throw new Error('login_required');
117122
// Get the access token silently
118123
// If the cache contains a non-expired token, this function
119124
// will just return the cached token. Otherwise, it will
120125
// make a request to the Azure OAuth endpoint to get a token
121-
var silentResult = await this.userAgentApplication.acquireTokenSilent({
122-
scopes: scopes
123-
});
126+
var silentResult = await this.publicClientApplication
127+
.acquireTokenSilent({
128+
scopes: scopes,
129+
account: accounts[0]
130+
});
124131

125132
return silentResult.accessToken;
126133
} catch (err) {
127134
// If a silent request fails, it may be because the user needs
128135
// to login or grant consent to one or more of the requested scopes
129136
if (this.isInteractionRequired(err)) {
130-
var interactiveResult = await this.userAgentApplication.acquireTokenPopup({
131-
scopes: scopes
132-
});
137+
var interactiveResult = await this.publicClientApplication
138+
.acquireTokenPopup({
139+
scopes: scopes
140+
});
133141

134142
return interactiveResult.accessToken;
135143
} else {
@@ -189,7 +197,8 @@ In this section you'll create an authentication provider and implement sign-in a
189197
return (
190198
error.message.indexOf('consent_required') > -1 ||
191199
error.message.indexOf('interaction_required') > -1 ||
192-
error.message.indexOf('login_required') > -1
200+
error.message.indexOf('login_required') > -1 ||
201+
error.message.indexOf('no_account_in_silent_request') > -1
193202
);
194203
}
195204
}
@@ -250,4 +259,4 @@ At this point your application has an access token, which is sent in the `Author
250259

251260
However, this token is short-lived. The token expires an hour after it is issued. This is where the refresh token becomes useful. The refresh token allows the app to request a new access token without requiring the user to sign in again.
252261

253-
Because the app is using the MSAL library, you do not have to implement any token storage or refresh logic. The `UserAgentApplication` caches the token in the browser session. The `acquireTokenSilent` method first checks the cached token, and if it is not expired, it returns it. If it is expired, it uses the cached refresh token to obtain a new one. You'll use this method more in the following module.
262+
Because the app is using the MSAL library, you do not have to implement any token storage or refresh logic. The `PublicClientApplication` caches the token in the browser session. The `acquireTokenSilent` method first checks the cached token, and if it is not expired, it returns it. If it is expired, it uses the cached refresh token to obtain a new one. You'll use this method more in the following module.
22.7 KB
Loading

0 commit comments

Comments
 (0)