@enterprisestandard/react 0.0.5-beta.20260114.3 → 0.0.5-beta.20260115.2
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/dist/group-store.js +127 -0
- package/dist/iam.js +680 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +144 -3687
- package/dist/session-store.js +105 -0
- package/dist/sso-server.d.ts +13 -0
- package/dist/sso-server.d.ts.map +1 -0
- package/dist/sso-server.js +46 -0
- package/dist/sso.d.ts +1 -1
- package/dist/sso.d.ts.map +1 -1
- package/dist/sso.js +820 -0
- package/dist/tenant-server.js +6 -0
- package/dist/tenant.d.ts.map +1 -1
- package/dist/tenant.js +324 -0
- package/dist/types/base-user.js +1 -0
- package/dist/types/enterprise-user.js +1 -0
- package/dist/types/oidc-schema.js +328 -0
- package/dist/types/scim-schema.js +519 -0
- package/dist/types/standard-schema.js +1 -0
- package/dist/types/user.js +1 -0
- package/dist/types/workload-schema.js +208 -0
- package/dist/ui/sign-in-loading.js +8 -0
- package/dist/ui/signed-in.js +8 -0
- package/dist/ui/signed-out.js +8 -0
- package/dist/ui/sso-provider.js +275 -0
- package/dist/user-store.js +114 -0
- package/dist/utils.js +23 -0
- package/dist/vault.js +22 -0
- package/dist/workload-server.d.ts +7 -6
- package/dist/workload-server.d.ts.map +1 -1
- package/dist/workload-server.js +167 -0
- package/dist/workload-token-store.js +95 -0
- package/dist/workload.d.ts.map +1 -1
- package/dist/workload.js +691 -0
- package/package.json +1 -1
- package/dist/index.js.map +0 -29
- package/dist/server.d.ts +0 -9
- package/dist/server.d.ts.map +0 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session management for tracking user sessions and enabling backchannel logout.
|
|
3
|
+
*
|
|
4
|
+
* Session stores are optional - the package works with JWT cookies alone.
|
|
5
|
+
* Sessions are only required for backchannel logout functionality.
|
|
6
|
+
*
|
|
7
|
+
* ## Session Validation Strategies
|
|
8
|
+
*
|
|
9
|
+
* When using a session store, you can configure when sessions are validated:
|
|
10
|
+
*
|
|
11
|
+
* ### 'always' (default)
|
|
12
|
+
* Validates session on every authenticated request.
|
|
13
|
+
* - **Security**: Maximum - immediate session revocation
|
|
14
|
+
* - **Performance**: InMemory ~0.00005ms, Redis ~1-2ms per request
|
|
15
|
+
* - **Backchannel Logout**: Takes effect immediately
|
|
16
|
+
* - **Use when**: Security is paramount, using InMemory or Redis backend
|
|
17
|
+
*
|
|
18
|
+
* ### 'refresh-only'
|
|
19
|
+
* Validates session only during token refresh (typically every 5-15 minutes).
|
|
20
|
+
* - **Security**: Good - 5-15 minute revocation window
|
|
21
|
+
* - **Performance**: 99% reduction in session lookups
|
|
22
|
+
* - **Backchannel Logout**: Takes effect within token TTL (5-15 min)
|
|
23
|
+
* - **Use when**: Performance is critical AND delayed revocation is acceptable
|
|
24
|
+
* - **WARNING**: Compromised sessions remain valid until next refresh
|
|
25
|
+
*
|
|
26
|
+
* ### 'disabled'
|
|
27
|
+
* Never validates sessions against the store.
|
|
28
|
+
* - **Security**: None - backchannel logout doesn't work
|
|
29
|
+
* - **Performance**: No overhead
|
|
30
|
+
* - **Use when**: Cookie-only mode without session store
|
|
31
|
+
* - **WARNING**: Do not use with session_store configured
|
|
32
|
+
*
|
|
33
|
+
* ## Performance Characteristics
|
|
34
|
+
*
|
|
35
|
+
* | Backend | Lookup Time | Impact on Request | Recommendation |
|
|
36
|
+
* |--------------|-------------|-------------------|------------------------|
|
|
37
|
+
* | InMemory | <0.00005ms | Negligible | Use 'always' |
|
|
38
|
+
* | Redis | 1-2ms | 2-4% increase | Use 'always' or test |
|
|
39
|
+
* | Database | 5-20ms | 10-40% increase | Use Redis cache layer |
|
|
40
|
+
*
|
|
41
|
+
* ## Example Usage
|
|
42
|
+
*
|
|
43
|
+
* ```typescript
|
|
44
|
+
* import { sso, InMemorySessionStore } from '@enterprisestandard/react/server';
|
|
45
|
+
*
|
|
46
|
+
* // Maximum security (default)
|
|
47
|
+
* const secure = sso({
|
|
48
|
+
* // ... other config
|
|
49
|
+
* session_store: new InMemorySessionStore(),
|
|
50
|
+
* session_validation: 'always', // Immediate revocation
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* // High performance
|
|
54
|
+
* const fast = sso({
|
|
55
|
+
* // ... other config
|
|
56
|
+
* session_store: new InMemorySessionStore(),
|
|
57
|
+
* session_validation: {
|
|
58
|
+
* strategy: 'refresh-only' // 5-15 min revocation delay
|
|
59
|
+
* }
|
|
60
|
+
* });
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
/**
|
|
64
|
+
* In-memory session store implementation using Maps.
|
|
65
|
+
*
|
|
66
|
+
* Suitable for:
|
|
67
|
+
* - Development and testing
|
|
68
|
+
* - Single-server deployments
|
|
69
|
+
* - Applications without high availability requirements
|
|
70
|
+
*
|
|
71
|
+
* NOT suitable for:
|
|
72
|
+
* - Multi-server deployments (sessions not shared)
|
|
73
|
+
* - High availability scenarios (sessions lost on restart)
|
|
74
|
+
* - Production applications with distributed architecture
|
|
75
|
+
*
|
|
76
|
+
* For production, implement SessionStore with Redis or a database.
|
|
77
|
+
*
|
|
78
|
+
* @template TExtended - Type-safe custom data that consumers can add to sessions
|
|
79
|
+
*/
|
|
80
|
+
export class InMemorySessionStore {
|
|
81
|
+
constructor() {
|
|
82
|
+
this.sessions = new Map();
|
|
83
|
+
}
|
|
84
|
+
async create(session) {
|
|
85
|
+
if (this.sessions.has(session.sid)) {
|
|
86
|
+
throw new Error(`Session with sid ${session.sid} already exists`);
|
|
87
|
+
}
|
|
88
|
+
this.sessions.set(session.sid, session);
|
|
89
|
+
}
|
|
90
|
+
async get(sid) {
|
|
91
|
+
return this.sessions.get(sid) ?? null;
|
|
92
|
+
}
|
|
93
|
+
async update(sid, data) {
|
|
94
|
+
const session = this.sessions.get(sid);
|
|
95
|
+
if (!session) {
|
|
96
|
+
throw new Error(`Session with sid ${sid} not found`);
|
|
97
|
+
}
|
|
98
|
+
// Merge the update data
|
|
99
|
+
const updated = { ...session, ...data };
|
|
100
|
+
this.sessions.set(sid, updated);
|
|
101
|
+
}
|
|
102
|
+
async delete(sid) {
|
|
103
|
+
this.sessions.delete(sid);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EnterpriseStandard } from '.';
|
|
2
|
+
import type { LoginConfig } from './sso';
|
|
3
|
+
/**
|
|
4
|
+
* Helper gets the user from the Request using the supplied EnterpriseStandard or the default instance
|
|
5
|
+
*/
|
|
6
|
+
export declare function getUser(request: Request, es?: EnterpriseStandard): Promise<import(".").User | undefined>;
|
|
7
|
+
export declare function getRequiredUser(request: Request, es?: EnterpriseStandard): Promise<import(".").User>;
|
|
8
|
+
export declare function initiateLogin(config: LoginConfig, es?: EnterpriseStandard): Promise<Response>;
|
|
9
|
+
export declare function callback(request: Request, es?: EnterpriseStandard): Promise<Response>;
|
|
10
|
+
export declare function handler(request: Request, es?: EnterpriseStandard): Promise<Response>;
|
|
11
|
+
export * from './tenant-server';
|
|
12
|
+
export * from './workload-server';
|
|
13
|
+
//# sourceMappingURL=sso-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sso-server.d.ts","sourceRoot":"","sources":["../src/sso-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,GAAG,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAezC;;GAEG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,kBAAkB,yCAEtE;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,kBAAkB,6BAI9E;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,kBAAkB,qBAI/E;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,kBAAkB,qBAIvE;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,kBAAkB,qBAItE;AAGD,cAAc,iBAAiB,CAAC;AAEhC,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getES } from './utils';
|
|
2
|
+
/**
|
|
3
|
+
* Returns a 503 response indicating that the SSO is unavailable
|
|
4
|
+
*/
|
|
5
|
+
function unavailable(error) {
|
|
6
|
+
error = error ?? 'SSO Unavailable';
|
|
7
|
+
new Response(JSON.stringify({ error }), {
|
|
8
|
+
status: 503,
|
|
9
|
+
statusText: error,
|
|
10
|
+
headers: { 'Content-Type': 'application/json' },
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Helper gets the user from the Request using the supplied EnterpriseStandard or the default instance
|
|
15
|
+
*/
|
|
16
|
+
export async function getUser(request, es) {
|
|
17
|
+
return getES(es)?.sso.getUser(request);
|
|
18
|
+
}
|
|
19
|
+
export async function getRequiredUser(request, es) {
|
|
20
|
+
const sso = getES(es)?.sso;
|
|
21
|
+
if (!sso)
|
|
22
|
+
throw unavailable();
|
|
23
|
+
return sso.getRequiredUser(request);
|
|
24
|
+
}
|
|
25
|
+
export async function initiateLogin(config, es) {
|
|
26
|
+
const sso = getES(es)?.sso;
|
|
27
|
+
if (!sso)
|
|
28
|
+
throw unavailable();
|
|
29
|
+
return sso.initiateLogin(config);
|
|
30
|
+
}
|
|
31
|
+
export async function callback(request, es) {
|
|
32
|
+
const sso = getES(es)?.sso;
|
|
33
|
+
if (!sso)
|
|
34
|
+
throw unavailable();
|
|
35
|
+
return sso.callbackHandler(request);
|
|
36
|
+
}
|
|
37
|
+
export async function handler(request, es) {
|
|
38
|
+
es = getES(es);
|
|
39
|
+
if (!es)
|
|
40
|
+
throw unavailable();
|
|
41
|
+
return es.sso.handler(request, es);
|
|
42
|
+
}
|
|
43
|
+
// Tenant server helpers
|
|
44
|
+
export * from './tenant-server';
|
|
45
|
+
// Workload server helpers
|
|
46
|
+
export * from './workload-server';
|
package/dist/sso.d.ts
CHANGED
|
@@ -97,7 +97,7 @@ export type SSO<TSessionData = {}, TUserData = {}> = SSOConfigWithDefaults<TSess
|
|
|
97
97
|
initiateLogin: (config: LoginConfig, requestUrl?: string) => Promise<Response>;
|
|
98
98
|
logout: (request: Request, config?: LoginConfig) => Promise<Response>;
|
|
99
99
|
callbackHandler: (request: Request) => Promise<Response>;
|
|
100
|
-
handler: (request: Request) => Promise<Response>;
|
|
100
|
+
handler: (request: Request, es?: EnterpriseStandard) => Promise<Response>;
|
|
101
101
|
};
|
|
102
102
|
export declare function sso<TSessionData = {}, TUserData = {}>(config?: SSOConfig<TSessionData, TUserData>): SSO<TSessionData, TUserData>;
|
|
103
103
|
export {};
|
package/dist/sso.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sso.d.ts","sourceRoot":"","sources":["../src/sso.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,GAAG,CAAC;AAC5C,OAAO,KAAK,EAAW,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE5F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAc,SAAS,EAAE,MAAM,cAAc,CAAC;AAG1D,MAAM,MAAM,SAAS,CAAC,YAAY,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE,IAAI;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IACrC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,aAAa,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;IAC3C;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE;QACX,cAAc,CAAC,EAAE,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;QAC/D,aAAa,CAAC,EAAE,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QACzD,aAAa,CAAC,EAAE,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;KAC1D,CAAC;IACF;;;OAGG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC;;;;;;OAMG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC,CAAC;AA0BF,KAAK,qBAAqB,CAAC,YAAY,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE,IAAI,SAAS,
|
|
1
|
+
{"version":3,"file":"sso.d.ts","sourceRoot":"","sources":["../src/sso.ts"],"names":[],"mappings":"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"}
|