@venturekit/auth 0.0.0-dev.20260506001012 → 0.0.0-dev.20260506003723
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/server/admin-users.d.ts +90 -0
- package/dist/server/admin-users.d.ts.map +1 -0
- package/dist/server/admin-users.js +132 -0
- package/dist/server/admin-users.js.map +1 -0
- package/dist/server/challenge.d.ts +74 -0
- package/dist/server/challenge.d.ts.map +1 -0
- package/dist/server/challenge.js +107 -0
- package/dist/server/challenge.js.map +1 -0
- package/dist/server/index.d.ts +6 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/refresh.d.ts.map +1 -1
- package/dist/server/refresh.js.map +1 -1
- package/dist/server/sign-in.d.ts +2 -7
- package/dist/server/sign-in.d.ts.map +1 -1
- package/dist/server/sign-in.js +1 -18
- package/dist/server/sign-in.js.map +1 -1
- package/dist/server/sign-up.d.ts +71 -0
- package/dist/server/sign-up.d.ts.map +1 -0
- package/dist/server/sign-up.js +106 -0
- package/dist/server/sign-up.js.map +1 -0
- package/dist/server/tokens.d.ts +32 -0
- package/dist/server/tokens.d.ts.map +1 -0
- package/dist/server/tokens.js +36 -0
- package/dist/server/tokens.js.map +1 -0
- package/package.json +4 -4
|
@@ -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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"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -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"}
|
package/dist/server/index.js
CHANGED
|
@@ -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';
|
package/dist/server/index.js.map
CHANGED
|
@@ -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;
|
|
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;
|
|
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;
|
|
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"}
|
package/dist/server/sign-in.d.ts
CHANGED
|
@@ -17,13 +17,8 @@
|
|
|
17
17
|
* Cognito-specific error names.
|
|
18
18
|
*/
|
|
19
19
|
import type { AuthServerConfig } from './config.js';
|
|
20
|
-
|
|
21
|
-
|
|
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;
|
|
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"}
|
package/dist/server/sign-in.js
CHANGED
|
@@ -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 {
|
|
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,
|
|
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.
|
|
3
|
+
"version": "0.0.0-dev.20260506003723",
|
|
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.
|
|
32
|
+
"@venturekit/core": "0.0.0-dev.20260506003723",
|
|
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.
|
|
37
|
+
"@venturekit/runtime": "0.0.0-dev.20260506003723"
|
|
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.
|
|
45
|
+
"@venturekit/runtime": "0.0.0-dev.20260506003723",
|
|
46
46
|
"@types/aws-lambda": "^8.10.131",
|
|
47
47
|
"@types/node": "^25.6.0",
|
|
48
48
|
"typescript": "^5.3.0"
|