@venturekit/auth 0.0.0-dev.20260506001012 → 0.0.0-dev.20260506003129

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.
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Admin-side Cognito user management.
3
+ *
4
+ * Wraps the four `Admin*` flows every consumer ends up needing once
5
+ * they have an ops console: invite a non-self-signup user, propagate
6
+ * profile / role attribute changes, and toggle a user's enabled
7
+ * status. Every helper is idempotent in the sense that re-issuing
8
+ * the same command on an already-converged user is a no-op (or
9
+ * fails with a stable error code mapped to a 4xx).
10
+ *
11
+ * The executing IAM principal needs the matching `cognito-idp:Admin*`
12
+ * permissions in production. `cognito-local` accepts admin commands
13
+ * unauthenticated.
14
+ */
15
+ import type { AuthServerConfig } from './config.js';
16
+ export interface AdminInviteUserInput {
17
+ /** Username — typically the user's email for email-keyed pools. */
18
+ username: string;
19
+ /**
20
+ * Permanent-on-first-login temporary password. The user lands in
21
+ * `FORCE_CHANGE_PASSWORD` until they complete the
22
+ * `NEW_PASSWORD_REQUIRED` challenge on their first sign-in.
23
+ */
24
+ temporaryPassword: string;
25
+ /** Standard OIDC `name` attribute. */
26
+ name?: string;
27
+ /**
28
+ * Standard attributes (`given_name`, `family_name`, `phone_number`,
29
+ * …). Sent verbatim. The helper always pre-sets `email` and
30
+ * `email_verified=true` so the first sign-in skips the
31
+ * verification challenge.
32
+ */
33
+ attributes?: Record<string, string>;
34
+ /**
35
+ * Custom attributes — keyed without the `custom:` prefix; the
36
+ * helper prepends it.
37
+ */
38
+ customAttributes?: Record<string, string>;
39
+ /**
40
+ * Whether Cognito should send its built-in invite email. Default
41
+ * `false` — most consumers ship their own branded welcome flow
42
+ * and don't want the AWS-templated message.
43
+ */
44
+ sendCognitoInviteEmail?: boolean;
45
+ }
46
+ export interface AdminInviteUserResult {
47
+ userSub: string;
48
+ }
49
+ /**
50
+ * Provision a user from the admin console.
51
+ *
52
+ * The user lands in Cognito's `FORCE_CHANGE_PASSWORD` state on
53
+ * purpose: their first /auth/login attempt returns a
54
+ * `NEW_PASSWORD_REQUIRED` challenge, the consumer's UI completes
55
+ * it, and the temporary password is unusable thereafter. There's
56
+ * no `AdminSetUserPassword(Permanent=true)` call here.
57
+ */
58
+ export declare function adminInviteUser(input: AdminInviteUserInput, config?: AuthServerConfig): Promise<AdminInviteUserResult>;
59
+ export interface AdminUpdateAttributesInput {
60
+ /** Username (= email for typical pools). */
61
+ username: string;
62
+ /** Standard attributes to set. */
63
+ attributes?: Record<string, string>;
64
+ /** Custom attributes (without `custom:` prefix — added automatically). */
65
+ customAttributes?: Record<string, string>;
66
+ }
67
+ /**
68
+ * Update arbitrary attributes on a Cognito user.
69
+ *
70
+ * cognito-local insists on `email` being present in the same
71
+ * payload whenever `email_verified` is set. To keep prod and local
72
+ * on the same path, the caller can include the user's email in
73
+ * `attributes` whenever `email_verified` is being toggled — the
74
+ * helper does NOT auto-fetch it.
75
+ */
76
+ export declare function adminUpdateUserAttributes(input: AdminUpdateAttributesInput, config?: AuthServerConfig): Promise<void>;
77
+ /**
78
+ * Disable a Cognito user. JWT verification keeps working until the
79
+ * existing tokens expire — Cognito doesn't revoke previously issued
80
+ * sessions. Pair with {@link revokeRefreshToken} per active session
81
+ * if immediate cut-off matters.
82
+ */
83
+ export declare function adminDisableUser(input: {
84
+ username: string;
85
+ }, config?: AuthServerConfig): Promise<void>;
86
+ /** Re-enable a previously disabled Cognito user. */
87
+ export declare function adminEnableUser(input: {
88
+ username: string;
89
+ }, config?: AuthServerConfig): Promise<void>;
90
+ //# sourceMappingURL=admin-users.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-users.d.ts","sourceRoot":"","sources":["../../src/server/admin-users.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAKpD,MAAM,WAAW,oBAAoB;IACnC,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,oBAAoB,EAC3B,MAAM,GAAE,gBAAyC,GAChD,OAAO,CAAC,qBAAqB,CAAC,CA8BhC;AAED,MAAM,WAAW,0BAA0B;IACzC,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,0BAA0B,EACjC,MAAM,GAAE,gBAAyC,GAChD,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC3B,MAAM,GAAE,gBAAyC,GAChD,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,oDAAoD;AACpD,wBAAsB,eAAe,CACnC,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC3B,MAAM,GAAE,gBAAyC,GAChD,OAAO,CAAC,IAAI,CAAC,CAYf"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Admin-side Cognito user management.
3
+ *
4
+ * Wraps the four `Admin*` flows every consumer ends up needing once
5
+ * they have an ops console: invite a non-self-signup user, propagate
6
+ * profile / role attribute changes, and toggle a user's enabled
7
+ * status. Every helper is idempotent in the sense that re-issuing
8
+ * the same command on an already-converged user is a no-op (or
9
+ * fails with a stable error code mapped to a 4xx).
10
+ *
11
+ * The executing IAM principal needs the matching `cognito-idp:Admin*`
12
+ * permissions in production. `cognito-local` accepts admin commands
13
+ * unauthenticated.
14
+ */
15
+ import { AdminCreateUserCommand, AdminDisableUserCommand, AdminEnableUserCommand, AdminUpdateUserAttributesCommand, } from '@aws-sdk/client-cognito-identity-provider';
16
+ import { loadAuthServerConfig } from './config.js';
17
+ import { getCognitoClient } from './cognito-client.js';
18
+ import { AuthError, mapProviderError } from './errors.js';
19
+ /**
20
+ * Provision a user from the admin console.
21
+ *
22
+ * The user lands in Cognito's `FORCE_CHANGE_PASSWORD` state on
23
+ * purpose: their first /auth/login attempt returns a
24
+ * `NEW_PASSWORD_REQUIRED` challenge, the consumer's UI completes
25
+ * it, and the temporary password is unusable thereafter. There's
26
+ * no `AdminSetUserPassword(Permanent=true)` call here.
27
+ */
28
+ export async function adminInviteUser(input, config = loadAuthServerConfig()) {
29
+ const client = getCognitoClient(config.region, config.endpoint);
30
+ const username = input.username.toLowerCase();
31
+ const userAttributes = buildUserAttributes(username, input);
32
+ try {
33
+ const res = await client.send(new AdminCreateUserCommand({
34
+ UserPoolId: config.userPoolId,
35
+ Username: username,
36
+ MessageAction: input.sendCognitoInviteEmail ? undefined : 'SUPPRESS',
37
+ TemporaryPassword: input.temporaryPassword,
38
+ UserAttributes: userAttributes,
39
+ }));
40
+ const sub = res.User?.Attributes?.find((a) => a.Name === 'sub')?.Value;
41
+ if (!sub) {
42
+ throw new AuthError('admin_invite_failed', 'Identity provider returned no sub from AdminCreateUser', 500);
43
+ }
44
+ return { userSub: sub };
45
+ }
46
+ catch (err) {
47
+ if (err instanceof AuthError)
48
+ throw err;
49
+ throw mapProviderError(err, 'admin_invite_failed');
50
+ }
51
+ }
52
+ /**
53
+ * Update arbitrary attributes on a Cognito user.
54
+ *
55
+ * cognito-local insists on `email` being present in the same
56
+ * payload whenever `email_verified` is set. To keep prod and local
57
+ * on the same path, the caller can include the user's email in
58
+ * `attributes` whenever `email_verified` is being toggled — the
59
+ * helper does NOT auto-fetch it.
60
+ */
61
+ export async function adminUpdateUserAttributes(input, config = loadAuthServerConfig()) {
62
+ const client = getCognitoClient(config.region, config.endpoint);
63
+ const username = input.username.toLowerCase();
64
+ const userAttributes = [];
65
+ for (const [name, value] of Object.entries(input.attributes ?? {})) {
66
+ userAttributes.push({ Name: name, Value: value });
67
+ }
68
+ for (const [name, value] of Object.entries(input.customAttributes ?? {})) {
69
+ userAttributes.push({ Name: `custom:${name}`, Value: value });
70
+ }
71
+ if (userAttributes.length === 0)
72
+ return;
73
+ try {
74
+ await client.send(new AdminUpdateUserAttributesCommand({
75
+ UserPoolId: config.userPoolId,
76
+ Username: username,
77
+ UserAttributes: userAttributes,
78
+ }));
79
+ }
80
+ catch (err) {
81
+ throw mapProviderError(err, 'admin_attribute_update_failed');
82
+ }
83
+ }
84
+ /**
85
+ * Disable a Cognito user. JWT verification keeps working until the
86
+ * existing tokens expire — Cognito doesn't revoke previously issued
87
+ * sessions. Pair with {@link revokeRefreshToken} per active session
88
+ * if immediate cut-off matters.
89
+ */
90
+ export async function adminDisableUser(input, config = loadAuthServerConfig()) {
91
+ const client = getCognitoClient(config.region, config.endpoint);
92
+ try {
93
+ await client.send(new AdminDisableUserCommand({
94
+ UserPoolId: config.userPoolId,
95
+ Username: input.username.toLowerCase(),
96
+ }));
97
+ }
98
+ catch (err) {
99
+ throw mapProviderError(err, 'admin_disable_failed');
100
+ }
101
+ }
102
+ /** Re-enable a previously disabled Cognito user. */
103
+ export async function adminEnableUser(input, config = loadAuthServerConfig()) {
104
+ const client = getCognitoClient(config.region, config.endpoint);
105
+ try {
106
+ await client.send(new AdminEnableUserCommand({
107
+ UserPoolId: config.userPoolId,
108
+ Username: input.username.toLowerCase(),
109
+ }));
110
+ }
111
+ catch (err) {
112
+ throw mapProviderError(err, 'admin_enable_failed');
113
+ }
114
+ }
115
+ function buildUserAttributes(username, input) {
116
+ const out = [
117
+ { Name: 'email', Value: username },
118
+ { Name: 'email_verified', Value: 'true' },
119
+ ];
120
+ if (input.name !== undefined)
121
+ out.push({ Name: 'name', Value: input.name });
122
+ for (const [name, value] of Object.entries(input.attributes ?? {})) {
123
+ if (name === 'email' || name === 'email_verified')
124
+ continue;
125
+ out.push({ Name: name, Value: value });
126
+ }
127
+ for (const [name, value] of Object.entries(input.customAttributes ?? {})) {
128
+ out.push({ Name: `custom:${name}`, Value: value });
129
+ }
130
+ return out;
131
+ }
132
+ //# sourceMappingURL=admin-users.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-users.js","sourceRoot":"","sources":["../../src/server/admin-users.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Cognito challenge flows that surface intermediate state to the
3
+ * caller instead of throwing.
4
+ *
5
+ * The default `signInWithPassword` raises `auth_challenge_required`
6
+ * for any `ChallengeName` Cognito returns — fine for service-style
7
+ * authentication where the token triplet is the only acceptable
8
+ * outcome. {@link signInWithPasswordOrChallenge} relaxes that for
9
+ * apps that need to drive the **first-login `NEW_PASSWORD_REQUIRED`
10
+ * flow**: an admin invites a user with `AdminCreateUser`, the user
11
+ * lands in `FORCE_CHANGE_PASSWORD`, and their first sign-in attempt
12
+ * must echo a fresh permanent password back through
13
+ * `RespondToAuthChallenge` before tokens are issued.
14
+ *
15
+ * Other challenges (MFA, software-token setup, …) still throw — V0
16
+ * Cognito User Pools created by VentureKit's CDK stack ship with MFA
17
+ * disabled, so any chained challenge is a config drift the operator
18
+ * should investigate rather than silently route around.
19
+ */
20
+ import type { AuthServerConfig } from './config.js';
21
+ import { type SignInResult } from './tokens.js';
22
+ import type { SignInCredentials } from './sign-in.js';
23
+ /**
24
+ * Challenge envelope surfaced to the caller when Cognito withholds
25
+ * tokens until the user completes a step. The discriminator stays
26
+ * narrow on purpose — additional challenge names should be added
27
+ * one-by-one as the consumer's UI grows to handle them.
28
+ */
29
+ export interface SignInChallenge {
30
+ challenge: 'NEW_PASSWORD_REQUIRED';
31
+ /** Opaque session token to pass back to {@link respondToNewPasswordChallenge}. */
32
+ session: string;
33
+ /** Echo of the username that triggered the challenge. */
34
+ username: string;
35
+ }
36
+ export type SignInOrChallengeResult = {
37
+ kind: 'tokens';
38
+ tokens: SignInResult;
39
+ } | {
40
+ kind: 'challenge';
41
+ challenge: SignInChallenge;
42
+ };
43
+ /**
44
+ * Sign-in path that surfaces the `NEW_PASSWORD_REQUIRED` challenge
45
+ * Cognito raises for admin-invited users on their first attempt.
46
+ *
47
+ * Returns either the issued tokens (happy path) or a structured
48
+ * challenge envelope the calling route can forward to the SPA so the
49
+ * user can pick a permanent password through
50
+ * {@link respondToNewPasswordChallenge}.
51
+ *
52
+ * Other challenges (MFA, etc.) still surface as
53
+ * `auth_challenge_required` errors — see file header for rationale.
54
+ */
55
+ export declare function signInWithPasswordOrChallenge(credentials: SignInCredentials, config?: AuthServerConfig): Promise<SignInOrChallengeResult>;
56
+ export interface RespondNewPasswordInput {
57
+ /** Username (= email for typical pools). */
58
+ username: string;
59
+ /** New permanent password. Must satisfy the User Pool's password policy. */
60
+ newPassword: string;
61
+ /** Opaque session token returned by `signInWithPasswordOrChallenge`. */
62
+ session: string;
63
+ }
64
+ /**
65
+ * Complete a `NEW_PASSWORD_REQUIRED` challenge with a permanent
66
+ * password. Returns the issued tokens — the user is now logged in
67
+ * and the temporary password is dead.
68
+ *
69
+ * A chained challenge in the response (e.g. MFA) surfaces as a
70
+ * `unsupported_challenge` (HTTP 400) AuthError so an operator can
71
+ * fix the misconfiguration rather than silently lose the user.
72
+ */
73
+ export declare function respondToNewPasswordChallenge(input: RespondNewPasswordInput, config?: AuthServerConfig): Promise<SignInResult>;
74
+ //# sourceMappingURL=challenge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../../src/server/challenge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,uBAAuB,CAAC;IACnC,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,uBAAuB,GAC/B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,wBAAsB,6BAA6B,CACjD,WAAW,EAAE,iBAAiB,EAC9B,MAAM,GAAE,gBAAyC,GAChD,OAAO,CAAC,uBAAuB,CAAC,CA0ClC;AAED,MAAM,WAAW,uBAAuB;IACtC,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,6BAA6B,CACjD,KAAK,EAAE,uBAAuB,EAC9B,MAAM,GAAE,gBAAyC,GAChD,OAAO,CAAC,YAAY,CAAC,CA2BvB"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Cognito challenge flows that surface intermediate state to the
3
+ * caller instead of throwing.
4
+ *
5
+ * The default `signInWithPassword` raises `auth_challenge_required`
6
+ * for any `ChallengeName` Cognito returns — fine for service-style
7
+ * authentication where the token triplet is the only acceptable
8
+ * outcome. {@link signInWithPasswordOrChallenge} relaxes that for
9
+ * apps that need to drive the **first-login `NEW_PASSWORD_REQUIRED`
10
+ * flow**: an admin invites a user with `AdminCreateUser`, the user
11
+ * lands in `FORCE_CHANGE_PASSWORD`, and their first sign-in attempt
12
+ * must echo a fresh permanent password back through
13
+ * `RespondToAuthChallenge` before tokens are issued.
14
+ *
15
+ * Other challenges (MFA, software-token setup, …) still throw — V0
16
+ * Cognito User Pools created by VentureKit's CDK stack ship with MFA
17
+ * disabled, so any chained challenge is a config drift the operator
18
+ * should investigate rather than silently route around.
19
+ */
20
+ import { ChallengeNameType, InitiateAuthCommand, RespondToAuthChallengeCommand, } from '@aws-sdk/client-cognito-identity-provider';
21
+ import { loadAuthServerConfig } from './config.js';
22
+ import { getCognitoClient } from './cognito-client.js';
23
+ import { AuthError, mapProviderError } from './errors.js';
24
+ import { extractSignInTokens } from './tokens.js';
25
+ /**
26
+ * Sign-in path that surfaces the `NEW_PASSWORD_REQUIRED` challenge
27
+ * Cognito raises for admin-invited users on their first attempt.
28
+ *
29
+ * Returns either the issued tokens (happy path) or a structured
30
+ * challenge envelope the calling route can forward to the SPA so the
31
+ * user can pick a permanent password through
32
+ * {@link respondToNewPasswordChallenge}.
33
+ *
34
+ * Other challenges (MFA, etc.) still surface as
35
+ * `auth_challenge_required` errors — see file header for rationale.
36
+ */
37
+ export async function signInWithPasswordOrChallenge(credentials, config = loadAuthServerConfig()) {
38
+ const client = getCognitoClient(config.region, config.endpoint);
39
+ const username = credentials.email.toLowerCase();
40
+ try {
41
+ const res = await client.send(new InitiateAuthCommand({
42
+ ClientId: config.appClientId,
43
+ AuthFlow: 'USER_PASSWORD_AUTH',
44
+ AuthParameters: {
45
+ USERNAME: username,
46
+ PASSWORD: credentials.password,
47
+ },
48
+ }));
49
+ if (res.ChallengeName === ChallengeNameType.NEW_PASSWORD_REQUIRED &&
50
+ res.Session) {
51
+ return {
52
+ kind: 'challenge',
53
+ challenge: {
54
+ challenge: 'NEW_PASSWORD_REQUIRED',
55
+ session: res.Session,
56
+ username,
57
+ },
58
+ };
59
+ }
60
+ if (res.ChallengeName) {
61
+ throw new AuthError('auth_challenge_required', `Identity provider requires challenge: ${res.ChallengeName}.`, 400);
62
+ }
63
+ return {
64
+ kind: 'tokens',
65
+ tokens: extractSignInTokens(res.AuthenticationResult),
66
+ };
67
+ }
68
+ catch (err) {
69
+ if (err instanceof AuthError)
70
+ throw err;
71
+ throw mapProviderError(err, 'auth_failed');
72
+ }
73
+ }
74
+ /**
75
+ * Complete a `NEW_PASSWORD_REQUIRED` challenge with a permanent
76
+ * password. Returns the issued tokens — the user is now logged in
77
+ * and the temporary password is dead.
78
+ *
79
+ * A chained challenge in the response (e.g. MFA) surfaces as a
80
+ * `unsupported_challenge` (HTTP 400) AuthError so an operator can
81
+ * fix the misconfiguration rather than silently lose the user.
82
+ */
83
+ export async function respondToNewPasswordChallenge(input, config = loadAuthServerConfig()) {
84
+ const client = getCognitoClient(config.region, config.endpoint);
85
+ const username = input.username.toLowerCase();
86
+ try {
87
+ const res = await client.send(new RespondToAuthChallengeCommand({
88
+ ClientId: config.appClientId,
89
+ ChallengeName: ChallengeNameType.NEW_PASSWORD_REQUIRED,
90
+ Session: input.session,
91
+ ChallengeResponses: {
92
+ USERNAME: username,
93
+ NEW_PASSWORD: input.newPassword,
94
+ },
95
+ }));
96
+ if (res.ChallengeName) {
97
+ throw new AuthError('unsupported_challenge', `Unsupported chained challenge: ${res.ChallengeName}`, 400);
98
+ }
99
+ return extractSignInTokens(res.AuthenticationResult);
100
+ }
101
+ catch (err) {
102
+ if (err instanceof AuthError)
103
+ throw err;
104
+ throw mapProviderError(err, 'sign_in_challenge_failed');
105
+ }
106
+ }
107
+ //# sourceMappingURL=challenge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"challenge.js","sourceRoot":"","sources":["../../src/server/challenge.ts"],"names":[],"mappings":"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"}
@@ -26,6 +26,12 @@ export type { AuthServerConfig } from './config.js';
26
26
  export { loadAuthServerConfig } from './config.js';
