Skip to content

Commit 7d2c07c

Browse files
Merge pull request #286148 from flang-msft/fxl---nodejs-ropc-entra-fix
Fxl---nodejs ropc entra fix
2 parents 2a018f0 + d5c139c commit 7d2c07c

File tree

1 file changed

+244
-34
lines changed

1 file changed

+244
-34
lines changed

articles/azure-cache-for-redis/cache-nodejs-get-started.md

Lines changed: 244 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,242 @@ In this quickstart, you incorporate Azure Cache for Redis into a Node.js app to
1717
## Prerequisites
1818

1919
- Azure subscription - [create one for free](https://azure.microsoft.com/free/)
20-
- [node_redis](https://github.com/mranney/node_redis), which you can install with the command `npm install redis`.
20+
- Node.js installed, if you haven't done so already. See [Install Node.js on Windows](/windows/dev-environment/javascript/nodejs-on-windows) for instructions on how to install Node and npm on a Windows computer.
2121

22-
For examples of using other Node.js clients, see the individual documentation for the Node.js clients listed at [Node.js Redis clients](https://redis.io/docs/connect/clients/nodejs/).
23-
24-
## Create a cache
22+
## Create a cache instance
2523

2624
[!INCLUDE [redis-cache-create](~/reusable-content/ce-skilling/azure/includes/azure-cache-for-redis/includes/redis-cache-create.md)]
2725

26+
## Install the node-redis client library
27+
28+
The [node-redis](https://github.com/redis/node-redis) library is the primary Node.js client for Redis. You can install the client with [npm](https://docs.npmjs.com/about-npm) by using the following command:
29+
30+
```bash
31+
npm install redis
32+
```
33+
34+
## Create a Node.js app to access a cache
35+
36+
Create a Node.js app that uses either Microsoft Entra ID or access keys to connect to an Azure Cache for Redis. We recommend you use Microsoft Entra ID.
37+
38+
## [Microsoft Entra ID Authentication (recommended)](#tab/entraid)
39+
40+
[!INCLUDE [cache-entra-access](includes/cache-entra-access.md)]
41+
42+
### Install the JavaScript Azure Identity client library
43+
44+
The [Microsoft Authentication Library (MSAL)](/entra/identity-platform/msal-overview) allows you to acquire security tokens from Microsoft identity to authenticate users. There's a [JavaScript Azure identity client library](/javascript/api/overview/azure/identity-readme) available that uses MSAL to provide token authentication support. Install this library using `npm`:
45+
46+
```bash
47+
npm install @azure/identity
48+
```
49+
50+
### Create a new Node.js app using Microsoft Entra ID
51+
52+
1. Add environment variables for your **Host name** and **Service Principal ID**, which is the object ID of your Microsoft Entra ID service principal or user. In the Azure portal, this is shown as the _Username_.
53+
54+
```cmd
55+
set AZURE_CACHE_FOR_REDIS_HOST_NAME=contosoCache
56+
set REDIS_SERVICE_PRINCIPAL_ID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
57+
```
58+
59+
1. Create a new script file named _redistest.js_.
60+
61+
1. Add the following example JavaScript to the file. This code shows you how to connect to an Azure Cache for Redis instance using the cache host name and key environment variables. The code also stores and retrieves a string value in the cache. The `PING` and `CLIENT LIST` commands are also executed. For more examples of using Redis with the [node-redis](https://github.com/redis/node-redis) client, see [https://redis.js.org/](https://redis.js.org/).
62+
63+
```javascript
64+
const { createClient } = require("redis");
65+
const { DefaultAzureCredential } = require("@azure/identity");
66+
67+
async function main() {
68+
// Construct a Token Credential from Identity library, e.g. ClientSecretCredential / ClientCertificateCredential / ManagedIdentityCredential, etc.
69+
const credential = new DefaultAzureCredential();
70+
const redisScope = "https://redis.azure.com/.default";
71+
72+
// Fetch a Microsoft Entra token to be used for authentication. This token will be used as the password.
73+
let accessToken = await credential.getToken(redisScope);
74+
console.log("access Token", accessToken);
75+
76+
// Create redis client and connect to the Azure Cache for Redis over the TLS port using the access token as password.
77+
const cacheConnection = createClient({
78+
username: process.env.REDIS_SERVICE_PRINCIPAL_ID,
79+
password: accessToken.token,
80+
url: `redis://${process.env.AZURE_CACHE_FOR_REDIS_HOST_NAME}:6380`,
81+
pingInterval: 100000,
82+
socket: {
83+
tls: true,
84+
keepAlive: 0
85+
},
86+
});
87+
88+
cacheConnection.on("error", (err) => console.log("Redis Client Error", err));
89+
await cacheConnection.connect();
90+
91+
// PING command
92+
console.log("\nCache command: PING");
93+
console.log("Cache response : " + await cacheConnection.ping());
94+
95+
// SET
96+
console.log("\nCache command: SET Message");
97+
console.log("Cache response : " + await cacheConnection.set("Message",
98+
"Hello! The cache is working from Node.js!"));
99+
100+
// GET
101+
console.log("\nCache command: GET Message");
102+
console.log("Cache response : " + await cacheConnection.get("Message"));
103+
104+
// Client list, useful to see if connection list is growing...
105+
console.log("\nCache command: CLIENT LIST");
106+
console.log("Cache response : " + await cacheConnection.sendCommand(["CLIENT", "LIST"]));
107+
108+
cacheConnection.disconnect();
109+
110+
return "Done"
111+
}
112+
113+
main().then((result) => console.log(result)).catch(ex => console.log(ex));
114+
```
115+
116+
1. Run the script with Node.js.
117+
118+
```bash
119+
node redistest.js
120+
```
121+
122+
1. The output of your code looks like this.
123+
124+
```bash
125+
Cache command: PING
126+
Cache response : PONG
127+
128+
Cache command: GET Message
129+
Cache response : Hello! The cache is working from Node.js!
130+
131+
Cache command: SET Message
132+
Cache response : OK
133+
134+
Cache command: GET Message
135+
Cache response : Hello! The cache is working from Node.js!
136+
137+
Cache command: CLIENT LIST
138+
Cache response : id=10017364 addr=76.22.73.183:59380 fd=221 name= age=1 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 argv-mem=10 obl=0 oll=0 omem=0 tot-mem=61466 ow=0 owmem=0 events=r cmd=client user=default numops=6
139+
140+
Done
141+
```
142+
143+
### Create a sample JavaScript app with reauthentication
144+
145+
Microsoft Entra ID access tokens have a limited lifespan, [averaging 75 minutes](/entra/identity-platform/configurable-token-lifetimes#token-lifetime-policies-for-access-saml-and-id-tokens). In order to maintain a connection to your cache, you need to refresh the token. This example demonstrates how to do this using JavaScript.
146+
147+
1. Create a new script file named _redistestreauth.js_.
148+
149+
1. Add the following example JavaScript to the file.
150+
151+
```javascript
152+
const { createClient } = require("redis");
153+
const { DefaultAzureCredential } = require("@azure/identity");
154+
155+
async function returnPassword(credential) {
156+
const redisScope = "https://redis.azure.com/.default";
157+
158+
// Fetch a Microsoft Entra token to be used for authentication. This token will be used as the password.
159+
return credential.getToken(redisScope);
160+
}
161+
162+
async function main() {
163+
// Construct a Token Credential from Identity library, e.g. ClientSecretCredential / ClientCertificateCredential / ManagedIdentityCredential, etc.
164+
const credential = new DefaultAzureCredential();
165+
let accessToken = await returnPassword(credential);
166+
167+
// Create redis client and connect to the Azure Cache for Redis over the TLS port using the access token as password.
168+
let cacheConnection = createClient({
169+
username: process.env.REDIS_SERVICE_PRINCIPAL_ID,
170+
password: accessToken.token,
171+
url: `redis://${process.env.AZURE_CACHE_FOR_REDIS_HOST_NAME}:6380`,
172+
pingInterval: 100000,
173+
socket: {
174+
tls: true,
175+
keepAlive: 0
176+
},
177+
});
178+
179+
cacheConnection.on("error", (err) => console.log("Redis Client Error", err));
180+
await cacheConnection.connect();
181+
182+
for (let i = 0; i < 3; i++) {
183+
try {
184+
// PING command
185+
console.log("\nCache command: PING");
186+
console.log("Cache response : " + await cacheConnection.ping());
187+
188+
// SET
189+
console.log("\nCache command: SET Message");
190+
console.log("Cache response : " + await cacheConnection.set("Message",
191+
"Hello! The cache is working from Node.js!"));
192+
193+
// GET
194+
console.log("\nCache command: GET Message");
195+
console.log("Cache response : " + await cacheConnection.get("Message"));
196+
197+
// Client list, useful to see if connection list is growing...
198+
console.log("\nCache command: CLIENT LIST");
199+
console.log("Cache response : " + await cacheConnection.sendCommand(["CLIENT", "LIST"]));
200+
break;
201+
} catch (e) {
202+
console.log("error during redis get", e.toString());
203+
if ((accessToken.expiresOnTimestamp <= Date.now())|| (redis.status === "end" || "close") ) {
204+
await redis.disconnect();
205+
accessToken = await returnPassword(credential);
206+
cacheConnection = createClient({
207+
username: process.env.REDIS_SERVICE_PRINCIPAL_ID,
208+
password: accessToken.token,
209+
url: `redis://${process.env.AZURE_CACHE_FOR_REDIS_HOST_NAME}:6380`,
210+
pingInterval: 100000,
211+
socket: {
212+
tls: true,
213+
keepAlive: 0
214+
},
215+
});
216+
}
217+
}
218+
}
219+
}
220+
221+
main().then((result) => console.log(result)).catch(ex => console.log(ex));
222+
```
223+
224+
1. Run the script with Node.js.
225+
226+
```bash
227+
node redistestreauth.js
228+
```
229+
230+
1. The output of your code looks like this.
231+
232+
```bash
233+
Cache command: PING
234+
Cache response : PONG
235+
236+
Cache command: GET Message
237+
Cache response : Hello! The cache is working from Node.js!
238+
239+
Cache command: SET Message
240+
Cache response : OK
241+
242+
Cache command: GET Message
243+
Cache response : Hello! The cache is working from Node.js!
244+
245+
Cache command: CLIENT LIST
246+
Cache response : id=10017364 addr=76.22.73.183:59380 fd=221 name= age=1 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 argv-mem=10 obl=0 oll=0 omem=0 tot-mem=61466 ow=0 owmem=0 events=r cmd=client user=default numops=6
247+
248+
```
249+
250+
>[!NOTE]
251+
>For additional examples of using Microsoft Entra ID to authenticate to Redis using the node-redis library, please see [this GitHub repo](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/identity/identity/samples/AzureCacheForRedis/node-redis.md)
252+
>
253+
254+
## [Access Key Authentication](#tab/accesskey)
255+
28256
[!INCLUDE [redis-cache-access-keys](includes/redis-cache-access-keys.md)]
29257

30258
Add environment variables for your **HOST NAME** and **Primary** access key. Use these variables from your code instead of including the sensitive information directly in your code.
@@ -34,18 +262,15 @@ set AZURE_CACHE_FOR_REDIS_HOST_NAME=contosoCache
34262
set AZURE_CACHE_FOR_REDIS_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
35263
```
36264

37-
## Connect to the cache
265+
### Connect to the cache
38266

39-
The latest builds of [node_redis](https://github.com/mranney/node_redis) provide support several connection options. Don't create a new connection for each operation in your code. Instead, reuse connections as much as possible.
267+
>[!NOTE]
268+
> Don't create a new connection for each operation in your code. Instead, reuse connections as much as possible.
269+
>
40270
41-
## Create a new Node.js app
271+
### Create a new Node.js app
42272
43-
1. Create a new script file named *redistest.js*.
44-
1. Use the command to install a redis package.
45-
46-
```bash
47-
`npm install redis`
48-
```
273+
1. Create a new script file named _redistest.js_.
49274
50275
1. Add the following example JavaScript to the file.
51276
@@ -101,7 +326,7 @@ The latest builds of [node_redis](https://github.com/mranney/node_redis) provide
101326
testCache().then((result) => console.log(result)).catch(ex => console.log(ex));
102327
```
103328
104-
This code shows you how to connect to an Azure Cache for Redis instance using the cache host name and key environment variables. The code also stores and retrieves a string value in the cache. The `PING` and `CLIENT LIST` commands are also executed. For more examples of using Redis with the [node_redis](https://github.com/mranney/node_redis) client, see [https://redis.js.org/](https://redis.js.org/).
329+
This code shows you how to connect to an Azure Cache for Redis instance using the cache host name and key environment variables. The code also stores and retrieves a string value in the cache. The `PING` and `CLIENT LIST` commands are also executed. For more examples of using Redis with the [node_redis](https://github.com/redis/node-redis) client, see [https://redis.js.org/](https://redis.js.org/).
105330
106331
1. Run the script with Node.js.
107332
@@ -111,7 +336,7 @@ The latest builds of [node_redis](https://github.com/mranney/node_redis) provide
111336
112337
1. Example the output.
113338
114-
```console
339+
```bash
115340
Cache command: PING
116341
Cache response : PONG
117342
@@ -130,31 +355,16 @@ The latest builds of [node_redis](https://github.com/mranney/node_redis) provide
130355
Done
131356
```
132357
133-
## Clean up resources
134-
135-
If you continue to the next tutorial, can keep the resources created in this quickstart and reuse them. Otherwise, if you're finished with the quickstart sample application, you can delete the Azure resources created in this quickstart to avoid charges.
136-
137-
> [!IMPORTANT]
138-
> Deleting a resource group is irreversible and that the resource group and all the resources in it are permanently deleted. Make sure that you do not accidentally delete the wrong resource group or resources. If you created the resources for hosting this sample inside an existing resource group that contains resources you want to keep, you can delete each resource individually instead of deleting the resource group.
139-
>
140-
141-
1. Sign in to the [Azure portal](https://portal.azure.com) and select **Resource groups**.
142-
143-
1. In the **Filter by name** text box, enter the name of your resource group. The instructions for this article used a resource group named *TestResources*. On your resource group in the result list, select **...** then **Delete resource group**.
144-
145-
![Delete Azure Resource group](./media/cache-nodejs-get-started/redis-cache-delete-resource-group.png)
146-
147-
1. Confirm the deletion of the resource group. Enter the name of your resource group to confirm, and select **Delete**.
358+
---
148359
149-
1. After a few moments, the resource group and all of its contained resources are deleted.
360+
[!INCLUDE [cache-delete-resource-group](includes/cache-delete-resource-group.md)]
150361
151362
## Get the sample code
152363
153364
Get the [Node.js quickstart](https://github.com/Azure-Samples/azure-cache-redis-samples/tree/main/quickstart/nodejs) on GitHub.
154365
155-
## Next steps
366+
## Related content
156367
157368
In this quickstart, you learned how to use Azure Cache for Redis from a Node.js application. Continue to the next quickstart to use Azure Cache for Redis with an ASP.NET web app.
158369
159-
> [!div class="nextstepaction"]
160-
> [Create an ASP.NET web app that uses an Azure Cache for Redis.](./cache-web-app-howto.md)
370+
- [Create an ASP.NET web app that uses an Azure Cache for Redis.](cache-web-app-howto.md)

0 commit comments

Comments
 (0)