Skip to content
This repository was archived by the owner on May 3, 2024. It is now read-only.

Commit ad0bca0

Browse files
committed
updated graph client method
1 parent bb5d03c commit ad0bca0

File tree

5 files changed

+32
-212
lines changed

5 files changed

+32
-212
lines changed

2-Authorization-I/1-call-graph/README.md

+13-95
Original file line numberDiff line numberDiff line change
@@ -400,12 +400,7 @@ export const Profile = () => {
400400
}
401401

402402
if (result) {
403-
getGraphClient({
404-
account: instance.getActiveAccount(),
405-
scopes: protectedResources.graphMe.scopes,
406-
interactionType: InteractionType.Popup,
407-
claims: claims,
408-
})
403+
getGraphClient(result.accessToken)
409404
.api('/me')
410405
.responseType(ResponseType.RAW)
411406
.get()
@@ -440,104 +435,27 @@ For more details on what's inside the access token, clients should use the token
440435

441436
### Calling the Microsoft Graph API
442437

443-
[Microsoft Graph JavaScript SDK](https://github.com/microsoftgraph/msgraph-sdk-javascript) provides various utility methods to query the Graph API. While the SDK has a default authentication provider that can be used in basic scenarios, it can also be extended to use with a custom authentication provider such as MSAL. To do so, we will initialize the Graph SDK client with [clientOptions](https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/CreatingClientInstance.md) method, which contains an `authProvider` object of class **MyAuthenticationProvider** that handles the token acquisition process for the client.
438+
[Microsoft Graph JavaScript SDK](https://github.com/microsoftgraph/msgraph-sdk-javascript) provides various utility methods to query the Graph API. While the SDK has a default authentication provider that can be used in basic scenarios, it can also be extended to use with a custom authentication provider such as MSAL. To do so, we will initialize the Graph SDK client with an [authProvider function](https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/CreatingClientInstance.md#2-create-with-options). In this case, user has to provide their own implementation for getting and refreshing accessToken. A callback will be passed into this `authProvider` function, accessToken or error needs to be passed in to that callback
444439

445440
```javascript
446-
export const getGraphClient = () => {
447-
let clientOptions = {
448-
authProvider: new MyAuthenticationProvider(),
449-
};
450-
const graphClient = Client.initWithMiddleware(clientOptions);
451-
return graphClient;
452-
}
453-
```
454-
455-
**MyAuthenticationProvider** needs to implement the [IAuthenticationProvider](https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/src/IAuthenticationProvider.ts) interface, which can be done as shown below:
456-
457-
```javascript
458-
class MsalAuthenticationProvider {
459-
account; // user account object to be used when attempting silent token acquisition
460-
scopes; // array of scopes required for this resource endpoint
461-
interactionType; // type of interaction to fallback to when silent token acquisition fails
462-
claims; // claims object required when fetching an access token
463-
464-
constructor(providerOptions) {
465-
this.account = providerOptions.account;
466-
this.scopes = providerOptions.scopes;
467-
this.interactionType = providerOptions.interactionType;
468-
this.claims = providerOptions.claims
469-
}
441+
export const getGraphClient = (accessToken) => {
442+
// Initialize Graph client
443+
const graphClient = Client.init({
444+
// Use the provided access token to authenticate requests
445+
authProvider: (done) => {
446+
done(null, accessToken);
447+
},
448+
});
470449

471-
/**
472-
* This method will get called before every request to the ms graph server
473-
* This should return a Promise that resolves to an accessToken (in case of success) or rejects with error (in case of failure)
474-
* Basically this method will contain the implementation for getting and refreshing accessTokens
475-
*/
476-
getAccessToken() {
477-
return new Promise(async (resolve, reject) => {
478-
let response;
479-
480-
try {
481-
response = await msalInstance.acquireTokenSilent({
482-
account: this.account,
483-
scopes: this.scopes,
484-
claims: this.claims
485-
});
486-
487-
if (response.accessToken) {
488-
resolve(response.accessToken);
489-
} else {
490-
reject(Error('Failed to acquire an access token'));
491-
}
492-
} catch (error) {
493-
// in case if silent token acquisition fails, fallback to an interactive method
494-
if (error instanceof InteractionRequiredAuthError) {
495-
switch (this.interactionType) {
496-
case InteractionType.Popup:
497-
response = await msalInstance.acquireTokenPopup({
498-
scopes: this.scopes,
499-
claims: this.claims,
500-
});
501-
502-
if (response.accessToken) {
503-
resolve(response.accessToken);
504-
} else {
505-
reject(Error('Failed to acquire an access token'));
506-
}
507-
break;
508-
case InteractionType.Redirect:
509-
/**
510-
* This will cause the app to leave the current page and redirect to the consent screen.
511-
* Once consent is provided, the app will return back to the current page and then the
512-
* silent token acquisition will succeed.
513-
*/
514-
515-
msalInstance.acquireTokenRedirect({
516-
scopes: this.scopes,
517-
claims: this.claims,
518-
});
519-
break;
520-
521-
default:
522-
break;
523-
}
524-
}
525-
}
526-
});
527-
}
528-
}
450+
return graphClient;
451+
};
529452
```
530453

531454
See [graph.js](./SPA/src/graph.js). The Graph client then can be used in your components as shown below:
532455

533456
```javascript
534457
if (result) {
535-
getGraphClient({
536-
account: instance.getActiveAccount(),
537-
scopes: protectedResources.graphMe.scopes,
538-
interactionType: InteractionType.Popup,
539-
claims: claims,
540-
})
458+
getGraphClient(result.accessToken)
541459
.api('/me')
542460
.responseType(ResponseType.RAW)
543461
.get()
+13-103
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,19 @@
1-
import { InteractionRequiredAuthError, InteractionType } from '@azure/msal-browser';
21
import { Client } from '@microsoft/microsoft-graph-client';
32

4-
import { msalInstance } from './index';
5-
6-
7-
/**
8-
* The code below demonstrates how you can use MSAL as a custom authentication provider for the Microsoft Graph JavaScript SDK.
9-
* You do NOT need to implement a custom provider. Microsoft Graph JavaScript SDK v3.0 (preview) offers AuthCodeMSALBrowserAuthenticationProvider
10-
* which handles token acquisition and renewal for you automatically. For more information on how to use it, visit:
11-
* https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/AuthCodeMSALBrowserAuthenticationProvider.md
12-
*/
13-
143
/**
15-
* Returns a graph client object with the provided token acquisition options
16-
* @param {Object} providerOptions: providerOptions: object containing user account, required scopes and interaction type
4+
* Creating a Graph client instance via options method. For more information, visit:
5+
* https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/CreatingClientInstance.md#2-create-with-options
6+
* @param {String} accessToken
7+
* @returns
178
*/
18-
export const getGraphClient = (providerOptions) => {
19-
/**
20-
* Pass the instance as authProvider in ClientOptions to instantiate the Client which will create and set the default middleware chain.
21-
* For more information, visit: https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/CreatingClientInstance.md
22-
*/
23-
let clientOptions = {
24-
authProvider: new MsalAuthenticationProvider(providerOptions),
25-
};
26-
27-
const graphClient = Client.initWithMiddleware(clientOptions);
9+
export const getGraphClient = (accessToken) => {
10+
// Initialize Graph client
11+
const graphClient = Client.init({
12+
// Use the provided access token to authenticate requests
13+
authProvider: (done) => {
14+
done(null, accessToken);
15+
},
16+
});
2817

2918
return graphClient;
30-
31-
}
32-
33-
34-
35-
/**
36-
* This class implements the IAuthenticationProvider interface, which allows a custom auth provider to be
37-
* used with the Graph client. See: https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/src/IAuthenticationProvider.ts
38-
*/
39-
class MsalAuthenticationProvider {
40-
account; // user account object to be used when attempting silent token acquisition
41-
scopes; // array of scopes required for this resource endpoint
42-
interactionType; // type of interaction to fallback to when silent token acquisition fails
43-
claims; // claims object required when fetching an access token
44-
45-
constructor(providerOptions) {
46-
this.account = providerOptions.account;
47-
this.scopes = providerOptions.scopes;
48-
this.interactionType = providerOptions.interactionType;
49-
this.claims = providerOptions.claims
50-
}
51-
52-
/**
53-
* This method will get called before every request to the ms graph server
54-
* This should return a Promise that resolves to an accessToken (in case of success) or rejects with error (in case of failure)
55-
* Basically this method will contain the implementation for getting and refreshing accessTokens
56-
*/
57-
getAccessToken() {
58-
return new Promise(async (resolve, reject) => {
59-
let response;
60-
61-
try {
62-
response = await msalInstance.acquireTokenSilent({
63-
account: this.account,
64-
scopes: this.scopes,
65-
claims: this.claims
66-
});
67-
68-
if (response.accessToken) {
69-
resolve(response.accessToken);
70-
} else {
71-
reject(Error('Failed to acquire an access token'));
72-
}
73-
} catch (error) {
74-
// in case if silent token acquisition fails, fallback to an interactive method
75-
if (error instanceof InteractionRequiredAuthError) {
76-
switch (this.interactionType) {
77-
case InteractionType.Popup:
78-
response = await msalInstance.acquireTokenPopup({
79-
scopes: this.scopes,
80-
claims: this.claims,
81-
});
82-
83-
if (response.accessToken) {
84-
resolve(response.accessToken);
85-
} else {
86-
reject(Error('Failed to acquire an access token'));
87-
}
88-
break;
89-
case InteractionType.Redirect:
90-
/**
91-
* This will cause the app to leave the current page and redirect to the consent screen.
92-
* Once consent is provided, the app will return back to the current page and then the
93-
* silent token acquisition will succeed.
94-
*/
95-
96-
msalInstance.acquireTokenRedirect({
97-
scopes: this.scopes,
98-
claims: this.claims,
99-
});
100-
break;
101-
102-
default:
103-
break;
104-
}
105-
}
106-
}
107-
});
108-
}
109-
}
19+
};

2-Authorization-I/1-call-graph/SPA/src/pages/Contacts.jsx

+3-7
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,8 @@ export const Contacts = () => {
4343
}
4444

4545
if (result) {
46-
getGraphClient({
47-
account: instance.getActiveAccount(),
48-
scopes: protectedResources.graphMe.scopes,
49-
interactionType: InteractionType.Popup,
50-
claims: claims,
51-
})
46+
let accessToken = result.accessToken;
47+
getGraphClient(accessToken)
5248
.api('/me/contacts')
5349
.responseType(ResponseType.RAW)
5450
.get()
@@ -64,7 +60,7 @@ export const Contacts = () => {
6460
login(InteractionType.Redirect, request);
6561
}
6662
console.log(error);
67-
})
63+
});
6864

6965
}
7066
}, [graphData, result, error, login]);

2-Authorization-I/1-call-graph/SPA/src/pages/Profile.jsx

+2-6
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,8 @@ export const Profile = () => {
4343
}
4444

4545
if (result) {
46-
getGraphClient({
47-
account: instance.getActiveAccount(),
48-
scopes: protectedResources.graphMe.scopes,
49-
interactionType: InteractionType.Popup,
50-
claims: claims,
51-
})
46+
let accessToken = result.accessToken;
47+
getGraphClient(accessToken)
5248
.api('/me')
5349
.responseType(ResponseType.RAW)
5450
.get()

2-Authorization-I/1-call-graph/SPA/src/styles/App.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
}
1616

1717
.navbarStyle {
18-
padding: .5rem 1rem
18+
padding: .5rem 1rem !important;
1919
}
2020

2121
.navbarButton {

0 commit comments

Comments
 (0)