27
27
  export type { SignInCredentials, SignInResult } from './sign-in.js';
28
28
  export { signInWithPassword } from './sign-in.js';
29
+ export type { SignInChallenge, SignInOrChallengeResult, RespondNewPasswordInput, } from './challenge.js';
30
+ export { signInWithPasswordOrChallenge, respondToNewPasswordChallenge, } from './challenge.js';
31
+ export type { SignUpInput, SignUpResult } from './sign-up.js';
32
+ export { signUpUser } from './sign-up.js';
33
+ export type { AdminInviteUserInput, AdminInviteUserResult, AdminUpdateAttributesInput, } from './admin-users.js';
34
+ export { adminInviteUser, adminUpdateUserAttributes, adminDisableUser, adminEnableUser, } from './admin-users.js';
29
35
  export type { RefreshResult } from './refresh.js';
30
36
  export { refreshSession } from './refresh.js';
31
37
  export { revokeRefreshToken } from './revoke.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,YAAY,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,gBAAgB,CAAC;AAExB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,eAAe,EACf,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
@@ -24,6 +24,9 @@
24
24
  export { AuthError, mapProviderError } from './errors.js';
25
25
  export { loadAuthServerConfig } from './config.js';
26
26
  export { signInWithPassword } from './sign-in.js';
