1
0
mirror of https://github.com/redis/node-redis.git synced 2025-07-31 05:44:24 +03:00
Files
Bobby I. 8b4ed0059a feat(entraid): add support for azure identity (#2901)
This PR adds support for using Azure Identity's credential classes with Redis Enterprise Entra ID authentication.
The main changes include:

- Add a new factory method createForDefaultAzureCredential to enable using Azure Identity credentials
- Add @azure/identity as a dependency to support the new authentication flow
- Add support for DefaultAzureCredential, EnvironmentCredential, and any other TokenCredential implementation
- Create a new AzureIdentityProvider to support DefaultAzureCredential
- Update documentation and README with usage examples for DefaultAzureCredential
- Add integration tests for the new authentication methods
- Include a sample application demonstrating interactive browser authentication
- Export constants for Redis scopes / credential mappers to simplify authentication configuration
2025-03-05 14:47:18 +02:00

112 lines
3.5 KiB
TypeScript

import express, { Request, Response } from 'express';
import session from 'express-session';
import dotenv from 'dotenv';
import { DEFAULT_TOKEN_MANAGER_CONFIG, EntraIdCredentialsProviderFactory } from '../../lib/entra-id-credentials-provider-factory';
import { InteractiveBrowserCredential } from '@azure/identity';
dotenv.config();
if (!process.env.SESSION_SECRET) {
throw new Error('SESSION_SECRET environment variable must be set');
}
const app = express();
const sessionConfig = {
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
secure: process.env.NODE_ENV === 'production', // Only use secure in production
httpOnly: true,
sameSite: 'lax',
maxAge: 3600000 // 1 hour
}
} as const;
app.use(session(sessionConfig));
if (!process.env.MSAL_CLIENT_ID || !process.env.MSAL_TENANT_ID) {
throw new Error('MSAL_CLIENT_ID and MSAL_TENANT_ID environment variables must be set');
}
app.get('/login', async (req: Request, res: Response) => {
try {
// Create an instance of InteractiveBrowserCredential
const credential = new InteractiveBrowserCredential({
clientId: process.env.MSAL_CLIENT_ID!,
tenantId: process.env.MSAL_TENANT_ID!,
loginStyle: 'popup',
redirectUri: 'http://localhost:3000/redirect'
});
// Create Redis client using the EntraID credentials provider
const entraidCredentialsProvider = EntraIdCredentialsProviderFactory.createForDefaultAzureCredential({
credential,
scopes: ['user.read'],
tokenManagerConfig: DEFAULT_TOKEN_MANAGER_CONFIG
});
// Subscribe to credentials updates
const initialCredentials = entraidCredentialsProvider.subscribe({
onNext: (token) => {
// Never log the full token in production
console.log('Token acquired successfully');
console.log('Username:', token.username);
},
onError: (error) => {
console.error('Token acquisition failed:', error);
}
});
// Wait for the initial credentials
const [credentials] = await initialCredentials;
// Return success response
res.json({
status: 'success',
message: 'Authentication successful',
credentials: {
username: credentials.username,
password: credentials.password
}
});
} catch (error) {
console.error('Authentication failed:', error);
res.status(500).json({
status: 'error',
message: 'Authentication failed',
error: error instanceof Error ? error.message : String(error)
});
}
});
// Create a simple status page
app.get('/', (req: Request, res: Response) => {
res.send(`
<html>
<head>
<title>Interactive Browser Credential Demo</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; line-height: 1.6; }
.button { display: inline-block; padding: 10px 20px; background: #0078d4; color: white; text-decoration: none; border-radius: 4px; }
</style>
</head>
<body>
<h1>Interactive Browser Credential Demo</h1>
<p>This example demonstrates using the InteractiveBrowserCredential from @azure/identity to authenticate with Microsoft Entra ID.</p>
<p>When you click the button below, you'll be redirected to the Microsoft login page.</p>
<a href="/login" class="button">Login with Microsoft</a>
</body>
</html>
`);
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
console.log(`Open http://localhost:${PORT} in your browser to start`);
});