@redis/entraid 5.0.0-next.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -0
- package/dist/lib/entra-id-credentials-provider-factory.d.ts +125 -0
- package/dist/lib/entra-id-credentials-provider-factory.d.ts.map +1 -0
- package/dist/lib/entra-id-credentials-provider-factory.js +240 -0
- package/dist/lib/entra-id-credentials-provider-factory.js.map +1 -0
- package/dist/lib/entraid-credentials-provider.d.ts +26 -0
- package/dist/lib/entraid-credentials-provider.d.ts.map +1 -0
- package/dist/lib/entraid-credentials-provider.js +104 -0
- package/dist/lib/entraid-credentials-provider.js.map +1 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +20 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/msal-identity-provider.d.ts +8 -0
- package/dist/lib/msal-identity-provider.d.ts.map +1 -0
- package/dist/lib/msal-identity-provider.js +26 -0
- package/dist/lib/msal-identity-provider.js.map +1 -0
- package/dist/lib/test-utils.d.ts +18 -0
- package/dist/lib/test-utils.d.ts.map +1 -0
- package/dist/lib/test-utils.js +46 -0
- package/dist/lib/test-utils.js.map +1 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# @redis/entraid
|
|
2
|
+
|
|
3
|
+
Secure token-based authentication for Redis clients using Microsoft Entra ID (formerly Azure Active Directory).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Token-based authentication using Microsoft Entra ID
|
|
8
|
+
- Automatic token refresh before expiration
|
|
9
|
+
- Automatic re-authentication of all connections after token refresh
|
|
10
|
+
- Support for multiple authentication flows:
|
|
11
|
+
- Managed identities (system-assigned and user-assigned)
|
|
12
|
+
- Service principals (with or without certificates)
|
|
13
|
+
- Authorization Code with PKCE flow
|
|
14
|
+
- Built-in retry mechanisms for transient failures
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @redis/client
|
|
20
|
+
npm install @redis/entraid
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Getting Started
|
|
24
|
+
|
|
25
|
+
The first step to using @redis/entraid is choosing the right credentials provider for your authentication needs. The `EntraIdCredentialsProviderFactory` class provides several factory methods to create the appropriate provider:
|
|
26
|
+
|
|
27
|
+
- `createForSystemAssignedManagedIdentity`: Use when your application runs in Azure with a system-assigned managed identity
|
|
28
|
+
- `createForUserAssignedManagedIdentity`: Use when your application runs in Azure with a user-assigned managed identity
|
|
29
|
+
- `createForClientCredentials`: Use when authenticating with a service principal using client secret
|
|
30
|
+
- `createForClientCredentialsWithCertificate`: Use when authenticating with a service principal using a certificate
|
|
31
|
+
- `createForAuthorizationCodeWithPKCE`: Use for interactive authentication flows in user applications
|
|
32
|
+
|
|
33
|
+
## Usage Examples
|
|
34
|
+
|
|
35
|
+
### Service Principal Authentication
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { createClient } from '@redis/client';
|
|
39
|
+
import { EntraIdCredentialsProviderFactory } from '@redis/entraid';
|
|
40
|
+
|
|
41
|
+
const provider = EntraIdCredentialsProviderFactory.createForClientCredentials({
|
|
42
|
+
clientId: 'your-client-id',
|
|
43
|
+
clientSecret: 'your-client-secret',
|
|
44
|
+
authorityConfig: {
|
|
45
|
+
type: 'multi-tenant',
|
|
46
|
+
tenantId: 'your-tenant-id'
|
|
47
|
+
},
|
|
48
|
+
tokenManagerConfig: {
|
|
49
|
+
expirationRefreshRatio: 0.8 // Refresh token after 80% of its lifetime
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const client = createClient({
|
|
54
|
+
url: 'redis://your-host',
|
|
55
|
+
credentialsProvider: provider
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
await client.connect();
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### System-Assigned Managed Identity
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const provider = EntraIdCredentialsProviderFactory.createForSystemAssignedManagedIdentity({
|
|
65
|
+
clientId: 'your-client-id',
|
|
66
|
+
tokenManagerConfig: {
|
|
67
|
+
expirationRefreshRatio: 0.8
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### User-Assigned Managed Identity
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const provider = EntraIdCredentialsProviderFactory.createForUserAssignedManagedIdentity({
|
|
76
|
+
clientId: 'your-client-id',
|
|
77
|
+
userAssignedClientId: 'your-user-assigned-client-id',
|
|
78
|
+
tokenManagerConfig: {
|
|
79
|
+
expirationRefreshRatio: 0.8
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Important Limitations
|
|
85
|
+
|
|
86
|
+
### RESP2 PUB/SUB Limitations
|
|
87
|
+
|
|
88
|
+
When using RESP2 (Redis Serialization Protocol 2), there are important limitations with PUB/SUB:
|
|
89
|
+
|
|
90
|
+
- **No Re-Authentication in PUB/SUB Mode**: In RESP2, once a connection enters PUB/SUB mode, the socket is blocked and cannot process out-of-band commands like AUTH. This means that connections in PUB/SUB mode cannot be re-authenticated when tokens are refreshed.
|
|
91
|
+
- **Connection Eviction**: As a result, PUB/SUB connections will be evicted by the Redis proxy when their tokens expire. The client will need to establish new connections with fresh tokens.
|
|
92
|
+
|
|
93
|
+
### Transaction Safety
|
|
94
|
+
|
|
95
|
+
When using token-based authentication, special care must be taken with Redis transactions. The token manager runs in the background and may attempt to re-authenticate connections at any time by sending AUTH commands. This can interfere with manually constructed transactions.
|
|
96
|
+
|
|
97
|
+
#### ✅ Recommended: Use the Official Transaction API
|
|
98
|
+
|
|
99
|
+
Always use the official transaction API provided by the client:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// Correct way to handle transactions
|
|
103
|
+
const multi = client.multi();
|
|
104
|
+
multi.set('key1', 'value1');
|
|
105
|
+
multi.set('key2', 'value2');
|
|
106
|
+
await multi.exec();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
#### ❌ Avoid: Manual Transaction Construction
|
|
110
|
+
|
|
111
|
+
Do not manually construct transactions by sending individual MULTI/EXEC commands:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// Incorrect and potentially dangerous
|
|
115
|
+
await client.sendCommand(['MULTI']);
|
|
116
|
+
await client.sendCommand(['SET', 'key1', 'value1']);
|
|
117
|
+
await client.sendCommand(['SET', 'key2', 'value2']);
|
|
118
|
+
await client.sendCommand(['EXEC']); // Risk of AUTH command being injected before EXEC
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Error Handling
|
|
122
|
+
|
|
123
|
+
The provider includes built-in retry mechanisms for transient errors:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
const provider = EntraIdCredentialsProviderFactory.createForClientCredentials({
|
|
127
|
+
// ... other config ...
|
|
128
|
+
tokenManagerConfig: {
|
|
129
|
+
retry: {
|
|
130
|
+
maxAttempts: 3,
|
|
131
|
+
initialDelayMs: 100,
|
|
132
|
+
maxDelayMs: 1000,
|
|
133
|
+
backoffMultiplier: 2
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
```
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { AuthenticationResult, PublicClientApplication } from '@azure/msal-node';
|
|
2
|
+
import { RetryPolicy, TokenManagerConfig, ReAuthenticationError } from '@redis/client/dist/lib/authx';
|
|
3
|
+
import { EntraidCredentialsProvider } from './entraid-credentials-provider';
|
|
4
|
+
/**
|
|
5
|
+
* This class is used to create credentials providers for different types of authentication flows.
|
|
6
|
+
*/
|
|
7
|
+
export declare class EntraIdCredentialsProviderFactory {
|
|
8
|
+
#private;
|
|
9
|
+
/**
|
|
10
|
+
* This method is used to create a ManagedIdentityProvider for both system-assigned and user-assigned managed identities.
|
|
11
|
+
*
|
|
12
|
+
* @param params
|
|
13
|
+
* @param userAssignedClientId For user-assigned managed identities, the developer needs to pass either the client ID,
|
|
14
|
+
* full resource identifier, or the object ID of the managed identity when creating ManagedIdentityApplication.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
static createManagedIdentityProvider(params: CredentialParams, userAssignedClientId?: string): EntraidCredentialsProvider;
|
|
18
|
+
/**
|
|
19
|
+
* This method is used to create a credentials provider for system-assigned managed identities.
|
|
20
|
+
* @param params
|
|
21
|
+
*/
|
|
22
|
+
static createForSystemAssignedManagedIdentity(params: CredentialParams): EntraidCredentialsProvider;
|
|
23
|
+
/**
|
|
24
|
+
* This method is used to create a credentials provider for user-assigned managed identities.
|
|
25
|
+
* It will include the client ID as the userAssignedClientId in the ManagedIdentityConfiguration.
|
|
26
|
+
* @param params
|
|
27
|
+
*/
|
|
28
|
+
static createForUserAssignedManagedIdentity(params: CredentialParams & {
|
|
29
|
+
userAssignedClientId: string;
|
|
30
|
+
}): EntraidCredentialsProvider;
|
|
31
|
+
/**
|
|
32
|
+
* This method is used to create a credentials provider for service principals using certificate.
|
|
33
|
+
* @param params
|
|
34
|
+
*/
|
|
35
|
+
static createForClientCredentialsWithCertificate(params: ClientCredentialsWithCertificateParams): EntraidCredentialsProvider;
|
|
36
|
+
/**
|
|
37
|
+
* This method is used to create a credentials provider for service principals using client secret.
|
|
38
|
+
* @param params
|
|
39
|
+
*/
|
|
40
|
+
static createForClientCredentials(params: ClientSecretCredentialsParams): EntraidCredentialsProvider;
|
|
41
|
+
/**
|
|
42
|
+
* This method is used to create a credentials provider for the Authorization Code Flow with PKCE.
|
|
43
|
+
* @param params
|
|
44
|
+
*/
|
|
45
|
+
static createForAuthorizationCodeWithPKCE(params: AuthCodePKCEParams): {
|
|
46
|
+
getPKCECodes: () => Promise<{
|
|
47
|
+
verifier: string;
|
|
48
|
+
challenge: string;
|
|
49
|
+
challengeMethod: string;
|
|
50
|
+
}>;
|
|
51
|
+
getAuthCodeUrl: (pkceCodes: {
|
|
52
|
+
challenge: string;
|
|
53
|
+
challengeMethod: string;
|
|
54
|
+
}) => Promise<string>;
|
|
55
|
+
createCredentialsProvider: (params: PKCEParams) => EntraidCredentialsProvider;
|
|
56
|
+
};
|
|
57
|
+
static getAuthority(config: AuthorityConfig): string;
|
|
58
|
+
}
|
|
59
|
+
export type AuthorityConfig = {
|
|
60
|
+
type: 'multi-tenant';
|
|
61
|
+
tenantId: string;
|
|
62
|
+
} | {
|
|
63
|
+
type: 'custom';
|
|
64
|
+
authorityUrl: string;
|
|
65
|
+
} | {
|
|
66
|
+
type: 'default';
|
|
67
|
+
};
|
|
68
|
+
export type PKCEParams = {
|
|
69
|
+
code: string;
|
|
70
|
+
verifier: string;
|
|
71
|
+
clientInfo?: string;
|
|
72
|
+
};
|
|
73
|
+
export type CredentialParams = {
|
|
74
|
+
clientId: string;
|
|
75
|
+
scopes?: string[];
|
|
76
|
+
authorityConfig?: AuthorityConfig;
|
|
77
|
+
tokenManagerConfig: TokenManagerConfig;
|
|
78
|
+
onReAuthenticationError?: (error: ReAuthenticationError) => void;
|
|
79
|
+
};
|
|
80
|
+
export type AuthCodePKCEParams = CredentialParams & {
|
|
81
|
+
redirectUri: string;
|
|
82
|
+
};
|
|
83
|
+
export type ClientSecretCredentialsParams = CredentialParams & {
|
|
84
|
+
clientSecret: string;
|
|
85
|
+
};
|
|
86
|
+
export type ClientCredentialsWithCertificateParams = CredentialParams & {
|
|
87
|
+
certificate: {
|
|
88
|
+
thumbprint: string;
|
|
89
|
+
privateKey: string;
|
|
90
|
+
x5c?: string;
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* The most important part of the RetryPolicy is the `isRetryable` function. This function is used to determine if a request should be retried based
|
|
95
|
+
* on the error returned from the identity provider. The default for is to retry on network errors only.
|
|
96
|
+
*/
|
|
97
|
+
export declare const DEFAULT_RETRY_POLICY: RetryPolicy;
|
|
98
|
+
export declare const DEFAULT_TOKEN_MANAGER_CONFIG: TokenManagerConfig;
|
|
99
|
+
/**
|
|
100
|
+
* This class is used to help with the Authorization Code Flow with PKCE.
|
|
101
|
+
* It provides methods to generate PKCE codes, get the authorization URL, and create the credential provider.
|
|
102
|
+
*/
|
|
103
|
+
export declare class AuthCodeFlowHelper {
|
|
104
|
+
readonly client: PublicClientApplication;
|
|
105
|
+
readonly scopes: string[];
|
|
106
|
+
readonly redirectUri: string;
|
|
107
|
+
private constructor();
|
|
108
|
+
getAuthCodeUrl(pkceCodes: {
|
|
109
|
+
challenge: string;
|
|
110
|
+
challengeMethod: string;
|
|
111
|
+
}): Promise<string>;
|
|
112
|
+
acquireTokenByCode(params: PKCEParams): Promise<AuthenticationResult>;
|
|
113
|
+
static generatePKCE(): Promise<{
|
|
114
|
+
verifier: string;
|
|
115
|
+
challenge: string;
|
|
116
|
+
challengeMethod: string;
|
|
117
|
+
}>;
|
|
118
|
+
static create(params: {
|
|
119
|
+
clientId: string;
|
|
120
|
+
redirectUri: string;
|
|
121
|
+
scopes?: string[];
|
|
122
|
+
authorityConfig?: AuthorityConfig;
|
|
123
|
+
}): AuthCodeFlowHelper;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=entra-id-credentials-provider-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entra-id-credentials-provider-factory.d.ts","sourceRoot":"","sources":["../../lib/entra-id-credentials-provider-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthCodeFlowHelper = exports.DEFAULT_TOKEN_MANAGER_CONFIG = exports.DEFAULT_RETRY_POLICY = exports.EntraIdCredentialsProviderFactory = void 0;
|
|
4
|
+
const msal_common_1 = require("@azure/msal-common");
|
|
5
|
+
const msal_node_1 = require("@azure/msal-node");
|
|
6
|
+
const authx_1 = require("@redis/client/dist/lib/authx");
|
|
7
|
+
const entraid_credentials_provider_1 = require("./entraid-credentials-provider");
|
|
8
|
+
const msal_identity_provider_1 = require("./msal-identity-provider");
|
|
9
|
+
/**
|
|
10
|
+
* This class is used to create credentials providers for different types of authentication flows.
|
|
11
|
+
*/
|
|
12
|
+
class EntraIdCredentialsProviderFactory {
|
|
13
|
+
/**
|
|
14
|
+
* This method is used to create a ManagedIdentityProvider for both system-assigned and user-assigned managed identities.
|
|
15
|
+
*
|
|
16
|
+
* @param params
|
|
17
|
+
* @param userAssignedClientId For user-assigned managed identities, the developer needs to pass either the client ID,
|
|
18
|
+
* full resource identifier, or the object ID of the managed identity when creating ManagedIdentityApplication.
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
static createManagedIdentityProvider(params, userAssignedClientId) {
|
|
22
|
+
const config = {
|
|
23
|
+
// For user-assigned identity, include the client ID
|
|
24
|
+
...(userAssignedClientId && {
|
|
25
|
+
managedIdentityIdParams: {
|
|
26
|
+
userAssignedClientId
|
|
27
|
+
}
|
|
28
|
+
}),
|
|
29
|
+
system: {
|
|
30
|
+
loggerOptions
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const client = new msal_node_1.ManagedIdentityApplication(config);
|
|
34
|
+
const idp = new msal_identity_provider_1.MSALIdentityProvider(() => client.acquireToken({
|
|
35
|
+
resource: params.scopes?.[0] ?? REDIS_SCOPE,
|
|
36
|
+
forceRefresh: true
|
|
37
|
+
}).then(x => x === null ? Promise.reject('Token is null') : x));
|
|
38
|
+
return new entraid_credentials_provider_1.EntraidCredentialsProvider(new authx_1.TokenManager(idp, params.tokenManagerConfig), idp, { onReAuthenticationError: params.onReAuthenticationError, credentialsMapper: OID_CREDENTIALS_MAPPER });
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* This method is used to create a credentials provider for system-assigned managed identities.
|
|
42
|
+
* @param params
|
|
43
|
+
*/
|
|
44
|
+
static createForSystemAssignedManagedIdentity(params) {
|
|
45
|
+
return this.createManagedIdentityProvider(params);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* This method is used to create a credentials provider for user-assigned managed identities.
|
|
49
|
+
* It will include the client ID as the userAssignedClientId in the ManagedIdentityConfiguration.
|
|
50
|
+
* @param params
|
|
51
|
+
*/
|
|
52
|
+
static createForUserAssignedManagedIdentity(params) {
|
|
53
|
+
return this.createManagedIdentityProvider(params, params.userAssignedClientId);
|
|
54
|
+
}
|
|
55
|
+
static #createForClientCredentials(authConfig, params) {
|
|
56
|
+
const config = {
|
|
57
|
+
auth: {
|
|
58
|
+
...authConfig,
|
|
59
|
+
authority: this.getAuthority(params.authorityConfig ?? { type: 'default' })
|
|
60
|
+
},
|
|
61
|
+
system: {
|
|
62
|
+
loggerOptions
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const client = new msal_node_1.ConfidentialClientApplication(config);
|
|
66
|
+
const idp = new msal_identity_provider_1.MSALIdentityProvider(() => client.acquireTokenByClientCredential({
|
|
67
|
+
skipCache: true,
|
|
68
|
+
scopes: params.scopes ?? [REDIS_SCOPE_DEFAULT]
|
|
69
|
+
}).then(x => x === null ? Promise.reject('Token is null') : x));
|
|
70
|
+
return new entraid_credentials_provider_1.EntraidCredentialsProvider(new authx_1.TokenManager(idp, params.tokenManagerConfig), idp, {
|
|
71
|
+
onReAuthenticationError: params.onReAuthenticationError,
|
|
72
|
+
credentialsMapper: OID_CREDENTIALS_MAPPER
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* This method is used to create a credentials provider for service principals using certificate.
|
|
77
|
+
* @param params
|
|
78
|
+
*/
|
|
79
|
+
static createForClientCredentialsWithCertificate(params) {
|
|
80
|
+
return this.#createForClientCredentials({
|
|
81
|
+
clientId: params.clientId,
|
|
82
|
+
clientCertificate: params.certificate
|
|
83
|
+
}, params);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* This method is used to create a credentials provider for service principals using client secret.
|
|
87
|
+
* @param params
|
|
88
|
+
*/
|
|
89
|
+
static createForClientCredentials(params) {
|
|
90
|
+
return this.#createForClientCredentials({
|
|
91
|
+
clientId: params.clientId,
|
|
92
|
+
clientSecret: params.clientSecret
|
|
93
|
+
}, params);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* This method is used to create a credentials provider for the Authorization Code Flow with PKCE.
|
|
97
|
+
* @param params
|
|
98
|
+
*/
|
|
99
|
+
static createForAuthorizationCodeWithPKCE(params) {
|
|
100
|
+
const requiredScopes = ['user.read', 'offline_access'];
|
|
101
|
+
const scopes = [...new Set([...(params.scopes || []), ...requiredScopes])];
|
|
102
|
+
const authFlow = AuthCodeFlowHelper.create({
|
|
103
|
+
clientId: params.clientId,
|
|
104
|
+
redirectUri: params.redirectUri,
|
|
105
|
+
scopes: scopes,
|
|
106
|
+
authorityConfig: params.authorityConfig
|
|
107
|
+
});
|
|
108
|
+
return {
|
|
109
|
+
getPKCECodes: AuthCodeFlowHelper.generatePKCE,
|
|
110
|
+
getAuthCodeUrl: (pkceCodes) => authFlow.getAuthCodeUrl(pkceCodes),
|
|
111
|
+
createCredentialsProvider: (pkceParams) => {
|
|
112
|
+
// This is used to store the initial credentials account to be used
|
|
113
|
+
// for silent token acquisition after the initial token acquisition.
|
|
114
|
+
let initialCredentialsAccount = null;
|
|
115
|
+
const idp = new msal_identity_provider_1.MSALIdentityProvider(async () => {
|
|
116
|
+
if (!initialCredentialsAccount) {
|
|
117
|
+
let authResult = await authFlow.acquireTokenByCode(pkceParams);
|
|
118
|
+
initialCredentialsAccount = authResult.account;
|
|
119
|
+
return authResult;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
return authFlow.client.acquireTokenSilent({
|
|
123
|
+
forceRefresh: true,
|
|
124
|
+
account: initialCredentialsAccount,
|
|
125
|
+
scopes
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
const tm = new authx_1.TokenManager(idp, params.tokenManagerConfig);
|
|
130
|
+
return new entraid_credentials_provider_1.EntraidCredentialsProvider(tm, idp, { onReAuthenticationError: params.onReAuthenticationError });
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
static getAuthority(config) {
|
|
135
|
+
switch (config.type) {
|
|
136
|
+
case 'multi-tenant':
|
|
137
|
+
return `https://login.microsoftonline.com/${config.tenantId}`;
|
|
138
|
+
case 'custom':
|
|
139
|
+
return config.authorityUrl;
|
|
140
|
+
case 'default':
|
|
141
|
+
return 'https://login.microsoftonline.com/common';
|
|
142
|
+
default:
|
|
143
|
+
throw new Error('Invalid authority configuration');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
exports.EntraIdCredentialsProviderFactory = EntraIdCredentialsProviderFactory;
|
|
148
|
+
const REDIS_SCOPE_DEFAULT = 'https://redis.azure.com/.default';
|
|
149
|
+
const REDIS_SCOPE = 'https://redis.azure.com';
|
|
150
|
+
const loggerOptions = {
|
|
151
|
+
loggerCallback(loglevel, message, containsPii) {
|
|
152
|
+
if (!containsPii)
|
|
153
|
+
console.log(message);
|
|
154
|
+
},
|
|
155
|
+
piiLoggingEnabled: false,
|
|
156
|
+
logLevel: msal_node_1.LogLevel.Error
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* The most important part of the RetryPolicy is the `isRetryable` function. This function is used to determine if a request should be retried based
|
|
160
|
+
* on the error returned from the identity provider. The default for is to retry on network errors only.
|
|
161
|
+
*/
|
|
162
|
+
exports.DEFAULT_RETRY_POLICY = {
|
|
163
|
+
// currently only retry on network errors
|
|
164
|
+
isRetryable: (error) => error instanceof msal_common_1.NetworkError,
|
|
165
|
+
maxAttempts: 10,
|
|
166
|
+
initialDelayMs: 100,
|
|
167
|
+
maxDelayMs: 100000,
|
|
168
|
+
backoffMultiplier: 2,
|
|
169
|
+
jitterPercentage: 0.1
|
|
170
|
+
};
|
|
171
|
+
exports.DEFAULT_TOKEN_MANAGER_CONFIG = {
|
|
172
|
+
retry: exports.DEFAULT_RETRY_POLICY,
|
|
173
|
+
expirationRefreshRatio: 0.7 // Refresh token when 70% of the token has expired
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* This class is used to help with the Authorization Code Flow with PKCE.
|
|
177
|
+
* It provides methods to generate PKCE codes, get the authorization URL, and create the credential provider.
|
|
178
|
+
*/
|
|
179
|
+
class AuthCodeFlowHelper {
|
|
180
|
+
client;
|
|
181
|
+
scopes;
|
|
182
|
+
redirectUri;
|
|
183
|
+
constructor(client, scopes, redirectUri) {
|
|
184
|
+
this.client = client;
|
|
185
|
+
this.scopes = scopes;
|
|
186
|
+
this.redirectUri = redirectUri;
|
|
187
|
+
}
|
|
188
|
+
async getAuthCodeUrl(pkceCodes) {
|
|
189
|
+
const authCodeUrlParameters = {
|
|
190
|
+
scopes: this.scopes,
|
|
191
|
+
redirectUri: this.redirectUri,
|
|
192
|
+
codeChallenge: pkceCodes.challenge,
|
|
193
|
+
codeChallengeMethod: pkceCodes.challengeMethod
|
|
194
|
+
};
|
|
195
|
+
return this.client.getAuthCodeUrl(authCodeUrlParameters);
|
|
196
|
+
}
|
|
197
|
+
async acquireTokenByCode(params) {
|
|
198
|
+
const tokenRequest = {
|
|
199
|
+
code: params.code,
|
|
200
|
+
scopes: this.scopes,
|
|
201
|
+
redirectUri: this.redirectUri,
|
|
202
|
+
codeVerifier: params.verifier,
|
|
203
|
+
clientInfo: params.clientInfo
|
|
204
|
+
};
|
|
205
|
+
return this.client.acquireTokenByCode(tokenRequest);
|
|
206
|
+
}
|
|
207
|
+
static async generatePKCE() {
|
|
208
|
+
const cryptoProvider = new msal_node_1.CryptoProvider();
|
|
209
|
+
const { verifier, challenge } = await cryptoProvider.generatePkceCodes();
|
|
210
|
+
return {
|
|
211
|
+
verifier,
|
|
212
|
+
challenge,
|
|
213
|
+
challengeMethod: 'S256'
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
static create(params) {
|
|
217
|
+
const config = {
|
|
218
|
+
auth: {
|
|
219
|
+
clientId: params.clientId,
|
|
220
|
+
authority: EntraIdCredentialsProviderFactory.getAuthority(params.authorityConfig ?? { type: 'default' })
|
|
221
|
+
},
|
|
222
|
+
system: {
|
|
223
|
+
loggerOptions
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
return new AuthCodeFlowHelper(new msal_node_1.PublicClientApplication(config), params.scopes ?? ['user.read'], params.redirectUri);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
exports.AuthCodeFlowHelper = AuthCodeFlowHelper;
|
|
230
|
+
const OID_CREDENTIALS_MAPPER = (token) => {
|
|
231
|
+
// Client credentials flow is app-only authentication (no user context),
|
|
232
|
+
// so only access token is provided without user-specific claims (uniqueId, idToken, ...)
|
|
233
|
+
// this means that we need to extract the oid from the access token manually
|
|
234
|
+
const accessToken = JSON.parse(Buffer.from(token.accessToken.split('.')[1], 'base64').toString());
|
|
235
|
+
return ({
|
|
236
|
+
username: accessToken.oid,
|
|
237
|
+
password: token.accessToken
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
//# sourceMappingURL=entra-id-credentials-provider-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entra-id-credentials-provider-factory.js","sourceRoot":"","sources":["../../lib/entra-id-credentials-provider-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AuthenticationResult } from '@azure/msal-common/node';
|
|
2
|
+
import { BasicAuth, StreamingCredentialsProvider, IdentityProvider, TokenManager, ReAuthenticationError, StreamingCredentialsListener, Disposable } from '@redis/client/dist/lib/authx';
|
|
3
|
+
/**
|
|
4
|
+
* A streaming credentials provider that uses the Entraid identity provider to provide credentials.
|
|
5
|
+
* Please use one of the factory functions in `entraid-credetfactories.ts` to create an instance of this class for the different
|
|
6
|
+
* type of authentication flows.
|
|
7
|
+
*/
|
|
8
|
+
export declare class EntraidCredentialsProvider implements StreamingCredentialsProvider {
|
|
9
|
+
#private;
|
|
10
|
+
readonly tokenManager: TokenManager<AuthenticationResult>;
|
|
11
|
+
readonly idp: IdentityProvider<AuthenticationResult>;
|
|
12
|
+
private readonly options;
|
|
13
|
+
readonly type = "streaming-credentials-provider";
|
|
14
|
+
constructor(tokenManager: TokenManager<AuthenticationResult>, idp: IdentityProvider<AuthenticationResult>, options?: {
|
|
15
|
+
onReAuthenticationError?: (error: ReAuthenticationError) => void;
|
|
16
|
+
credentialsMapper?: (token: AuthenticationResult) => BasicAuth;
|
|
17
|
+
onRetryableError?: (error: string) => void;
|
|
18
|
+
});
|
|
19
|
+
subscribe(listener: StreamingCredentialsListener<BasicAuth>): Promise<[BasicAuth, Disposable]>;
|
|
20
|
+
onReAuthenticationError: (error: ReAuthenticationError) => void;
|
|
21
|
+
hasActiveSubscriptions(): boolean;
|
|
22
|
+
getSubscriptionsCount(): number;
|
|
23
|
+
getTokenManager(): TokenManager<AuthenticationResult>;
|
|
24
|
+
getCurrentCredentials(): BasicAuth | null;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=entraid-credentials-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entraid-credentials-provider.d.ts","sourceRoot":"","sources":["../../lib/entraid-credentials-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EACL,SAAS,EAAE,4BAA4B,EAAE,gBAAgB,EAAE,YAAY,EACvE,qBAAqB,EAAE,4BAA4B,EAAmB,UAAU,EACjF,MAAM,8BAA8B,CAAC;AAEtC;;;;GAIG;AACH,qBAAa,0BAA2B,YAAW,4BAA4B;;aAe3D,YAAY,EAAE,YAAY,CAAC,oBAAoB,CAAC;aAChD,GAAG,EAAE,gBAAgB,CAAC,oBAAoB,CAAC;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO;IAhB1B,QAAQ,CAAC,IAAI,oCAAoC;gBAc/B,YAAY,EAAE,YAAY,CAAC,oBAAoB,CAAC,EAChD,GAAG,EAAE,gBAAgB,CAAC,oBAAoB,CAAC,EAC1C,OAAO,GAAE;QACxB,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;QACjE,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,SAAS,CAAC;QAC/D,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;KACvC;IAMF,SAAS,CACb,QAAQ,EAAE,4BAA4B,CAAC,SAAS,CAAC,GAChD,OAAO,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IA6BnC,uBAAuB,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IA6CzD,sBAAsB,IAAI,OAAO;IAIjC,qBAAqB,IAAI,MAAM;IAI/B,eAAe;IAIf,qBAAqB,IAAI,SAAS,GAAG,IAAI;CAKjD"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EntraidCredentialsProvider = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* A streaming credentials provider that uses the Entraid identity provider to provide credentials.
|
|
6
|
+
* Please use one of the factory functions in `entraid-credetfactories.ts` to create an instance of this class for the different
|
|
7
|
+
* type of authentication flows.
|
|
8
|
+
*/
|
|
9
|
+
class EntraidCredentialsProvider {
|
|
10
|
+
tokenManager;
|
|
11
|
+
idp;
|
|
12
|
+
options;
|
|
13
|
+
type = 'streaming-credentials-provider';
|
|
14
|
+
#listeners = new Set();
|
|
15
|
+
#tokenManagerDisposable = null;
|
|
16
|
+
#isStarting = false;
|
|
17
|
+
#pendingSubscribers = [];
|
|
18
|
+
constructor(tokenManager, idp, options = {}) {
|
|
19
|
+
this.tokenManager = tokenManager;
|
|
20
|
+
this.idp = idp;
|
|
21
|
+
this.options = options;
|
|
22
|
+
this.onReAuthenticationError = options.onReAuthenticationError ?? DEFAULT_ERROR_HANDLER;
|
|
23
|
+
this.#credentialsMapper = options.credentialsMapper ?? DEFAULT_CREDENTIALS_MAPPER;
|
|
24
|
+
}
|
|
25
|
+
async subscribe(listener) {
|
|
26
|
+
const currentToken = this.tokenManager.getCurrentToken();
|
|
27
|
+
if (currentToken) {
|
|
28
|
+
return [this.#credentialsMapper(currentToken.value), this.#createDisposable(listener)];
|
|
29
|
+
}
|
|
30
|
+
if (this.#isStarting) {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
this.#pendingSubscribers.push({ resolve, reject, pendingListener: listener });
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
this.#isStarting = true;
|
|
36
|
+
try {
|
|
37
|
+
const initialToken = await this.#startTokenManagerAndObtainInitialToken();
|
|
38
|
+
this.#pendingSubscribers.forEach(({ resolve, pendingListener }) => {
|
|
39
|
+
resolve([this.#credentialsMapper(initialToken.value), this.#createDisposable(pendingListener)]);
|
|
40
|
+
});
|
|
41
|
+
this.#pendingSubscribers = [];
|
|
42
|
+
return [this.#credentialsMapper(initialToken.value), this.#createDisposable(listener)];
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
this.#isStarting = false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
onReAuthenticationError;
|
|
49
|
+
#credentialsMapper;
|
|
50
|
+
#createTokenManagerListener(subscribers) {
|
|
51
|
+
return {
|
|
52
|
+
onError: (error) => {
|
|
53
|
+
if (!error.isRetryable) {
|
|
54
|
+
subscribers.forEach(listener => listener.onError(error));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.options.onRetryableError?.(error.message);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
onNext: (token) => {
|
|
61
|
+
const credentials = this.#credentialsMapper(token.value);
|
|
62
|
+
subscribers.forEach(listener => listener.onNext(credentials));
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
#createDisposable(listener) {
|
|
67
|
+
this.#listeners.add(listener);
|
|
68
|
+
return {
|
|
69
|
+
dispose: () => {
|
|
70
|
+
this.#listeners.delete(listener);
|
|
71
|
+
if (this.#listeners.size === 0 && this.#tokenManagerDisposable) {
|
|
72
|
+
this.#tokenManagerDisposable.dispose();
|
|
73
|
+
this.#tokenManagerDisposable = null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async #startTokenManagerAndObtainInitialToken() {
|
|
79
|
+
const initialResponse = await this.idp.requestToken();
|
|
80
|
+
const token = this.tokenManager.wrapAndSetCurrentToken(initialResponse.token, initialResponse.ttlMs);
|
|
81
|
+
this.#tokenManagerDisposable = this.tokenManager.start(this.#createTokenManagerListener(this.#listeners), this.tokenManager.calculateRefreshTime(token));
|
|
82
|
+
return token;
|
|
83
|
+
}
|
|
84
|
+
hasActiveSubscriptions() {
|
|
85
|
+
return this.#tokenManagerDisposable !== null && this.#listeners.size > 0;
|
|
86
|
+
}
|
|
87
|
+
getSubscriptionsCount() {
|
|
88
|
+
return this.#listeners.size;
|
|
89
|
+
}
|
|
90
|
+
getTokenManager() {
|
|
91
|
+
return this.tokenManager;
|
|
92
|
+
}
|
|
93
|
+
getCurrentCredentials() {
|
|
94
|
+
const currentToken = this.tokenManager.getCurrentToken();
|
|
95
|
+
return currentToken ? this.#credentialsMapper(currentToken.value) : null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.EntraidCredentialsProvider = EntraidCredentialsProvider;
|
|
99
|
+
const DEFAULT_CREDENTIALS_MAPPER = (token) => ({
|
|
100
|
+
username: token.uniqueId,
|
|
101
|
+
password: token.accessToken
|
|
102
|
+
});
|
|
103
|
+
const DEFAULT_ERROR_HANDLER = (error) => console.error('ReAuthenticationError', error);
|
|
104
|
+
//# sourceMappingURL=entraid-credentials-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entraid-credentials-provider.js","sourceRoot":"","sources":["../../lib/entraid-credentials-provider.ts"],"names":[],"mappings":";;;AAMA;;;;GAIG;AACH,MAAa,0BAA0B;IAenB;IACA;IACC;IAhBV,IAAI,GAAG,gCAAgC,CAAC;IAExC,UAAU,GAAiD,IAAI,GAAG,EAAE,CAAC;IAE9E,uBAAuB,GAAsB,IAAI,CAAC;IAClD,WAAW,GAAY,KAAK,CAAC;IAE7B,mBAAmB,GAId,EAAE,CAAC;IAER,YACkB,YAAgD,EAChD,GAA2C,EAC1C,UAIb,EAAE;QANU,iBAAY,GAAZ,YAAY,CAAoC;QAChD,QAAG,GAAH,GAAG,CAAwC;QAC1C,YAAO,GAAP,OAAO,CAIlB;QAEN,IAAI,CAAC,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,IAAI,qBAAqB,CAAC;QACxF,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,IAAI,0BAA0B,CAAC;IACpF,CAAC;IAED,KAAK,CAAC,SAAS,CACb,QAAiD;QAGjD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC;QAEzD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzF,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,CAAC;YAChF,CAAC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,uCAAuC,EAAE,CAAC;YAE1E,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE;gBAChE,OAAO,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAClG,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC;YAE9B,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzF,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,uBAAuB,CAAyC;IAEhE,kBAAkB,CAA6C;IAE/D,2BAA2B,CAAC,WAAyD;QACnF,OAAO;YACL,OAAO,EAAE,CAAC,KAAe,EAAQ,EAAE;gBACjC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;oBACvB,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC3D,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;YACD,MAAM,EAAE,CAAC,KAAsC,EAAQ,EAAE;gBACvD,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACzD,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;YAChE,CAAC;SACF,CAAC;IACJ,CAAC;IAED,iBAAiB,CAAC,QAAiD;QACjE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE9B,OAAO;YACL,OAAO,EAAE,GAAG,EAAE;gBACZ,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACjC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;oBAC/D,IAAI,CAAC,uBAAuB,CAAC,OAAO,EAAE,CAAC;oBACvC,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;gBACtC,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,uCAAuC;QAC3C,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,sBAAsB,CAAC,eAAe,CAAC,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC;QAErG,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CACpD,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,UAAU,CAAC,EACjD,IAAI,CAAC,YAAY,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAC9C,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,sBAAsB;QAC3B,OAAO,IAAI,CAAC,uBAAuB,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,CAAC;IAC3E,CAAC;IAEM,qBAAqB;QAC1B,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;IAC9B,CAAC;IAEM,eAAe;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAEM,qBAAqB;QAC1B,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC;QACzD,OAAO,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,CAAC;CAEF;AAxHD,gEAwHC;AAED,MAAM,0BAA0B,GAAG,CAAC,KAA2B,EAAa,EAAE,CAAC,CAAC;IAC9E,QAAQ,EAAE,KAAK,CAAC,QAAQ;IACxB,QAAQ,EAAE,KAAK,CAAC,WAAW;CAC5B,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,KAA4B,EAAE,EAAE,CAC7D,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,yCAAyC,CAAC;AACxD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./entra-id-credentials-provider-factory"), exports);
|
|
18
|
+
__exportStar(require("./entraid-credentials-provider"), exports);
|
|
19
|
+
__exportStar(require("./msal-identity-provider"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0EAAwD;AACxD,iEAA+C;AAC/C,2DAAyC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AuthenticationResult } from '@azure/msal-node';
|
|
2
|
+
import { IdentityProvider, TokenResponse } from '@redis/client/dist/lib/authx';
|
|
3
|
+
export declare class MSALIdentityProvider implements IdentityProvider<AuthenticationResult> {
|
|
4
|
+
private readonly getToken;
|
|
5
|
+
constructor(getToken: () => Promise<AuthenticationResult>);
|
|
6
|
+
requestToken(): Promise<TokenResponse<AuthenticationResult>>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=msal-identity-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msal-identity-provider.d.ts","sourceRoot":"","sources":["../../lib/msal-identity-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE/E,qBAAa,oBAAqB,YAAW,gBAAgB,CAAC,oBAAoB,CAAC;IACjF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;gBAEnD,QAAQ,EAAE,MAAM,OAAO,CAAC,oBAAoB,CAAC;IAInD,YAAY,IAAI,OAAO,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC;CAgBnE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MSALIdentityProvider = void 0;
|
|
4
|
+
class MSALIdentityProvider {
|
|
5
|
+
getToken;
|
|
6
|
+
constructor(getToken) {
|
|
7
|
+
this.getToken = getToken;
|
|
8
|
+
}
|
|
9
|
+
async requestToken() {
|
|
10
|
+
try {
|
|
11
|
+
const result = await this.getToken();
|
|
12
|
+
if (!result?.accessToken || !result?.expiresOn) {
|
|
13
|
+
throw new Error('Invalid token response');
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
token: result,
|
|
17
|
+
ttlMs: result.expiresOn.getTime() - Date.now()
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.MSALIdentityProvider = MSALIdentityProvider;
|
|
26
|
+
//# sourceMappingURL=msal-identity-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msal-identity-provider.js","sourceRoot":"","sources":["../../lib/msal-identity-provider.ts"],"names":[],"mappings":";;;AAKA,MAAa,oBAAoB;IACd,QAAQ,CAAsC;IAE/D,YAAY,QAA6C;QACvD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YAErC,IAAI,CAAC,MAAM,EAAE,WAAW,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC;gBAC/C,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAC5C,CAAC;YACD,OAAO;gBACL,KAAK,EAAE,MAAM;gBACb,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE;aAC/C,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CAEF;AAvBD,oDAuBC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { StreamingCredentialsProvider } from '@redis/client/dist/lib/authx';
|
|
2
|
+
import TestUtils from '@redis/test-utils';
|
|
3
|
+
export declare const testUtils: TestUtils;
|
|
4
|
+
export declare const GLOBAL: {
|
|
5
|
+
CLUSTERS: {
|
|
6
|
+
PASSWORD_WITH_REPLICAS: {
|
|
7
|
+
serverArguments: string[];
|
|
8
|
+
numberOfMasters: number;
|
|
9
|
+
numberOfReplicas: number;
|
|
10
|
+
clusterConfiguration: {
|
|
11
|
+
defaults: {
|
|
12
|
+
credentialsProvider: StreamingCredentialsProvider;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=test-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../lib/test-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,4BAA4B,EAA+B,MAAM,8BAA8B,CAAC;AAC3H,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAG1C,eAAO,MAAM,SAAS,WAIpB,CAAC;AAgCH,eAAO,MAAM,MAAM;;;;;;;;;;;;;CAIlB,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GLOBAL = exports.testUtils = void 0;
|
|
7
|
+
const authx_1 = require("@redis/client/dist/lib/authx");
|
|
8
|
+
const test_utils_1 = __importDefault(require("@redis/test-utils"));
|
|
9
|
+
const entraid_credentials_provider_1 = require("./entraid-credentials-provider");
|
|
10
|
+
exports.testUtils = new test_utils_1.default({
|
|
11
|
+
dockerImageName: 'redis/redis-stack',
|
|
12
|
+
dockerImageVersionArgument: 'redis-version',
|
|
13
|
+
defaultDockerVersion: '7.4.0-v1'
|
|
14
|
+
});
|
|
15
|
+
const DEBUG_MODE_ARGS = exports.testUtils.isVersionGreaterThan([7]) ?
|
|
16
|
+
['--enable-debug-command', 'yes'] :
|
|
17
|
+
[];
|
|
18
|
+
const idp = {
|
|
19
|
+
requestToken() {
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
return Promise.resolve({
|
|
22
|
+
ttlMs: 100000,
|
|
23
|
+
token: {
|
|
24
|
+
accessToken: 'password'
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const tokenManager = new authx_1.TokenManager(idp, { expirationRefreshRatio: 0.8 });
|
|
30
|
+
const entraIdCredentialsProvider = new entraid_credentials_provider_1.EntraidCredentialsProvider(tokenManager, idp);
|
|
31
|
+
const PASSWORD_WITH_REPLICAS = {
|
|
32
|
+
serverArguments: ['--requirepass', 'password', ...DEBUG_MODE_ARGS],
|
|
33
|
+
numberOfMasters: 2,
|
|
34
|
+
numberOfReplicas: 1,
|
|
35
|
+
clusterConfiguration: {
|
|
36
|
+
defaults: {
|
|
37
|
+
credentialsProvider: entraIdCredentialsProvider
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
exports.GLOBAL = {
|
|
42
|
+
CLUSTERS: {
|
|
43
|
+
PASSWORD_WITH_REPLICAS
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=test-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../../lib/test-utils.ts"],"names":[],"mappings":";;;;;;AACA,wDAA2H;AAC3H,mEAA0C;AAC1C,iFAA4E;AAE/D,QAAA,SAAS,GAAG,IAAI,oBAAS,CAAC;IACrC,eAAe,EAAE,mBAAmB;IACpC,0BAA0B,EAAE,eAAe;IAC3C,oBAAoB,EAAE,UAAU;CACjC,CAAC,CAAC;AAEH,MAAM,eAAe,GAAG,iBAAS,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC,CAAC;IACnC,EAAE,CAAC;AAEL,MAAM,GAAG,GAA2C;IAClD,YAAY;QACV,aAAa;QACb,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,KAAK,EAAE,MAAM;YACb,KAAK,EAAE;gBACL,WAAW,EAAE,UAAU;aACxB;SACF,CAAC,CAAA;IACJ,CAAC;CACF,CAAA;AAED,MAAM,YAAY,GAAG,IAAI,oBAAY,CAAuB,GAAG,EAAE,EAAE,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC;AAClG,MAAM,0BAA0B,GAAiC,IAAI,yDAA0B,CAAC,YAAY,EAAE,GAAG,CAAC,CAAA;AAElH,MAAM,sBAAsB,GAAG;IAC7B,eAAe,EAAE,CAAC,eAAe,EAAE,UAAU,EAAE,GAAG,eAAe,CAAC;IAClE,eAAe,EAAE,CAAC;IAClB,gBAAgB,EAAE,CAAC;IACnB,oBAAoB,EAAE;QACpB,QAAQ,EAAE;YACR,mBAAmB,EAAE,0BAA0B;SAChD;KACF;CACF,CAAA;AAEY,QAAA,MAAM,GAAG;IACpB,QAAQ,EAAE;QACR,sBAAsB;KACvB;CACF,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@redis/entraid",
|
|
3
|
+
"version": "5.0.0-next.6",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist/",
|
|
9
|
+
"!dist/tsconfig.tsbuildinfo"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"clean": "rimraf dist",
|
|
13
|
+
"build": "npm run clean && tsc",
|
|
14
|
+
"start:auth-pkce": "tsx --tsconfig tsconfig.samples.json ./samples/auth-code-pkce/index.ts",
|
|
15
|
+
"test-integration": "mocha -r tsx --tsconfig tsconfig.integration-tests.json './integration-tests/**/*.spec.ts'",
|
|
16
|
+
"test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@azure/msal-node": "^2.16.1"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@redis/client": "^5.0.0-next.6"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/express": "^4.17.21",
|
|
26
|
+
"@types/express-session": "^1.18.0",
|
|
27
|
+
"@types/node": "^22.9.0",
|
|
28
|
+
"dotenv": "^16.3.1",
|
|
29
|
+
"express": "^4.21.1",
|
|
30
|
+
"express-session": "^1.18.1",
|
|
31
|
+
"@redis/test-utils": "*"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">= 18"
|
|
35
|
+
},
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git://github.com/redis/node-redis.git"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/redis/node-redis/issues"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/redis/node-redis/tree/master/packages/entraid",
|
|
44
|
+
"keywords": [
|
|
45
|
+
"redis"
|
|
46
|
+
]
|
|
47
|
+
}
|