27
+ export { signInWithPasswordOrChallenge, respondToNewPasswordChallenge, } from './challenge.js';
28
+ export { signUpUser } from './sign-up.js';
29
+ export { adminInviteUser, adminUpdateUserAttributes, adminDisableUser, adminEnableUser, } from './admin-users.js';
27
30
  export { refreshSession } from './refresh.js';
28
31
  export { revokeRefreshToken } from './revoke.js';
29
32
  export { changePassword } from './change-password.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGlD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAOlD,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAO1C,OAAO,EACL,eAAe,EACf,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../src/server/refresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,MAAM,GAAE,gBAAyC,GAChD,OAAO,CAAC,aAAa,CAAC,CA8BxB"}
1
+ {"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../src/server/refresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAWpD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,MAAM,GAAE,gBAAyC,GAChD,OAAO,CAAC,aAAa,CAAC,CA8BxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../src/server/refresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAEhF,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAe1D;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,YAAoB,EACpB,SAA2B,oBAAoB,EAAE;IAEjD,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChE,IAAI,GAAG,CAAC;IACR,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CACrB,IAAI,mBAAmB,CAAC;YACtB,QAAQ,EAAE,MAAM,CAAC,WAAW;YAC5B,QAAQ,EAAE,oBAAoB;YAC9B,cAAc,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE;SAChD,CAAC,CACH,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,oBAAoB,CAAC;IACxC,iEAAiE;IACjE,qEAAqE;IACrE,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QAC5C,MAAM,IAAI,SAAS,CACjB,wBAAwB,EACxB,yDAAyD,EACzD,GAAG,CACJ,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,YAAY,EAAE,EAAE;QAChB,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,sBAAsB,CAAC,MAAM,CAAC,WAAW,CAAC;KAC1E,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../src/server/refresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAEhF,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAoB1D;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,YAAoB,EACpB,SAA2B,oBAAoB,EAAE;IAEjD,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChE,IAAI,GAAG,CAAC;IACR,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CACrB,IAAI,mBAAmB,CAAC;YACtB,QAAQ,EAAE,MAAM,CAAC,WAAW;YAC5B,QAAQ,EAAE,oBAAoB;YAC9B,cAAc,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE;SAChD,CAAC,CACH,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,oBAAoB,CAAC;IACxC,iEAAiE;IACjE,qEAAqE;IACrE,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QAC5C,MAAM,IAAI,SAAS,CACjB,wBAAwB,EACxB,yDAAyD,EACzD,GAAG,CACJ,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,YAAY,EAAE,EAAE;QAChB,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,sBAAsB,CAAC,MAAM,CAAC,WAAW,CAAC;KAC1E,CAAC;AACJ,CAAC"}
@@ -17,13 +17,8 @@
17
17
  * Cognito-specific error names.
