@stackwright-pro/auth 0.2.0-alpha.1 → 0.2.0-alpha.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/index.d.mts CHANGED
@@ -1,372 +1,9 @@
1
- import { z } from 'zod';
1
+ import { AuthProvider as AuthProvider$1, PKIConfig, AuthContext as AuthContext$1, AuthUser, AuthSession, OIDCConfig, RBACConfig, ComponentAuthConfig } from '@stackwright-pro/types';
2
+ export { AuthConfig, AuthSession, AuthUser, ComponentAuthConfig, OIDCConfig, PKIConfig, RBACConfig, authConfigSchema, authSessionSchema, authUserSchema, componentAuthSchema, oidcConfigSchema, pkiConfigSchema, rbacConfigSchema } from '@stackwright-pro/types';
2
3
  import { X509Certificate } from '@peculiar/x509';
3
4
  import * as React from 'react';
4
5
  import React__default, { ReactNode, ReactElement } from 'react';
5
6
 
6
- /**
7
- * HMAC Header Signing for PKI Gateway Authentication
8
- *
9
- * Prevents header forgery attacks by HMAC-signing certificate headers
10
- * at the gateway (nginx/HAProxy) and verifying them in the application.
11
- *
12
- * Without this, any request that bypasses the reverse proxy can forge
13
- * x-client-cert-* headers and impersonate any certificate identity.
14
- *
15
- * Canonical string format:
16
- * {prefix}dn:{value}\n{prefix}issuer:{value}\n...{prefix}fingerprint:{value}\n_ts:{timestamp}
17
- *
18
- * @see packages/auth/test/integration/docker/nginx/nginx.conf for gateway setup
19
- */
20
- interface HeaderSigningConfig {
21
- /** Shared HMAC secret between gateway and application */
22
- secret: string;
23
- /** Header name for the signature (default: 'x-client-cert-sig') */
24
- signatureHeader?: string;
25
- /** Header name for the timestamp (default: 'x-client-cert-sig-ts') */
26
- timestampHeader?: string;
27
- /** Maximum age of signature in seconds (default: 30) */
28
- maxAge?: number;
29
- /** Custom header prefix if not using default 'x-client-cert-' */
30
- headerPrefix?: string;
31
- }
32
- /**
33
- * Signs certificate headers with HMAC-SHA256.
34
- *
35
- * Used by the gateway (nginx via lua-resty-hmac, or a sidecar) to sign
36
- * headers before forwarding to the application.
37
- *
38
- * @returns Object with `signature` and `timestamp` to set as additional headers
39
- */
40
- declare function signCertHeaders(headers: Record<string, string>, config: HeaderSigningConfig): {
41
- signature: string;
42
- timestamp: string;
43
- };
44
- /**
45
- * Verifies the HMAC signature on certificate headers.
46
- *
47
- * Call this in the auth provider BEFORE trusting any cert header values.
48
- * Returns `{ valid: true }` only when the signature is both correct and fresh.
49
- */
50
- declare function verifyCertHeaders(headers: Record<string, string | undefined>, config: HeaderSigningConfig): {
51
- valid: boolean;
52
- reason?: string;
53
- };
54
-
55
- /**
56
- * Core Type Definitions for Stackwright Auth
57
- *
58
- * These types define the foundational contract for authentication.
59
- * All auth functionality builds on these interfaces.
60
- */
61
-
62
- /**
63
- * Authenticated user representation
64
- * Normalized across PKI and OIDC providers
65
- */
66
- interface AuthUser {
67
- id: string;
68
- email?: string;
69
- name?: string;
70
- roles: string[];
71
- permissions?: string[];
72
- metadata?: Record<string, any>;
73
- }
74
- /**
75
- * Session representation (in-memory).
76
- * Contains user info and expiration details.
77
- *
78
- * Note: `refreshToken` is the **plaintext** value used by application code.
79
- * When serialised to a JWT (via SessionManager.signSession), the refresh
80
- * token is encrypted with JWE (A256GCM) and stored as `encRefreshToken`.
81
- * It is never written to the JWT in plaintext.
82
- *
83
- * Legacy JWTs containing a plain `refreshToken` claim are accepted for
84
- * backward compatibility but trigger a deprecation warning.
85
- */
86
- interface AuthSession {
87
- user: AuthUser;
88
- expiresAt: number;
89
- issuedAt: number;
90
- refreshToken?: string;
91
- /** Unique session identifier (JWT ID) for revocation support */
92
- jti?: string;
93
- }
94
- /**
95
- * PKI-specific configuration
96
- * Supports DoD CAC, PIV cards, and custom PKI deployments
97
- */
98
- interface PKIConfig {
99
- type: 'pki';
100
- profile: 'dod_cac' | 'piv' | 'custom';
101
- source: 'gateway_headers' | 'direct_tls';
102
- headerPrefix?: string;
103
- verifiedHeader?: string;
104
- requiredValue?: string;
105
- caChain?: string;
106
- requiredOU?: string[];
107
- allowedIssuers?: string[];
108
- /** HMAC signing config for verifying gateway-provided cert headers */
109
- headerSigning?: HeaderSigningConfig;
110
- }
111
- /**
112
- * OIDC configuration
113
- * Supports major providers + custom OIDC implementations
114
- */
115
- interface OIDCConfig {
116
- type: 'oidc';
117
- provider: 'cognito' | 'azure_ad' | 'authentik' | 'keycloak' | 'okta' | 'auth0' | 'custom';
118
- discoveryUrl: string;
119
- clientId: string;
120
- clientSecret: string;
121
- redirectUri?: string;
122
- claimsMapping?: {
123
- user_id?: string;
124
- email?: string;
125
- name?: string;
126
- roles?: string;
127
- };
128
- quirks?: {
129
- skipIssuerCheck?: boolean;
130
- useRefreshTokenRotation?: boolean;
131
- };
132
- /** When true (default), authenticate() throws if expectedState is missing from context. */
133
- requireState?: boolean;
134
- }
135
- /**
136
- * Union of all auth configurations
137
- * Discriminated by 'type' field for type safety
138
- */
139
- type AuthConfig = PKIConfig | OIDCConfig;
140
- /**
141
- * Component-level auth configuration (from YAML)
142
- * Defines access requirements for individual components
143
- */
144
- interface ComponentAuthConfig {
145
- required_roles?: string[];
146
- required_permissions?: string[];
147
- fallback?: 'hide' | 'placeholder' | 'message';
148
- fallback_message?: string;
149
- }
150
- /**
151
- * Role-based access control configuration
152
- * Defines roles, permissions, and route protection
153
- */
154
- interface RBACConfig {
155
- roles: Array<{
156
- name: string;
157
- permissions?: string[];
158
- }>;
159
- protected_routes?: Array<{
160
- path: string;
161
- roles: string[];
162
- }>;
163
- public_routes?: string[];
164
- }
165
- /**
166
- * Auth context passed to providers during authentication
167
- */
168
- interface AuthContext$1 {
169
- headers?: Record<string, string>;
170
- query?: Record<string, string>;
171
- cookies?: Record<string, string>;
172
- /** Expected state for OIDC CSRF validation (stored server-side before redirect) */
173
- expectedState?: string;
174
- /** Expected nonce for OIDC ID token replay protection */
175
- expectedNonce?: string;
176
- /** PKCE code verifier for OIDC authorization code exchange */
177
- codeVerifier?: string;
178
- }
179
- /**
180
- * Provider interface that both PKI and OIDC implementations must satisfy
181
- * Ensures consistent behavior across auth strategies
182
- */
183
- interface AuthProvider$1 {
184
- authenticate(context: AuthContext$1): Promise<AuthUser | null>;
185
- validate(session: AuthSession): Promise<boolean>;
186
- refresh?(session: AuthSession): Promise<AuthSession | null>;
187
- }
188
-
189
- /**
190
- * Zod Schemas for Runtime Validation
191
- *
192
- * These schemas provide runtime validation for all auth-related data structures.
193
- * They mirror the TypeScript types but enforce validation at runtime.
194
- */
195
-
196
- /**
197
- * PKI Configuration Schema
198
- * Validates PKI auth config with sensible defaults
199
- */
200
- declare const pkiConfigSchema: z.ZodObject<{
201
- type: z.ZodLiteral<"pki">;
202
- profile: z.ZodEnum<{
203
- dod_cac: "dod_cac";
204
- piv: "piv";
205
- custom: "custom";
206
- }>;
207
- source: z.ZodEnum<{
208
- gateway_headers: "gateway_headers";
209
- direct_tls: "direct_tls";
210
- }>;
211
- headerPrefix: z.ZodDefault<z.ZodOptional<z.ZodString>>;
212
- verifiedHeader: z.ZodDefault<z.ZodOptional<z.ZodString>>;
213
- requiredValue: z.ZodDefault<z.ZodOptional<z.ZodString>>;
214
- caChain: z.ZodOptional<z.ZodString>;
215
- requiredOU: z.ZodOptional<z.ZodArray<z.ZodString>>;
216
- allowedIssuers: z.ZodOptional<z.ZodArray<z.ZodString>>;
217
- headerSigning: z.ZodOptional<z.ZodObject<{
218
- secret: z.ZodString;
219
- signatureHeader: z.ZodOptional<z.ZodString>;
220
- timestampHeader: z.ZodOptional<z.ZodString>;
221
- maxAge: z.ZodOptional<z.ZodNumber>;
222
- headerPrefix: z.ZodOptional<z.ZodString>;
223
- }, z.core.$strip>>;
224
- }, z.core.$strip>;
225
- /**
226
- * OIDC Configuration Schema
227
- * Validates OIDC provider config including claims mapping and quirks
228
- */
229
- declare const oidcConfigSchema: z.ZodObject<{
230
- type: z.ZodLiteral<"oidc">;
231
- provider: z.ZodEnum<{
232
- custom: "custom";
233
- cognito: "cognito";
234
- azure_ad: "azure_ad";
235
- authentik: "authentik";
236
- keycloak: "keycloak";
237
- okta: "okta";
238
- auth0: "auth0";
239
- }>;
240
- discoveryUrl: z.ZodString;
241
- clientId: z.ZodString;
242
- clientSecret: z.ZodString;
243
- redirectUri: z.ZodOptional<z.ZodString>;
244
- claimsMapping: z.ZodOptional<z.ZodObject<{
245
- user_id: z.ZodOptional<z.ZodString>;
246
- email: z.ZodOptional<z.ZodString>;
247
- name: z.ZodOptional<z.ZodString>;
248
- roles: z.ZodOptional<z.ZodString>;
249
- }, z.core.$strip>>;
250
- quirks: z.ZodOptional<z.ZodObject<{
251
- skipIssuerCheck: z.ZodOptional<z.ZodBoolean>;
252
- useRefreshTokenRotation: z.ZodOptional<z.ZodBoolean>;
253
- }, z.core.$strip>>;
254
- requireState: z.ZodOptional<z.ZodBoolean>;
255
- }, z.core.$strip>;
256
- /**
257
- * Discriminated Union Schema
258
- * Auto-discriminates based on 'type' field for type-safe validation
259
- */
260
- declare const authConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
261
- type: z.ZodLiteral<"pki">;
262
- profile: z.ZodEnum<{
263
- dod_cac: "dod_cac";
264
- piv: "piv";
265
- custom: "custom";
266
- }>;
267
- source: z.ZodEnum<{
268
- gateway_headers: "gateway_headers";
269
- direct_tls: "direct_tls";
270
- }>;
271
- headerPrefix: z.ZodDefault<z.ZodOptional<z.ZodString>>;
272
- verifiedHeader: z.ZodDefault<z.ZodOptional<z.ZodString>>;
273
- requiredValue: z.ZodDefault<z.ZodOptional<z.ZodString>>;
274
- caChain: z.ZodOptional<z.ZodString>;
275
- requiredOU: z.ZodOptional<z.ZodArray<z.ZodString>>;
276
- allowedIssuers: z.ZodOptional<z.ZodArray<z.ZodString>>;
277
- headerSigning: z.ZodOptional<z.ZodObject<{
278
- secret: z.ZodString;
279
- signatureHeader: z.ZodOptional<z.ZodString>;
280
- timestampHeader: z.ZodOptional<z.ZodString>;
281
- maxAge: z.ZodOptional<z.ZodNumber>;
282
- headerPrefix: z.ZodOptional<z.ZodString>;
283
- }, z.core.$strip>>;
284
- }, z.core.$strip>, z.ZodObject<{
285
- type: z.ZodLiteral<"oidc">;
286
- provider: z.ZodEnum<{
287
- custom: "custom";
288
- cognito: "cognito";
289
- azure_ad: "azure_ad";
290
- authentik: "authentik";
291
- keycloak: "keycloak";
292
- okta: "okta";
293
- auth0: "auth0";
294
- }>;
295
- discoveryUrl: z.ZodString;
296
- clientId: z.ZodString;
297
- clientSecret: z.ZodString;
298
- redirectUri: z.ZodOptional<z.ZodString>;
299
- claimsMapping: z.ZodOptional<z.ZodObject<{
300
- user_id: z.ZodOptional<z.ZodString>;
301
- email: z.ZodOptional<z.ZodString>;
302
- name: z.ZodOptional<z.ZodString>;
303
- roles: z.ZodOptional<z.ZodString>;
304
- }, z.core.$strip>>;
305
- quirks: z.ZodOptional<z.ZodObject<{
306
- skipIssuerCheck: z.ZodOptional<z.ZodBoolean>;
307
- useRefreshTokenRotation: z.ZodOptional<z.ZodBoolean>;
308
- }, z.core.$strip>>;
309
- requireState: z.ZodOptional<z.ZodBoolean>;
310
- }, z.core.$strip>], "type">;
311
- /**
312
- * Component Auth Configuration Schema
313
- * Validates YAML-based component auth requirements
314
- */
315
- declare const componentAuthSchema: z.ZodOptional<z.ZodObject<{
316
- required_roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
317
- required_permissions: z.ZodOptional<z.ZodArray<z.ZodString>>;
318
- fallback: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
319
- hide: "hide";
320
- placeholder: "placeholder";
321
- message: "message";
322
- }>>>;
323
- fallback_message: z.ZodOptional<z.ZodString>;
324
- }, z.core.$strip>>;
325
- /**
326
- * RBAC Configuration Schema
327
- * Validates role definitions, permissions, and route protection rules
328
- */
329
- declare const rbacConfigSchema: z.ZodObject<{
330
- roles: z.ZodArray<z.ZodObject<{
331
- name: z.ZodString;
332
- permissions: z.ZodOptional<z.ZodArray<z.ZodString>>;
333
- }, z.core.$strip>>;
334
- protected_routes: z.ZodOptional<z.ZodArray<z.ZodObject<{
335
- path: z.ZodString;
336
- roles: z.ZodArray<z.ZodString>;
337
- }, z.core.$strip>>>;
338
- public_routes: z.ZodOptional<z.ZodArray<z.ZodString>>;
339
- }, z.core.$strip>;
340
- /**
341
- * Auth User Schema
342
- * Validates user objects with required id and roles
343
- */
344
- declare const authUserSchema: z.ZodObject<{
345
- id: z.ZodString;
346
- email: z.ZodOptional<z.ZodString>;
347
- name: z.ZodOptional<z.ZodString>;
348
- roles: z.ZodArray<z.ZodString>;
349
- permissions: z.ZodOptional<z.ZodArray<z.ZodString>>;
350
- metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
351
- }, z.core.$strip>;
352
- /**
353
- * Auth Session Schema
354
- * Validates session structure including expiration timestamps
355
- */
356
- declare const authSessionSchema: z.ZodObject<{
357
- user: z.ZodObject<{
358
- id: z.ZodString;
359
- email: z.ZodOptional<z.ZodString>;
360
- name: z.ZodOptional<z.ZodString>;
361
- roles: z.ZodArray<z.ZodString>;
362
- permissions: z.ZodOptional<z.ZodArray<z.ZodString>>;
363
- metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
364
- }, z.core.$strip>;
365
- expiresAt: z.ZodNumber;
366
- issuedAt: z.ZodNumber;
367
- refreshToken: z.ZodOptional<z.ZodString>;
368
- }, z.core.$strip>;
369
-
370
7
  /**
371
8
  * Authentication Audit Logging
372
9
  *
@@ -1217,6 +854,55 @@ interface AuthProviderProps {
1217
854
  */
