Skip to content

Commit c41881f

Browse files
authored
Merge pull request #371 from microsoftgraph/Authentication
@azure/identity-TokenCredential
2 parents 23fc68e + c9aff66 commit c41881f

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

+23986
-2647
lines changed

.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ npm-debug.log
1414
/lib/*
1515
!/lib/.npmignore
1616

17+
/authProviders/*
18+
19+
src/**/*.js
20+
src/**/*.js.map
21+
src/**/*.d.ts
22+
23+
samples/**/secrets.ts
24+
samples/**/secrets.js
1725
samples/node/secrets.json
1826
samples/browser/src/secrets.js
1927
samples/browser/src/graph-js-sdk.js

README.md

+5-54
Original file line numberDiff line numberDiff line change
@@ -55,64 +55,15 @@ Register your application to use Microsoft Graph API using one of the following
5555

5656
### 2. Authenticate for the Microsoft Graph service
5757

58-
The Microsoft Graph JavaScript Client Library has an adapter implementation ([ImplicitMSALAuthenticationProvider](src/ImplicitMSALAuthenticationProvider.ts)) for [MSAL](https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-core) (Microsoft Authentication Library) which takes care of getting the `accessToken`. MSAL library does not ship with this library, user has to include it externally (For including MSAL, refer [this](https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-core#installation)).
58+
The Microsoft Graph JavaScript Client Library has an adapter implementation for the following -
5959

60-
> **Important Note:** MSAL is supported only for frontend applications, for server-side authentication you have to implement your own AuthenticationProvider. Learn how you can create a [Custom Authentication Provider](./docs/CustomAuthenticationProvider.md).
60+
- ([TokenCredentialAuthenticationProvider](src/authentication/TokenCredentialAuthenticationProvider.ts)) to support [Azure Identity TokenCredential](https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/identity/identity/README.md) (Azure Identity client library for JavaScript) which takes care of getting the `accessToken`. @azure/identity library does not ship with this library, user has to include it externally (For including @azure/identity, refer [this](https://www.npmjs.com/package/@azure/identity)).
6161

62-
#### Creating an instance of ImplicitMSALAuthenticationProvider in browser environment
62+
> Learn how to [create an instance of TokenCredentialAuthenticationProvider](./docs/TokenCredentialAuthenticationProvider.md).
6363
64-
Refer devDependencies in [package.json](./package.json) for the compatible msal version and update that version in below.
64+
- ([ImplicitMSALAuthenticationProvider](src/ImplicitMSALAuthenticationProvider.ts)) for [MSAL](https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-core) (Microsoft Authentication Library) which takes care of getting the `accessToken`. MSAL library does not ship with this library, user has to include it externally (For including MSAL, refer [this](https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-core#installation)).
6565

66-
```html
67-
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/<version>/js/msal.min.js"></script>
68-
```
69-
70-
```typescript
71-
// Configuration options for MSAL @see https://github.com/AzureAD/microsoft-authentication-library-for-js/wiki/MSAL.js-1.0.0-api-release#configuration-options
72-
const msalConfig = {
73-
auth: {
74-
clientId: "your_client_id", // Client Id of the registered application
75-
redirectUri: "your_redirect_uri",
76-
},
77-
};
78-
const graphScopes = ["user.read", "mail.send"]; // An array of graph scopes
79-
80-
// Important Note: This library implements loginPopup and acquireTokenPopup flow, remember this while initializing the msal
81-
// Initialize the MSAL @see https://github.com/AzureAD/microsoft-authentication-library-for-js#1-instantiate-the-useragentapplication
82-
const msalApplication = new Msal.UserAgentApplication(msalConfig);
83-
const options = new MicrosoftGraph.MSALAuthenticationProviderOptions(graphScopes);
84-
const authProvider = new MicrosoftGraph.ImplicitMSALAuthenticationProvider(msalApplication, options);
85-
```
86-
87-
#### Creating an instance of ImplicitMSALAuthenticationProvider in node environment
88-
89-
Refer devDependencies in [package.json](./package.json) for the compatible msal version and update that version in below.
90-
91-
```cmd
92-
npm install msal@<version>
93-
```
94-
95-
```typescript
96-
import { UserAgentApplication } from "msal";
97-
98-
import { ImplicitMSALAuthenticationProvider } from "@microsoft/microsoft-graph-client/lib/src/ImplicitMSALAuthenticationProvider";
99-
import { MSALAuthenticationProviderOptions } from "@microsoft/microsoft-graph-client/lib/src/MSALAuthenticationProviderOptions";
100-
101-
// An Optional options for initializing the MSAL @see https://github.com/AzureAD/microsoft-authentication-library-for-js/wiki/MSAL-basics#configuration-options
102-
const msalConfig = {
103-
auth: {
104-
clientId: "your_client_id", // Client Id of the registered application
105-
redirectUri: "your_redirect_uri",
106-
},
107-
};
108-
const graphScopes = ["user.read", "mail.send"]; // An array of graph scopes
109-
110-
// Important Note: This library implements loginPopup and acquireTokenPopup flow, remember this while initializing the msal
111-
// Initialize the MSAL @see https://github.com/AzureAD/microsoft-authentication-library-for-js#1-instantiate-the-useragentapplication
112-
const msalApplication = new UserAgentApplication(msalConfig);
113-
const options = new MSALAuthenticationProviderOptions(graphScopes);
114-
const authProvider = new ImplicitMSALAuthenticationProvider(msalApplication, options);
115-
```
66+
> Learn how to [create an instance of ImplicitMSALAuthenticationProvider](./docs/ImplicitMSALAuthenticationProvider.md).
11667
11768
User can integrate own preferred authentication library by implementing `IAuthenticationProvider` interface. Refer implementing [Custom Authentication Provider](./docs/CustomAuthenticationProvider.md).
11869

authProviderOptions/ReadMe.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
The authProviderOptions/ folders contains barrels for exporting Authentication Provider options such as MSAL and Azure Identity Token Credentials.
2+
3+
[tsconfig-sub-cjs.json](../tsconfig-sub-es.json) and [tsconfig-sub-cjs.json](../tsconfig-sub-es.json) contains the config for transpiling the files to authProviders/ output folder.
4+
5+
This approach is used because of the limitations of creating a submodule structure - References - https://github.com/microsoft/TypeScript/issues/8305 https://github.com/microsoft/TypeScript/issues/33079
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* -------------------------------------------------------------------------------------------
3+
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
4+
* See License in the project root for license information.
5+
* -------------------------------------------------------------------------------------------
6+
*/
7+
export * from "../../lib/src/authentication/azureTokenCredentials/TokenCredentialAuthenticationProvider";
8+
export * from "../../lib/src/authentication/azureTokenCredentials/ITokenCredentialAuthenticationProviderOptions";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* -------------------------------------------------------------------------------------------
3+
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
4+
* See License in the project root for license information.
5+
* -------------------------------------------------------------------------------------------
6+
*/
7+
export * from "../../../lib/es/src/authentication/azureTokenCredentials/TokenCredentialAuthenticationProvider";
8+
export * from "../../../lib/es/src/authentication/azureTokenCredentials/ITokenCredentialAuthenticationProviderOptions";

authProviderOptions/es/msal/index.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* -------------------------------------------------------------------------------------------
3+
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
4+
* See License in the project root for license information.
5+
* -------------------------------------------------------------------------------------------
6+
*/
7+
8+
export * from "../../../lib/es/src/authentication/msal/ImplicitMSALAuthenticationProvider";
9+
export * from "../../../lib/es/src/authentication/msal/MSALAuthenticationProviderOptions";

authProviderOptions/msal/index.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* -------------------------------------------------------------------------------------------
3+
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
4+
* See License in the project root for license information.
5+
* -------------------------------------------------------------------------------------------
6+
*/
7+
export * from "../../lib/src/authentication/msal/MSALAuthenticationProviderOptions";
8+
export * from "../../lib/src/authentication/msal/ImplicitMSALAuthenticationProvider";
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#### Creating an instance of ImplicitMSALAuthenticationProvider in browser environment
2+
3+
Refer devDependencies in [package.json](../package.json) for the compatible msal version and update that version in below.
4+
5+
**Important Note:** MSAL is supported only for frontend applications, for server-side authentication you either can use [TokenCredentialAuthenticationProvider](./TokenCredentialAuthenticationProvider.md) or implement your own AuthenticationProvider. Learn how you can create a [Custom Authentication Provider](./docs/CustomAuthenticationProvider.md).
6+
7+
```html
8+
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/<version>/js/msal.min.js"></script>
9+
```
10+
11+
```typescript
12+
// Configuration options for MSAL @see https://github.com/AzureAD/microsoft-authentication-library-for-js/wiki/MSAL.js-1.0.0-api-release#configuration-options
13+
const msalConfig = {
14+
auth: {
15+
clientId: "your_client_id", // Client Id of the registered application
16+
redirectUri: "your_redirect_uri",
17+
},
18+
};
19+
const graphScopes = ["user.read", "mail.send"]; // An array of graph scopes
20+
21+
// Important Note: This library implements loginPopup and acquireTokenPopup flow, remember this while initializing the msal
22+
// Initialize the MSAL @see https://github.com/AzureAD/microsoft-authentication-library-for-js#1-instantiate-the-useragentapplication
23+
const msalApplication = new Msal.UserAgentApplication(msalConfig);
24+
const options = new MicrosoftGraph.MSALAuthenticationProviderOptions(graphScopes);
25+
const authProvider = new MicrosoftGraph.ImplicitMSALAuthenticationProvider(msalApplication, options);
26+
```
27+
28+
#### Creating an instance of ImplicitMSALAuthenticationProvider in node environment
29+
30+
Refer devDependencies in [package.json](./package.json) for the compatible msal version and update that version in below.
31+
32+
```cmd
33+
npm install msal@<version>
34+
```
35+
36+
```typescript
37+
import { UserAgentApplication } from "msal";
38+
39+
import { ImplicitMSALAuthenticationProvider, MSALAuthenticationProviderOptions } from "@microsoft/microsoft-graph-client/authProviders/msal";
40+
41+
// An Optional options for initializing the MSAL @see https://github.com/AzureAD/microsoft-authentication-library-for-js/wiki/MSAL-basics#configuration-options
42+
const msalConfig = {
43+
auth: {
44+
clientId: "your_client_id", // Client Id of the registered application
45+
redirectUri: "your_redirect_uri",
46+
},
47+
};
48+
const graphScopes = ["user.read", "mail.send"]; // An array of graph scopes
49+
50+
// Important Note: This library implements loginPopup and acquireTokenPopup flow, remember this while initializing the msal
51+
52+
// Initialize the MSAL @see https://github.com/AzureAD/microsoft-authentication-library-for-js#1-instantiate-the-useragentapplication
53+
const msalApplication = new UserAgentApplication(msalConfig);
54+
const options = new MSALAuthenticationProviderOptions(graphScopes);
55+
const authProvider = new ImplicitMSALAuthenticationProvider(msalApplication, options);
56+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#### Creating an instance of TokenCredentialAuthentication
2+
3+
###### Links for more information -
4+
5+
- [GitHub - Azure Identity client library for JavaScript ](https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/identity/identity/README.md)
6+
7+
- [npm - Azure Identity client library for JavaScript](https://www.npmjs.com/package/@azure/identity)
8+
9+
- Check the [tokenCredentialSamples folder][../samples/tokencredentialsamples]. The ClientSecretCredentialFlow is an example of using TokenCredential to authenticate a node application. The AuthenticationCodeFlow is an example of using TokenCredential to authenticate a browser application.
10+
11+
**Important Note:** TokenCredentials can be used to authenticate browser and node applications.
12+
13+
###### Example of how to create and pass a token credential -
14+
15+
```typescript
16+
// Import the TokenCredential class that you wish to use. This example uses a Client SecretCredential
17+
18+
import { ClientSecretCredential } from "@azure/identity";
19+
import { TokenCredentialAuthenticationProvider, TokenCredentialAuthenticationProviderOptions } from "@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials";
20+
21+
// Create an instance of the TokenCredential class that is imported
22+
const tokenCredential = new ClientSecretCredential("your_tenantId", "your_clientId", "your_clientSecret");
23+
24+
// Set your scopes and options for TokenCredential.getToken (Check the ` interface GetTokenOptions` in (TokenCredential Implementation)[https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/core/core-auth/src/tokenCredential.ts])
25+
26+
const options: TokenCredentialAuthenticationProviderOptions = { scopes: [scopes], getTokenOptions };
27+
28+
// Create an instance of the TokenCredentialAuthenticationProvider by passing the tokenCredential instance and options to the constructor
29+
const authProvider = new TokenCredentialAuthenticationProvider(tokenCredential, options);
30+
const client = Client.initWithMiddleware({
31+
debugLogging: true,
32+
authProvider: authProvider,
33+
});
34+
const res = await client.api("/users/").get();
35+
```
36+
37+
```javascript
38+
// Import the TokenCredential class that you wish to use. This examples uses a ClientSecretCredential
39+
40+
const { ClientSecretCredential } = require("@azure/identity");
41+
const { Client } = require("@microsoft/microsoft-graph-client");
42+
const { TokenCredentialAuthenticationProvider } = require("@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials");
43+
44+
// Create an instance of the TokenCredential class that is imported
45+
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
46+
47+
// Set your scopes and options for TokenCredential.getToken (Check the ` interface GetTokenOptions` in (TokenCredential Implementation)[https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/core/core-auth/src/tokenCredential.ts])
48+
49+
const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: [scopes] });
50+
51+
const client = Client.initWithMiddleware({
52+
debugLogging: true,
53+
authProvider,
54+
});
55+
const res = await client.api("/users/").get();
56+
```

docs/content/Batching.md

+69-69
Original file line numberDiff line numberDiff line change
@@ -66,79 +66,79 @@ const serialBatching = async function(elem) {
6666
};
6767
```
6868

69-
### Download multiple profile photos with batching and preprocess these for rendering in a browser
69+
### Download multiple profile photos with batching and preprocess these for rendering in a browser
7070

7171
You should convert the downloaded photos through batching to a Base64 representation if you want to render these in a browser.
7272

7373
```typescript
74-
b64toBlob = async (b64Data:any, contentType:string, sliceSize?:number):Promise<Blob> => {
75-
contentType = contentType || 'image/png';
76-
sliceSize = sliceSize || 512;
77-
78-
let byteCharacters:string = atob(b64Data);
79-
let byteArrays = [];
80-
81-
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
82-
let slice = byteCharacters.slice(offset, offset + sliceSize);
83-
84-
let byteNumbers = new Array(slice.length);
85-
for (let i = 0; i < slice.length; i++) {
86-
byteNumbers[i] = slice.charCodeAt(i);
87-
}
88-
89-
let byteArray = new Uint8Array(byteNumbers);
90-
byteArrays.push(byteArray);
91-
}
92-
93-
let blob = new Blob(byteArrays, {type: contentType});
94-
return blob;
95-
};
96-
97-
blobToBase64 = (blob: Blob): Promise<string> => {
98-
return new Promise((resolve, reject) => {
99-
const reader = new FileReader();
100-
reader.onerror = reject;
101-
reader.onload = _ => {
102-
resolve(reader.result as string);
103-
};
104-
reader.readAsDataURL(blob);
105-
});
106-
};
107-
108-
downloadPhotosBatching = async (client: Client) => {
109-
try {
110-
111-
112-
// create batch request steps for the users specified above
113-
const batchRequestSteps : BatchRequestStep[] = users.map((userId) => {
114-
const request : BatchRequestStep = {
115-
id: userId,
116-
request: new Request(`/users/${userId}/photo/$value`, {
117-
method: "GET",
118-
})
119-
};
120-
return request;
121-
})
122-
123-
// initiate the batchrequest and execute the operation
124-
const batchRequestContent = new BatchRequestContent(batchRequestSteps);
125-
const content = await batchRequestContent.getContent();
126-
const batchResponse = new BatchResponseContent(await client.api("/$batch").post(content));
127-
128-
// example on how to retrieve the base64 representation of the downloaded image for the first user
129-
const response = batchResponse.getResponseById(users[0]);
130-
if (response.ok) {
131-
var data = await response.text();
132-
const binToBlob = await this.b64toBlob((data),'img/jpg');
133-
134-
// you can associate the base64 output to an src attribute of an <img> HTML tag
135-
const base64Result = await this.blobToBase64(binToBlob);
136-
console.log(base64Result);
137-
}
138-
} catch (error) {
139-
console.error(error);
140-
}
141-
};
74+
b64toBlob = async (b64Data: any, contentType: string, sliceSize?: number): Promise<Blob> => {
75+
contentType = contentType || "image/png";
76+
sliceSize = sliceSize || 512;
77+
78+
let byteCharacters: string = atob(b64Data);
79+
let byteArrays = [];
80+
81+
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
82+
let slice = byteCharacters.slice(offset, offset + sliceSize);
83+
84+
let byteNumbers = new Array(slice.length);
85+
for (let i = 0; i < slice.length; i++) {
86+
byteNumbers[i] = slice.charCodeAt(i);
87+
}
88+
89+
let byteArray = new Uint8Array(byteNumbers);
90+
byteArrays.push(byteArray);
91+
}
92+
93+
let blob = new Blob(byteArrays, { type: contentType });
94+
return blob;
95+
};
96+
97+
blobToBase64 = (blob: Blob): Promise<string> => {
98+
return new Promise((resolve, reject) => {
99+
const reader = new FileReader();
100+
reader.onerror = reject;
101+
reader.onload = (_) => {
102+
resolve(reader.result as string);
103+
};
104+
reader.readAsDataURL(blob);
105+
});
106+
};
107+
108+
downloadPhotosBatching = async (client: Client) => {
109+
try {
110+
111+
112+
// create batch request steps for the users specified above
113+
const batchRequestSteps: BatchRequestStep[] = users.map((userId) => {
114+
const request: BatchRequestStep = {
115+
id: userId,
116+
request: new Request(`/users/${userId}/photo/$value`, {
117+
method: "GET",
118+
}),
119+
};
120+
return request;
121+
});
122+
123+
// initiate the batchrequest and execute the operation
124+
const batchRequestContent = new BatchRequestContent(batchRequestSteps);
125+
const content = await batchRequestContent.getContent();
126+
const batchResponse = new BatchResponseContent(await client.api("/$batch").post(content));
127+
128+
// example on how to retrieve the base64 representation of the downloaded image for the first user
129+
const response = batchResponse.getResponseById(users[0]);
130+
if (response.ok) {
131+
var data = await response.text();
132+
const binToBlob = await this.b64toBlob(data, "img/jpg");
133+
134+
// you can associate the base64 output to an src attribute of an <img> HTML tag
135+
const base64Result = await this.blobToBase64(binToBlob);
136+
console.log(base64Result);
137+
}
138+
} catch (error) {
139+
console.error(error);
140+
}
141+
};
142142
```
143143

144144
### GET and POST contents from and to different workloads - Making parallel requests

0 commit comments

Comments
 (0)