18
18
  */
19
19
  import type { AuthServerConfig } from './config.js';
20
- export interface SignInResult {
21
- idToken: string;
22
- accessToken: string;
23
- refreshToken: string;
24
- /** Seconds until the id/access tokens expire. */
25
- expiresIn: number;
26
- }
20
+ import { type SignInResult } from './tokens.js';
21
+ export type { SignInResult } from './tokens.js';
27
22
  export interface SignInCredentials {
28
23
  email: string;
29
24
  password: string;
@@ -1 +1 @@
1
- {"version":3,"file":"sign-in.d.ts","sourceRoot":"","sources":["../../src/server/sign-in.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,iBAAiB,EAC9B,MAAM,GAAE,gBAAyC,GAChD,OAAO,CAAC,YAAY,CAAC,CAsCvB"}
1
+ {"version":3,"file":"sign-in.d.ts","sourceRoot":"","sources":["../../src/server/sign-in.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAErE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,iBAAiB,EAC9B,MAAM,GAAE,gBAAyC,GAChD,OAAO,CAAC,YAAY,CAAC,CAsCvB"}
@@ -20,7 +20,7 @@ import { InitiateAuthCommand, } from '@aws-sdk/client-cognito-identity-provider'
20
20
  import { loadAuthServerConfig } from './config.js';
21
21
  import { getCognitoClient } from './cognito-client.js';
22
22
  import { AuthError, mapProviderError } from './errors.js';
23
- import { deriveExpiresInFromJwt } from './token-utils.js';
23
+ import { extractSignInTokens } from './tokens.js';
24
24
  /**
25
25
  * Authenticate a user with email + password and return freshly-minted
26
26
  * id, access, and refresh tokens.
@@ -71,21 +71,4 @@ function challengeMessage(challengeName) {
71
71
  }
72
72
  return base;
73
73
  }
74
- function extractSignInTokens(result) {
75
- // Tokens themselves MUST be present. `ExpiresIn` is derived from the
76
- // access-token's `exp` claim when the response omits it — real AWS
77
- // always sends it, but some OSS compatibles (cognito-local) don't,
78
- // and the tokens are usable regardless.
79
- if (!result?.IdToken ||
80
- !result.AccessToken ||
81
- !result.RefreshToken) {
82
- throw new AuthError('incomplete_auth_result', 'Identity provider returned an incomplete authentication result', 500);
83
- }
84
- return {
85
- idToken: result.IdToken,
86
- accessToken: result.AccessToken,
87
- refreshToken: result.RefreshToken,
88
- expiresIn: result.ExpiresIn ?? deriveExpiresInFromJwt(result.AccessToken),
89
- };
90
- }
91
74
  //# sourceMappingURL=sign-in.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sign-in.js","sourceRoot":"","sources":["../../src/server/sign-in.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,mBAAmB,GAGpB,MAAM,2CAA2C,CAAC;AAEnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAe1D;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,WAA8B,EAC9B,SAA2B,oBAAoB,EAAE;IAEjD,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChE,IAAI,GAA8B,CAAC;IACnC,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CACrB,IAAI,mBAAmB,CAAC;YACtB,QAAQ,EAAE,MAAM,CAAC,WAAW;YAC5B,QAAQ,EAAE,oBAAoB;YAC9B,cAAc,EAAE;gBACd,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE;gBACzC,QAAQ,EAAE,WAAW,CAAC,QAAQ;aAC/B;SACF,CAAC,CACH,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,gBAAgB,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,uCAAuC;IACvC,4DAA4D;IAC5D,wEAAwE;IACxE,6DAA6D;IAC7D,kEAAkE;IAClE,EAAE;IACF,uEAAuE;IACvE,kEAAkE;IAClE,kEAAkE;IAClE,yDAAyD;IACzD,0DAA0D;IAC1D,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;QACtB,MAAM,IAAI,SAAS,CACjB,yBAAyB,EACzB,gBAAgB,CAAC,GAAG,CAAC,aAAa,CAAC,EACnC,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,OAAO,mBAAmB,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,gBAAgB,CAAC,aAAqB;IAC7C,MAAM,IAAI,GAAG,yCAAyC,aAAa,GAAG,CAAC;IACvE,IAAI,aAAa,KAAK,uBAAuB,EAAE,CAAC;QAC9C,OAAO,CACL,IAAI;YACJ,oEAAoE;YACpE,qEAAqE;YACrE,qDAAqD,CACtD,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,mBAAmB,CAC1B,MAA4C;IAE5C,qEAAqE;IACrE,mEAAmE;IACnE,mEAAmE;IACnE,wCAAwC;IACxC,IACE,CAAC,MAAM,EAAE,OAAO;QAChB,CAAC,MAAM,CAAC,WAAW;QACnB,CAAC,MAAM,CAAC,YAAY,EACpB,CAAC;QACD,MAAM,IAAI,SAAS,CACjB,wBAAwB,EACxB,gEAAgE,EAChE,GAAG,CACJ,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,sBAAsB,CAAC,MAAM,CAAC,WAAW,CAAC;KAC1E,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"sign-in.js","sourceRoot":"","sources":["../../src/server/sign-in.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,mBAAmB,GAEpB,MAAM,2CAA2C,CAAC;AAEnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAqB,MAAM,aAAa,CAAC;AASrE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,WAA8B,EAC9B,SAA2B,oBAAoB,EAAE;IAEjD,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChE,IAAI,GAA8B,CAAC;IACnC,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CACrB,IAAI,mBAAmB,CAAC;YACtB,QAAQ,EAAE,MAAM,CAAC,WAAW;YAC5B,QAAQ,EAAE,oBAAoB;YAC9B,cAAc,EAAE;gBACd,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE;gBACzC,QAAQ,EAAE,WAAW,CAAC,QAAQ;aAC/B;SACF,CAAC,CACH,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,gBAAgB,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,uCAAuC;IACvC,4DAA4D;IAC5D,wEAAwE;IACxE,6DAA6D;IAC7D,kEAAkE;IAClE,EAAE;IACF,uEAAuE;IACvE,kEAAkE;IAClE,kEAAkE;IAClE,yDAAyD;IACzD,0DAA0D;IAC1D,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;QACtB,MAAM,IAAI,SAAS,CACjB,yBAAyB,EACzB,gBAAgB,CAAC,GAAG,CAAC,aAAa,CAAC,EACnC,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,OAAO,mBAAmB,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,gBAAgB,CAAC,aAAqB;IAC7C,MAAM,IAAI,GAAG,yCAAyC,aAAa,GAAG,CAAC;IACvE,IAAI,aAAa,KAAK,uBAAuB,EAAE,CAAC;QAC9C,OAAO,CACL,IAAI;YACJ,oEAAoE;YACpE,qEAAqE;YACrE,qDAAqD,CACtD,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Self-service user registration against a Cognito User Pool.
3
+ *
4
+ * Wraps the three-step pattern every consumer ends up writing for a
5
+ * working "sign-up + immediate login" flow:
6
+ *
7
+ * 1. `SignUp` — create the user with email + password + standard
8
+ * and custom attributes.
9
+ * 2. `AdminConfirmSignUp` — skip the email-verification challenge
10
+ * (the consumer's own flow is responsible for whatever real
11
+ * verification ships before / after this).
12
+ * 3. `AdminUpdateUserAttributes` — flip `email_verified=true` so
13
+ * Cognito doesn't re-challenge on the next sign-in.
14
+ *
15
+ * Steps 2-3 are gated by {@link SignUpInput.autoConfirm} (default
16
+ * `true`). When the consumer wants the standard Cognito email-link
17
+ * verification, set it to `false` and call `AdminConfirmSignUp`
18
+ * yourself out-of-band.
19
+ *
20
+ * In production the executing IAM principal needs
21
+ * `cognito-idp:AdminConfirmSignUp` and
22
+ * `cognito-idp:AdminUpdateUserAttributes` for steps 2-3.
23
+ * `cognito-local` accepts admin commands unauthenticated.
24
+ */
25
+ import type { AuthServerConfig } from './config.js';
26
+ export interface SignUpInput {
27
+ email: string;
28
+ password: string;
29
+ /**
30
+ * Standard OIDC `name` attribute on the Cognito user. Optional —
31
+ * omit when the pool doesn't request `name` as a required attribute.
32
+ */
33
+ name?: string;
34
+ /**
35
+ * Additional standard attributes (`given_name`, `family_name`,
36
+ * `phone_number`, …). Keys are sent verbatim. Standard claims are
37
+ * defined by Cognito's user-pool schema.
38
+ */
39
+ attributes?: Record<string, string>;
40
+ /**
41
+ * Custom attributes — keyed without the `custom:` prefix; the
42
+ * helper prepends it. So `{ role: 'buyer' }` becomes
43
+ * `{ Name: 'custom:role', Value: 'buyer' }`.
44
+ */
45
+ customAttributes?: Record<string, string>;
46
+ /**
47
+ * When `true` (default), follow the SignUp with
48
+ * `AdminConfirmSignUp` + `email_verified=true` so the user can
49
+ * immediately sign in without going through Cognito's email
50
+ * verification challenge. Set to `false` to opt into the standard
51
+ * verification flow.
52
+ */
53
+ autoConfirm?: boolean;
54
+ }
55
+ export interface SignUpResult {
56
+ /** Cognito `sub` — canonical user id across the platform. */
57
+ userSub: string;
58
+ /** Whether `AdminConfirmSignUp` ran successfully. */
59
+ confirmed: boolean;
60
+ }
61
+ /**
62
+ * Register a new user. Returns the Cognito `sub` so the caller can
63
+ * mirror it into their own `users` table.
64
+ *
65
+ * Errors are normalized via {@link mapProviderError}: a duplicate
66
+ * email surfaces as `UsernameExistsException` (HTTP 401 by default —
67
+ * route handlers typically map this to a 409), an invalid password
68
+ * as `invalid_parameter` (HTTP 422).
69
+ */
70
+ export declare function signUpUser(input: SignUpInput, config?: AuthServerConfig): Promise<SignUpResult>;
71
+ //# sourceMappingURL=sign-up.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign-up.d.ts","sourceRoot":"","sources":["../../src/server/sign-up.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAQH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAKpD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,WAAW,EAClB,MAAM,GAAE,gBAAyC,GAChD,OAAO,CAAC,YAAY,CAAC,CAiEvB"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Self-service user registration against a Cognito User Pool.
3
+ *
4
+ * Wraps the three-step pattern every consumer ends up writing for a
5
+ * working "sign-up + immediate login" flow:
6
+ *
7
+ * 1. `SignUp` — create the user with email + password + standard
8
+ * and custom attributes.
9
+ * 2. `AdminConfirmSignUp` — skip the email-verification challenge
10
+ * (the consumer's own flow is responsible for whatever real
11
+ * verification ships before / after this).
12
+ * 3. `AdminUpdateUserAttributes` — flip `email_verified=true` so
13
+ * Cognito doesn't re-challenge on the next sign-in.
14
+ *
15
+ * Steps 2-3 are gated by {@link SignUpInput.autoConfirm} (default
16
+ * `true`). When the consumer wants the standard Cognito email-link
17
+ * verification, set it to `false` and call `AdminConfirmSignUp`
18
+ * yourself out-of-band.
19
+ *
20
+ * In production the executing IAM principal needs
21
+ * `cognito-idp:AdminConfirmSignUp` and
22
+ * `cognito-idp:AdminUpdateUserAttributes` for steps 2-3.
23
+ * `cognito-local` accepts admin commands unauthenticated.
24
+ */
25
+ import { AdminConfirmSignUpCommand, AdminUpdateUserAttributesCommand, SignUpCommand, } from '@aws-sdk/client-cognito-identity-provider';
26
+ import { loadAuthServerConfig } from './config.js';
27
+ import { getCognitoClient } from './cognito-client.js';
28
+ import { AuthError, mapProviderError } from './errors.js';
29
+ /**
30
+ * Register a new user. Returns the Cognito `sub` so the caller can
31
+ * mirror it into their own `users` table.
32
+ *
33
+ * Errors are normalized via {@link mapProviderError}: a duplicate
34
+ * email surfaces as `UsernameExistsException` (HTTP 401 by default —
35
+ * route handlers typically map this to a 409), an invalid password
36
+ * as `invalid_parameter` (HTTP 422).
37
+ */
38
+ export async function signUpUser(input, config = loadAuthServerConfig()) {
39
+ const client = getCognitoClient(config.region, config.endpoint);
40
+ const email = input.email.toLowerCase();
41
+ const autoConfirm = input.autoConfirm ?? true;
42
+ const userAttributes = buildUserAttributes(email, input);
43
+ let userSub;
44
+ try {
45
+ const res = await client.send(new SignUpCommand({
46
+ ClientId: config.appClientId,
47
+ Username: email,
48
+ Password: input.password,
49
+ UserAttributes: userAttributes,
50
+ }));
51
+ if (!res.UserSub) {
52
+ throw new AuthError('sign_up_failed', 'Identity provider returned no UserSub from SignUp', 500);
53
+ }
54
+ userSub = res.UserSub;
55
+ }
56
+ catch (err) {
57
+ if (err instanceof AuthError)
58
+ throw err;
59
+ throw mapProviderError(err, 'sign_up_failed');
60
+ }
61
+ if (!autoConfirm) {
62
+ return { userSub, confirmed: false };
63
+ }
64
+ // Confirm + mark email verified so the next sign-in succeeds
65
+ // without manual intervention. Failures here are fatal — an
66
+ // unconfirmed user can't log in, leaving the account in a
67
+ // half-registered limbo.
68
+ try {
69
+ await client.send(new AdminConfirmSignUpCommand({
70
+ UserPoolId: config.userPoolId,
71
+ Username: email,
72
+ }));
73
+ await client.send(new AdminUpdateUserAttributesCommand({
74
+ UserPoolId: config.userPoolId,
75
+ Username: email,
76
+ // cognito-local insists on `email` being present whenever
77
+ // `email_verified` is set in the same request (see
78
+ // validatePermittedAttributeChanges in jagregory/cognito-local).
79
+ // Real Cognito doesn't require this but accepts it as a no-op
80
+ // re-set, so sending both keeps prod + local on the same path.
81
+ UserAttributes: [
82
+ { Name: 'email', Value: email },
83
+ { Name: 'email_verified', Value: 'true' },
84
+ ],
85
+ }));
86
+ }
87
+ catch (err) {
88
+ throw mapProviderError(err, 'sign_up_confirm_failed');
89
+ }
90
+ return { userSub, confirmed: true };
91
+ }
92
+ function buildUserAttributes(email, input) {
93
+ const out = [{ Name: 'email', Value: email }];
94
+ if (input.name !== undefined)
95
+ out.push({ Name: 'name', Value: input.name });
96
+ for (const [name, value] of Object.entries(input.attributes ?? {})) {
97
+ if (name === 'email')
98
+ continue; // already set above
99
+ out.push({ Name: name, Value: value });
100
+ }
101
+ for (const [name, value] of Object.entries(input.customAttributes ?? {})) {
102
+ out.push({ Name: `custom:${name}`, Value: value });
103
+ }
104
+ return out;
105
+ }
106
+ //# sourceMappingURL=sign-up.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign-up.js","sourceRoot":"","sources":["../../src/server/sign-up.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Internal token-extraction helper shared by every Cognito flow that
3
+ * resolves an `AuthenticationResult` (sign-in, refresh, challenge
4
+ * response).
5
+ *
6
+ * `ExpiresIn` is populated by real AWS Cognito on every successful
7
+ * `InitiateAuth` / `RespondToAuthChallenge` response, but some OSS
8
+ * compatibles (notably `cognito-local`) omit it. The access token's
9
+ * `exp` claim is always present and trustworthy (we just minted the
10
+ * token), so we derive the remaining lifetime from it as a fallback.
11
+ *
12
+ * Not part of the public API — `@venturekit/auth/server` consumers
13
+ * receive the resolved {@link SignInResult} from the flow they call.
14
+ */
15
+ import type { AuthenticationResultType } from '@aws-sdk/client-cognito-identity-provider';
16
+ export interface SignInResult {
17
+ idToken: string;
18
+ accessToken: string;
19
+ refreshToken: string;
20
+ /** Seconds until the id/access tokens expire. */
21
+ expiresIn: number;
22
+ }
23
+ /**
24
+ * Map a successful Cognito `AuthenticationResult` to the
25
+ * {@link SignInResult} shape consumers receive from the public flows.
26
+ *
27
+ * Throws {@link AuthError} (`incomplete_auth_result`, HTTP 500) when
28
+ * any of the three tokens is missing — that's a provider-side bug,
29
+ * not a credentials problem.
30
+ */
31
+ export declare function extractSignInTokens(result: AuthenticationResultType | undefined): SignInResult;
32
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/server/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AAI1F,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,wBAAwB,GAAG,SAAS,GAC3C,YAAY,CAcd"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Internal token-extraction helper shared by every Cognito flow that
3
+ * resolves an `AuthenticationResult` (sign-in, refresh, challenge
4
+ * response).
5
+ *
6
+ * `ExpiresIn` is populated by real AWS Cognito on every successful
7
+ * `InitiateAuth` / `RespondToAuthChallenge` response, but some OSS
8
+ * compatibles (notably `cognito-local`) omit it. The access token's
9
+ * `exp` claim is always present and trustworthy (we just minted the
10
+ * token), so we derive the remaining lifetime from it as a fallback.
11
+ *
12
+ * Not part of the public API — `@venturekit/auth/server` consumers
13
+ * receive the resolved {@link SignInResult} from the flow they call.
14
+ */
15
+ import { AuthError } from './errors.js';
16
+ import { deriveExpiresInFromJwt } from './token-utils.js';
17
+ /**
18
+ * Map a successful Cognito `AuthenticationResult` to the
19
+ * {@link SignInResult} shape consumers receive from the public flows.
20
+ *
21
+ * Throws {@link AuthError} (`incomplete_auth_result`, HTTP 500) when
22
+ * any of the three tokens is missing — that's a provider-side bug,
23
+ * not a credentials problem.
24
+ */
25
+ export function extractSignInTokens(result) {
26
+ if (!result?.IdToken || !result.AccessToken || !result.RefreshToken) {
27
+ throw new AuthError('incomplete_auth_result', 'Identity provider returned an incomplete authentication result', 500);
28
+ }
29
+ return {
30
+ idToken: result.IdToken,
31
+ accessToken: result.AccessToken,
32
+ refreshToken: result.RefreshToken,
33
+ expiresIn: result.ExpiresIn ?? deriveExpiresInFromJwt(result.AccessToken),
34
+ };
35
+ }
36
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/server/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAU1D;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAA4C;IAE5C,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;QACpE,MAAM,IAAI,SAAS,CACjB,wBAAwB,EACxB,gEAAgE,EAChE,GAAG,CACJ,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,sBAAsB,CAAC,MAAM,CAAC,WAAW,CAAC;KAC1E,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@venturekit/auth",
3
- "version": "0.0.0-dev.20260506001012",
3
+ "version": "0.0.0-dev.20260506003129",
4
4
  "description": "Authentication and authorization for VentureKit",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -29,12 +29,12 @@
29
29
  }
30
30
  },
31
31
  "dependencies": {
32
- "@venturekit/core": "0.0.0-dev.20260506001012",
32
+ "@venturekit/core": "0.0.0-dev.20260506003129",
33
33
  "@aws-sdk/client-cognito-identity-provider": "^3.668.0",
34
34
  "aws-jwt-verify": "^4.0.1"
35
35
  },
36
36
  "peerDependencies": {
37
- "@venturekit/runtime": "0.0.0-dev.20260506001012"
37
+ "@venturekit/runtime": "0.0.0-dev.20260506003129"
38
38
  },
39
39
  "peerDependenciesMeta": {
40
40
  "@venturekit/runtime": {
@@ -42,7 +42,7 @@
42
42
  }
43
43
  },
44
44
  "devDependencies": {
45
- "@venturekit/runtime": "0.0.0-dev.20260506001012",
45
+ "@venturekit/runtime": "0.0.0-dev.20260506003129",
46
46
  "@types/aws-lambda": "^8.10.131",
47
47
  "@types/node": "^25.6.0",
48
48
  "typescript": "^5.3.0"