1218
855
  declare function AuthProvider({ user, session, rbacConfig, isLoading, children, }: AuthProviderProps): ReactElement;
1219
856
 
857
+ /**
858
+ * HMAC Header Signing for PKI Gateway Authentication
859
+ *
860
+ * Prevents header forgery attacks by HMAC-signing certificate headers
861
+ * at the gateway (nginx/HAProxy) and verifying them in the application.
862
+ *
863
+ * Without this, any request that bypasses the reverse proxy can forge
864
+ * x-client-cert-* headers and impersonate any certificate identity.
865
+ *
866
+ * Canonical string format:
867
+ * {prefix}dn:{value}\n{prefix}issuer:{value}\n...{prefix}fingerprint:{value}\n_ts:{timestamp}
868
+ *
869
+ * @see packages/auth/test/integration/docker/nginx/nginx.conf for gateway setup
870
+ */
871
+ interface HeaderSigningConfig {
872
+ /** Shared HMAC secret between gateway and application */
873
+ secret: string;
874
+ /** Header name for the signature (default: 'x-client-cert-sig') */
875
+ signatureHeader?: string;
876
+ /** Header name for the timestamp (default: 'x-client-cert-sig-ts') */
877
+ timestampHeader?: string;
878
+ /** Maximum age of signature in seconds (default: 30) */
879
+ maxAge?: number;
880
+ /** Custom header prefix if not using default 'x-client-cert-' */
881
+ headerPrefix?: string;
882
+ }
883
+ /**
884
+ * Signs certificate headers with HMAC-SHA256.
885
+ *
886
+ * Used by the gateway (nginx via lua-resty-hmac, or a sidecar) to sign
887
+ * headers before forwarding to the application.
888
+ *
889
+ * @returns Object with `signature` and `timestamp` to set as additional headers
890
+ */
891
+ declare function signCertHeaders(headers: Record<string, string>, config: HeaderSigningConfig): {
892
+ signature: string;
893
+ timestamp: string;
894
+ };
895
+ /**
896
+ * Verifies the HMAC signature on certificate headers.
897
+ *
898
+ * Call this in the auth provider BEFORE trusting any cert header values.
899
+ * Returns `{ valid: true }` only when the signature is both correct and fresh.
900
+ */
901
+ declare function verifyCertHeaders(headers: Record<string, string | undefined>, config: HeaderSigningConfig): {
902
+ valid: boolean;
903
+ reason?: string;
904
+ };
905
+
1220
906
  /**
1221
907
  * DoD CAC Profile Configuration
1222
908
  *
@@ -1364,4 +1050,4 @@ declare function hasAuthConfig(item: any): item is {
1364
1050
  auth: ComponentAuthConfig;
1365
1051
  };
1366
1052
 
1367
- export { type AuditEvent, AuditEventType, type AuditLogger, type AuthConfig, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthSession, type AuthUser, type AuthorizationRequest, type BuildAuthorizationUrlOptions, type ComponentAuthConfig, type ComponentProps, CompositeAuditLogger, ConsoleAuditLogger, type CookieOptions, DOD_CAC_PROFILE, type HeaderSigningConfig, InMemoryRevocationStore, KeycloakAdapter, NoopAuditLogger, type OIDCConfig, type OIDCMetadata, OIDCProvider, type PKIConfig, PKIProvider, type ParsedCertificate, type RBACConfig, RBACEngine, type RevocationStore, SessionManager, type SessionManagerConfig, type TokenSet, authConfigSchema, authSessionSchema, authUserSchema, buildAuthorizationUrl, clearCookie, componentAuthSchema, createAuditEvent, createDoDCACConfig, createDoDCACDevConfig, decryptToken, deriveEncryptionKey, discoverOIDC, encryptToken, exchangeCodeForTokens, extractEDIPI, generateCodeChallenge, generateCodeVerifier, generateJti, generateNonce, generateState, getAuthDecorator, hasAuthConfig, maybeWrapWithAuth, oidcConfigSchema, parseCertFromHeaders, parseCertificate, parseCookies, pkiConfigSchema, rbacConfigSchema, refreshAccessToken, registerAuthDecorator, serializeCookie, signCertHeaders, useAuth, useRequireAuth, validateDoDCAC, validateIdToken, verifyCertHeaders, verifyState, withAuth, withAuthFallback };
1053
+ export { type AuditEvent, AuditEventType, type AuditLogger, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthorizationRequest, type BuildAuthorizationUrlOptions, type ComponentProps, CompositeAuditLogger, ConsoleAuditLogger, type CookieOptions, DOD_CAC_PROFILE, type HeaderSigningConfig, InMemoryRevocationStore, KeycloakAdapter, NoopAuditLogger, type OIDCMetadata, OIDCProvider, PKIProvider, type ParsedCertificate, RBACEngine, type RevocationStore, SessionManager, type SessionManagerConfig, type TokenSet, buildAuthorizationUrl, clearCookie, createAuditEvent, createDoDCACConfig, createDoDCACDevConfig, decryptToken, deriveEncryptionKey, discoverOIDC, encryptToken, exchangeCodeForTokens, extractEDIPI, generateCodeChallenge, generateCodeVerifier, generateJti, generateNonce, generateState, getAuthDecorator, hasAuthConfig, maybeWrapWithAuth, parseCertFromHeaders, parseCertificate, parseCookies, refreshAccessToken, registerAuthDecorator, serializeCookie, signCertHeaders, useAuth, useRequireAuth, validateDoDCAC, validateIdToken, verifyCertHeaders, verifyState, withAuth, withAuthFallback };