@robelest/convex-auth 0.0.4-preview.30 → 0.0.4-preview.32
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/bin.js +125 -36
- package/dist/browser/index.d.ts +3 -13
- package/dist/browser/index.js +47 -12
- package/dist/browser/navigation.js +1 -1
- package/dist/browser/passkey.js +7 -7
- package/dist/browser/runtime.js +13 -15
- package/dist/client/core/types.d.ts +179 -63
- package/dist/client/core/types.js +6 -0
- package/dist/client/factors/totp.js +1 -1
- package/dist/client/index.d.ts +5 -4
- package/dist/client/index.js +115 -56
- package/dist/client/runtime/mutex.js +3 -2
- package/dist/component/_generated/component.d.ts +40 -0
- package/dist/component/http.js +9 -0
- package/dist/component/index.d.ts +1 -1
- package/dist/component/model.d.ts +27 -27
- package/dist/component/model.js +2 -1
- package/dist/component/modules.js +1 -0
- package/dist/component/public/factors/passkeys.js +31 -1
- package/dist/component/public/identity/codes.js +1 -1
- package/dist/component/public/identity/tokens.js +2 -1
- package/dist/component/public/identity/verifiers.js +15 -5
- package/dist/component/public.js +2 -2
- package/dist/component/schema.d.ts +287 -285
- package/dist/component/schema.js +2 -1
- package/dist/core/index.d.ts +8 -3
- package/dist/core/index.js +7 -2
- package/dist/expo/index.d.ts +21 -0
- package/dist/expo/index.js +148 -0
- package/dist/expo/passkey.js +174 -0
- package/dist/providers/apple.d.ts +1 -1
- package/dist/providers/apple.js +6 -8
- package/dist/providers/custom.d.ts +1 -1
- package/dist/providers/custom.js +4 -7
- package/dist/providers/github.d.ts +1 -1
- package/dist/providers/github.js +5 -8
- package/dist/providers/google.d.ts +1 -1
- package/dist/providers/google.js +5 -8
- package/dist/providers/microsoft.d.ts +1 -1
- package/dist/providers/microsoft.js +5 -9
- package/dist/providers/password.d.ts +18 -37
- package/dist/providers/password.js +170 -115
- package/dist/providers/redirect.d.ts +1 -0
- package/dist/providers/redirect.js +20 -0
- package/dist/server/auth.d.ts +6 -7
- package/dist/server/auth.js +3 -2
- package/dist/server/{ctxCache.js → cache/context.js} +2 -2
- package/dist/server/{componentContext.d.ts → component/context.d.ts} +2 -2
- package/dist/server/context.js +3 -10
- package/dist/server/contract.d.ts +2 -87
- package/dist/server/contract.js +1 -1
- package/dist/server/cookies.js +25 -1
- package/dist/server/core.js +1 -1
- package/dist/server/errors.js +24 -1
- package/dist/server/{auth-context.d.ts → facade.d.ts} +3 -45
- package/dist/server/{auth-context.js → facade.js} +11 -12
- package/dist/server/http.d.ts +7 -7
- package/dist/server/http.js +47 -7
- package/dist/server/{convexIdentity.d.ts → identity/convex.d.ts} +3 -3
- package/dist/server/index.d.ts +5 -3
- package/dist/server/index.js +3 -2
- package/dist/server/mounts.d.ts +171 -18
- package/dist/server/mutations/code.js +7 -1
- package/dist/server/mutations/{credentialsSignIn.js → credentials/signin.js} +10 -10
- package/dist/server/mutations/index.js +1 -1
- package/dist/server/mutations/invalidate.js +11 -1
- package/dist/server/mutations/oauth.js +25 -27
- package/dist/server/mutations/signin.js +6 -0
- package/dist/server/mutations/signout.js +5 -0
- package/dist/server/mutations/store.js +1 -1
- package/dist/server/oauth/factory.js +11 -3
- package/dist/server/passkey.js +126 -110
- package/dist/server/prefetch.js +8 -1
- package/dist/server/redirects.js +11 -3
- package/dist/server/refresh.js +6 -1
- package/dist/server/runtime.d.ts +68 -37
- package/dist/server/runtime.js +318 -36
- package/dist/server/services/group.js +4 -0
- package/dist/server/sessions.js +1 -0
- package/dist/server/signin.js +8 -6
- package/dist/server/sso/domain.d.ts +159 -16
- package/dist/server/sso/domain.js +1 -1
- package/dist/server/sso/http.js +144 -60
- package/dist/server/sso/oidc.js +28 -12
- package/dist/server/sso/policy.js +30 -14
- package/dist/server/sso/provision.js +1 -1
- package/dist/server/sso/saml.js +18 -9
- package/dist/server/sso/scim.js +12 -4
- package/dist/server/sso/shared.js +5 -5
- package/dist/server/telemetry.js +3 -0
- package/dist/server/tokens.js +10 -2
- package/dist/server/totp.js +127 -100
- package/dist/server/types.d.ts +224 -151
- package/dist/server/url.js +1 -1
- package/dist/server/users.js +93 -53
- package/dist/server/wellknown.d.ts +75 -0
- package/dist/server/wellknown.js +198 -0
- package/dist/shared/errors.js +0 -1
- package/package.json +36 -4
- package/dist/server/oauth/index.js +0 -12
- package/dist/server/utils/dispatch.js +0 -36
- package/dist/shared/authResults.d.ts +0 -16
- /package/dist/server/{componentContext.js → component/context.js} +0 -0
- /package/dist/server/{convexIdentity.js → identity/convex.js} +0 -0
|
@@ -1,76 +1,7 @@
|
|
|
1
1
|
import "./types.js";
|
|
2
|
-
import "./
|
|
2
|
+
import "./component/context.js";
|
|
3
3
|
|
|
4
4
|
//#region src/server/contract.d.ts
|
|
5
|
-
type GroupConnectionRecord = {
|
|
6
|
-
_id: string;
|
|
7
|
-
_creationTime: number;
|
|
8
|
-
groupId: string;
|
|
9
|
-
slug?: string;
|
|
10
|
-
name?: string;
|
|
11
|
-
protocol: "oidc" | "saml";
|
|
12
|
-
status: "draft" | "active" | "disabled";
|
|
13
|
-
config?: unknown;
|
|
14
|
-
extend?: unknown;
|
|
15
|
-
};
|
|
16
|
-
type GroupConnectionDomainLookupRecord = {
|
|
17
|
-
connection: GroupConnectionRecord | null;
|
|
18
|
-
domain: ConnectionDomainRecord | null;
|
|
19
|
-
};
|
|
20
|
-
type GroupConnectionListResult = {
|
|
21
|
-
items: GroupConnectionRecord[];
|
|
22
|
-
nextCursor: string | null;
|
|
23
|
-
};
|
|
24
|
-
type ConnectionDomainRecord = {
|
|
25
|
-
_id: string;
|
|
26
|
-
_creationTime: number;
|
|
27
|
-
connectionId: string;
|
|
28
|
-
groupId: string;
|
|
29
|
-
domain: string;
|
|
30
|
-
isPrimary: boolean;
|
|
31
|
-
verifiedAt?: number;
|
|
32
|
-
};
|
|
33
|
-
type ScimConfigRecord = {
|
|
34
|
-
_id: string;
|
|
35
|
-
_creationTime: number;
|
|
36
|
-
connectionId: string;
|
|
37
|
-
groupId: string;
|
|
38
|
-
status: string;
|
|
39
|
-
basePath: string;
|
|
40
|
-
tokenHash: string;
|
|
41
|
-
lastRotatedAt?: number;
|
|
42
|
-
extend?: unknown;
|
|
43
|
-
};
|
|
44
|
-
type WebhookEndpointRecord = {
|
|
45
|
-
_id: string;
|
|
46
|
-
_creationTime: number;
|
|
47
|
-
connectionId: string;
|
|
48
|
-
groupId: string;
|
|
49
|
-
url: string;
|
|
50
|
-
status: string;
|
|
51
|
-
secretHash: string;
|
|
52
|
-
subscriptions: string[];
|
|
53
|
-
createdByUserId?: string;
|
|
54
|
-
lastSuccessAt?: number;
|
|
55
|
-
lastFailureAt?: number;
|
|
56
|
-
failureCount: number;
|
|
57
|
-
extend?: unknown;
|
|
58
|
-
};
|
|
59
|
-
type WebhookDeliveryRecord = {
|
|
60
|
-
_id: string;
|
|
61
|
-
_creationTime: number;
|
|
62
|
-
connectionId: string;
|
|
63
|
-
endpointId: string;
|
|
64
|
-
auditEventId?: string;
|
|
65
|
-
eventType: string;
|
|
66
|
-
status: string;
|
|
67
|
-
attemptCount: number;
|
|
68
|
-
nextAttemptAt: number;
|
|
69
|
-
lastAttemptAt?: number;
|
|
70
|
-
lastResponseStatus?: number;
|
|
71
|
-
lastError?: string;
|
|
72
|
-
payload: unknown;
|
|
73
|
-
};
|
|
74
5
|
type ScimIdentityRecord = {
|
|
75
6
|
_id: string;
|
|
76
7
|
_creationTime: number;
|
|
@@ -84,22 +15,6 @@ type ScimIdentityRecord = {
|
|
|
84
15
|
raw?: Record<string, unknown>;
|
|
85
16
|
lastProvisionedAt?: number;
|
|
86
17
|
};
|
|
87
|
-
type AuditEventRecord = {
|
|
88
|
-
_id: string;
|
|
89
|
-
_creationTime: number;
|
|
90
|
-
connectionId?: string;
|
|
91
|
-
groupId: string;
|
|
92
|
-
eventType: string;
|
|
93
|
-
actorType: string;
|
|
94
|
-
actorId?: string;
|
|
95
|
-
subjectType: string;
|
|
96
|
-
subjectId?: string;
|
|
97
|
-
status: string;
|
|
98
|
-
occurredAt: number;
|
|
99
|
-
requestId?: string;
|
|
100
|
-
ip?: string;
|
|
101
|
-
metadata?: Record<string, unknown>;
|
|
102
|
-
};
|
|
103
18
|
//#endregion
|
|
104
|
-
export {
|
|
19
|
+
export { ScimIdentityRecord };
|
|
105
20
|
//# sourceMappingURL=contract.d.ts.map
|
package/dist/server/contract.js
CHANGED
package/dist/server/cookies.js
CHANGED
|
@@ -10,6 +10,30 @@ const SHARED_COOKIE_OPTIONS = {
|
|
|
10
10
|
path: "/",
|
|
11
11
|
partitioned: true
|
|
12
12
|
};
|
|
13
|
+
/** Encode a redirectTo URL into the OAuth state parameter. */
|
|
14
|
+
function encodeOAuthState(state, redirectTo) {
|
|
15
|
+
if (redirectTo === null) return state;
|
|
16
|
+
const json = JSON.stringify({
|
|
17
|
+
s: state,
|
|
18
|
+
r: redirectTo
|
|
19
|
+
});
|
|
20
|
+
return btoa(json).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
21
|
+
}
|
|
22
|
+
/** Decode an OAuth state parameter, extracting the original state and redirectTo. */
|
|
23
|
+
function decodeOAuthState(encoded) {
|
|
24
|
+
try {
|
|
25
|
+
const padded = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
26
|
+
const json = JSON.parse(atob(padded));
|
|
27
|
+
if (typeof json === "object" && json !== null && typeof json.s === "string") return {
|
|
28
|
+
state: json.s,
|
|
29
|
+
redirectTo: typeof json.r === "string" ? json.r : null
|
|
30
|
+
};
|
|
31
|
+
} catch {}
|
|
32
|
+
return {
|
|
33
|
+
state: encoded,
|
|
34
|
+
redirectTo: null
|
|
35
|
+
};
|
|
36
|
+
}
|
|
13
37
|
const REDIRECT_MAX_AGE = 900;
|
|
14
38
|
/** @internal */
|
|
15
39
|
function redirectToParamCookie(providerId, redirectTo) {
|
|
@@ -44,5 +68,5 @@ function redirectToParamCookieName(providerId) {
|
|
|
44
68
|
}
|
|
45
69
|
|
|
46
70
|
//#endregion
|
|
47
|
-
export { SHARED_COOKIE_OPTIONS, redirectToParamCookie, useRedirectToParam };
|
|
71
|
+
export { SHARED_COOKIE_OPTIONS, decodeOAuthState, encodeOAuthState, redirectToParamCookie, useRedirectToParam };
|
|
48
72
|
//# sourceMappingURL=cookies.js.map
|
package/dist/server/core.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getSessionUserId } from "./context.js";
|
|
2
|
-
import { cached, ctxCacheHas, invalidateCtxCache } from "./
|
|
2
|
+
import { cached, ctxCacheHas, invalidateCtxCache } from "./cache/context.js";
|
|
3
3
|
import { generateRandomString, sha256 } from "./random.js";
|
|
4
4
|
import { buildScopeChecker, checkKeyRateLimit, generateApiKey, hashApiKey } from "./keys.js";
|
|
5
5
|
import { ConvexError } from "convex/values";
|
package/dist/server/errors.js
CHANGED
|
@@ -2,6 +2,29 @@ import { AuthFlowError } from "../shared/errors.js";
|
|
|
2
2
|
import { ConvexError } from "convex/values";
|
|
3
3
|
|
|
4
4
|
//#region src/server/errors.ts
|
|
5
|
+
/**
|
|
6
|
+
* Internal signal carrying a non-`signedIn` flow result up through a
|
|
7
|
+
* credentials authorize callback.
|
|
8
|
+
*
|
|
9
|
+
* `ctx.auth.provider.signIn` re-enters the canonical sign-in flow so a
|
|
10
|
+
* credentials provider (e.g. password.ts) can hand off to a verify/reset
|
|
11
|
+
* email provider, an OAuth redirect, or a device-code flow. Those handlers
|
|
12
|
+
* resolve to results like `{ kind: "started" }` or `{ kind: "redirect" }`,
|
|
13
|
+
* which the credentials runner has no shape to return — its `authorize`
|
|
14
|
+
* contract is `{ userId, ... } | null`. Throwing a `FlowSignal` lets the
|
|
15
|
+
* runner unwrap it and forward the carried result unchanged to the outer
|
|
16
|
+
* signIn action.
|
|
17
|
+
*
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
var FlowSignal = class extends Error {
|
|
21
|
+
result;
|
|
22
|
+
constructor(result) {
|
|
23
|
+
super(`FlowSignal:${result.kind}`);
|
|
24
|
+
this.name = "FlowSignal";
|
|
25
|
+
this.result = result;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
5
28
|
/** @internal */
|
|
6
29
|
const toConvexError = (error) => {
|
|
7
30
|
if (error instanceof ConvexError) return error;
|
|
@@ -16,5 +39,5 @@ const toConvexError = (error) => {
|
|
|
16
39
|
};
|
|
17
40
|
|
|
18
41
|
//#endregion
|
|
19
|
-
export { toConvexError };
|
|
42
|
+
export { FlowSignal, toConvexError };
|
|
20
43
|
//# sourceMappingURL=errors.js.map
|
|
@@ -2,7 +2,7 @@ import { ConvexAuthConfig, Doc } from "./types.js";
|
|
|
2
2
|
import { GenericId } from "convex/values";
|
|
3
3
|
import { UserIdentity } from "convex/server";
|
|
4
4
|
|
|
5
|
-
//#region src/server/
|
|
5
|
+
//#region src/server/facade.d.ts
|
|
6
6
|
/**
|
|
7
7
|
* Config for auth setup. Extends the standard auth config
|
|
8
8
|
* minus `component` (which is passed as the first constructor argument).
|
|
@@ -139,23 +139,6 @@ type AuthContextConfig<TResolve extends Record<string, unknown> = Record<string,
|
|
|
139
139
|
* of throwing `NOT_SIGNED_IN`.
|
|
140
140
|
*/
|
|
141
141
|
optional?: boolean;
|
|
142
|
-
/**
|
|
143
|
-
* Resolve the active group + membership when building `ctx.auth`.
|
|
144
|
-
*
|
|
145
|
-
* The full resolver fires three sequential component reads on every
|
|
146
|
-
* call: `user.get`, `user.getActiveGroup`, `member.inspect`. For
|
|
147
|
-
* handlers that only need `userId` / `user` (e.g. `account:listPasskeys`,
|
|
148
|
-
* profile reads, self-service settings), the second and third reads are
|
|
149
|
-
* pure overhead.
|
|
150
|
-
*
|
|
151
|
-
* Set `group: false` to skip them. `ctx.auth.groupId`, `ctx.auth.role`,
|
|
152
|
-
* and `ctx.auth.grants` come back as `null` / `[]` without any
|
|
153
|
-
* component round-trip. Saves ~10–30ms per auth-gated call on the
|
|
154
|
-
* lightweight path.
|
|
155
|
-
*
|
|
156
|
-
* @defaultValue true
|
|
157
|
-
*/
|
|
158
|
-
group?: boolean;
|
|
159
142
|
/**
|
|
160
143
|
* Attach additional derived fields to the auth context after the base auth
|
|
161
144
|
* context is resolved.
|
|
@@ -163,31 +146,6 @@ type AuthContextConfig<TResolve extends Record<string, unknown> = Record<string,
|
|
|
163
146
|
* This callback runs only when an authenticated user context is available.
|
|
164
147
|
*/
|
|
165
148
|
resolve?: (ctx: TCtx, user: UserDoc, auth: AuthContext) => Promise<TResolve> | TResolve;
|
|
166
|
-
/**
|
|
167
|
-
* Override or wrap the base auth resolution used by {@link createAuth().ctx}.
|
|
168
|
-
*
|
|
169
|
-
* Return `undefined` to fall back to the built-in resolver,
|
|
170
|
-
* `null` for an explicit unauthenticated state, or an
|
|
171
|
-
* {@link AuthContext} object to provide a pre-resolved auth state.
|
|
172
|
-
* This is useful for tests, proxy auth, impersonation flows, or any
|
|
173
|
-
* environment that needs to inject auth without depending on the standard
|
|
174
|
-
* Convex auth tables.
|
|
175
|
-
*
|
|
176
|
-
* @param ctx - The Convex function context.
|
|
177
|
-
* @param fallback - The built-in auth resolver used by {@link createAuth().ctx}.
|
|
178
|
-
* @returns Resolved auth state, `null`, or `undefined` to use the fallback.
|
|
179
|
-
*
|
|
180
|
-
* @example
|
|
181
|
-
* ```ts
|
|
182
|
-
* const authCtx = auth.ctx({
|
|
183
|
-
* authResolve: async (ctx, fallback) => {
|
|
184
|
-
* const injected = getInjectedAuth(ctx);
|
|
185
|
-
* return injected ?? (await fallback());
|
|
186
|
-
* },
|
|
187
|
-
* });
|
|
188
|
-
* ```
|
|
189
|
-
*/
|
|
190
|
-
authResolve?: (ctx: TCtx, fallback: () => Promise<AuthContext | null>) => Promise<AuthContext | null | undefined> | AuthContext | null | undefined;
|
|
191
149
|
};
|
|
192
150
|
/**
|
|
193
151
|
* Extract the resolved `auth` context type from an `auth.ctx()` customization.
|
|
@@ -217,5 +175,5 @@ type InferAuth<T extends {
|
|
|
217
175
|
input: (...args: never[]) => CustomFunctionInputResult<Record<string, unknown>>;
|
|
218
176
|
}> = Awaited<ReturnType<T["input"]>>["ctx"]["auth"];
|
|
219
177
|
//#endregion
|
|
220
|
-
export { AuthConfig, AuthContext, AuthContextConfig, AuthContextFactory, AuthContextResolver, InferAuth, OptionalAuthContext, UserDoc };
|
|
221
|
-
//# sourceMappingURL=
|
|
178
|
+
export { AuthConfig, AuthContext, AuthContextConfig, type AuthContextFactory, type AuthContextResolver, InferAuth, OptionalAuthContext, UserDoc };
|
|
179
|
+
//# sourceMappingURL=facade.d.ts.map
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { createUnauthenticatedAuthContext, getAuthContext } from "./context.js";
|
|
2
2
|
import { ConvexError } from "convex/values";
|
|
3
3
|
|
|
4
|
-
//#region src/server/
|
|
5
|
-
async function resolveConfiguredAuthContext(auth, ctx,
|
|
6
|
-
|
|
7
|
-
const authOverride = config?.authResolve ? await config.authResolve(ctx, fallback) : void 0;
|
|
8
|
-
return authOverride === void 0 ? await fallback() : authOverride;
|
|
4
|
+
//#region src/server/facade.ts
|
|
5
|
+
async function resolveConfiguredAuthContext(auth, ctx, _config) {
|
|
6
|
+
return await getAuthContext(auth, ctx);
|
|
9
7
|
}
|
|
10
8
|
function createNotSignedInError() {
|
|
11
9
|
return new ConvexError({
|
|
@@ -13,6 +11,7 @@ function createNotSignedInError() {
|
|
|
13
11
|
message: "Authentication required."
|
|
14
12
|
});
|
|
15
13
|
}
|
|
14
|
+
/** @internal */
|
|
16
15
|
function assertAuthResolverContext(ctx) {
|
|
17
16
|
const candidate = ctx;
|
|
18
17
|
if (candidate === null || typeof candidate !== "object" || candidate.auth === void 0 || candidate.auth === null || typeof candidate.auth !== "object" || typeof candidate.auth.getUserIdentity !== "function" || typeof candidate.runQuery !== "function") throw new TypeError("auth.context(ctx) requires a Convex function context with auth.getUserIdentity() and runQuery().");
|
|
@@ -20,8 +19,7 @@ function assertAuthResolverContext(ctx) {
|
|
|
20
19
|
/**
|
|
21
20
|
* Resolve the public auth context for a Convex handler context.
|
|
22
21
|
*
|
|
23
|
-
* This low-level helper underpins `auth.context(...)
|
|
24
|
-
* compatibility with existing consumers using the server entrypoint.
|
|
22
|
+
* This low-level helper underpins `auth.context(...)`.
|
|
25
23
|
*/
|
|
26
24
|
async function createPublicAuthContext(auth, ctx, config) {
|
|
27
25
|
const resolved = await resolveConfiguredAuthContext(auth, ctx, config);
|
|
@@ -38,8 +36,7 @@ async function createPublicAuthContext(auth, ctx, config) {
|
|
|
38
36
|
/**
|
|
39
37
|
* Create a convex-helpers customization that injects `ctx.auth`.
|
|
40
38
|
*
|
|
41
|
-
* This low-level helper underpins `auth.ctx(...)
|
|
42
|
-
* compatibility with existing consumers using the server entrypoint.
|
|
39
|
+
* This low-level helper underpins `auth.ctx(...)`.
|
|
43
40
|
*/
|
|
44
41
|
function createAuthContextCustomization(auth, config) {
|
|
45
42
|
return {
|
|
@@ -71,8 +68,10 @@ function createAuthContextCustomization(auth, config) {
|
|
|
71
68
|
};
|
|
72
69
|
}
|
|
73
70
|
/**
|
|
74
|
-
* Build the shared public auth
|
|
71
|
+
* Build the shared public auth context facade used by both `createAuth()` and
|
|
75
72
|
* `createAuthContext()`.
|
|
73
|
+
*
|
|
74
|
+
* @internal
|
|
76
75
|
*/
|
|
77
76
|
function createAuthContextFacade(auth) {
|
|
78
77
|
return {
|
|
@@ -85,5 +84,5 @@ function createAuthContextFacade(auth) {
|
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
//#endregion
|
|
88
|
-
export {
|
|
89
|
-
//# sourceMappingURL=
|
|
87
|
+
export { createAuthContextFacade };
|
|
88
|
+
//# sourceMappingURL=facade.js.map
|
package/dist/server/http.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HttpKeyContext } from "./types.js";
|
|
2
|
-
import { AuthContext, OptionalAuthContext, UserDoc } from "./
|
|
3
|
-
import { ComponentReadCtx } from "./
|
|
2
|
+
import { AuthContext, OptionalAuthContext, UserDoc } from "./facade.js";
|
|
3
|
+
import { ComponentReadCtx } from "./component/context.js";
|
|
4
4
|
import "./auth.js";
|
|
5
5
|
import { GenericActionCtx, GenericDataModel, HttpRouter, UserIdentity } from "convex/server";
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ type HttpIdentityCtx = {
|
|
|
12
12
|
};
|
|
13
13
|
type HttpContextCtx = HttpIdentityCtx & ComponentReadCtx;
|
|
14
14
|
/**
|
|
15
|
-
* Auth context returned by `auth.
|
|
15
|
+
* Auth context returned by `auth.request.context(ctx, request)`.
|
|
16
16
|
*
|
|
17
17
|
* This resolves raw HTTP authentication in two steps:
|
|
18
18
|
* 1. session auth from `ctx.auth.getUserIdentity()`
|
|
@@ -24,7 +24,7 @@ type HttpContextCtx = HttpIdentityCtx & ComponentReadCtx;
|
|
|
24
24
|
*
|
|
25
25
|
* @example
|
|
26
26
|
* ```ts
|
|
27
|
-
* const authContext = await auth.
|
|
27
|
+
* const authContext = await auth.request.context(ctx, request);
|
|
28
28
|
* if (authContext.source === "key") {
|
|
29
29
|
* console.log(authContext.key.keyId);
|
|
30
30
|
* }
|
|
@@ -39,7 +39,7 @@ type HttpAuthContext = (AuthContext & {
|
|
|
39
39
|
});
|
|
40
40
|
/**
|
|
41
41
|
* Nullable HTTP auth context returned by
|
|
42
|
-
* `auth.
|
|
42
|
+
* `auth.request.context(ctx, request, { optional: true })`.
|
|
43
43
|
*
|
|
44
44
|
* This preserves a stable auth-shaped object for raw `httpAction` handlers
|
|
45
45
|
* that allow anonymous callers.
|
|
@@ -49,7 +49,7 @@ type OptionalHttpAuthContext = (OptionalAuthContext & {
|
|
|
49
49
|
key: null;
|
|
50
50
|
}) | HttpAuthContext;
|
|
51
51
|
/**
|
|
52
|
-
* Configuration for {@link createAuth().
|
|
52
|
+
* Configuration for {@link createAuth().request.context}.
|
|
53
53
|
*
|
|
54
54
|
* This mirrors {@link AuthContextConfig} for raw HTTP handlers and adds support
|
|
55
55
|
* for enriching mixed session/API-key auth results.
|
|
@@ -59,7 +59,7 @@ type OptionalHttpAuthContext = (OptionalAuthContext & {
|
|
|
59
59
|
*
|
|
60
60
|
* @example
|
|
61
61
|
* ```ts
|
|
62
|
-
* const authContext = await auth.
|
|
62
|
+
* const authContext = await auth.request.context(ctx, request, {
|
|
63
63
|
* resolve: async (_ctx, user, authState) => ({
|
|
64
64
|
* email: user.email,
|
|
65
65
|
* isMachineRequest: authState.source === "key",
|
package/dist/server/http.js
CHANGED
|
@@ -54,7 +54,7 @@ async function resolveHttpAuthContext(auth, ctx, request) {
|
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
56
|
* @internal
|
|
57
|
-
* Create the implementation behind `auth.
|
|
57
|
+
* Create the implementation behind `auth.request.context(...)`.
|
|
58
58
|
*/
|
|
59
59
|
function createHttpContext(auth) {
|
|
60
60
|
return (async (ctx, request, config) => {
|
|
@@ -230,8 +230,9 @@ function parseConnectionRuntimeRoute(pathname, routeBase) {
|
|
|
230
230
|
}
|
|
231
231
|
function addOpenIdRoutes(http, deps) {
|
|
232
232
|
const cacheControl = "public, max-age=15, stale-while-revalidate=15, stale-if-error=86400";
|
|
233
|
+
const routeBase = deps.routeBase ?? "";
|
|
233
234
|
http.route({
|
|
234
|
-
path:
|
|
235
|
+
path: `${routeBase}/.well-known/openid-configuration`,
|
|
235
236
|
method: "GET",
|
|
236
237
|
handler: httpActionGeneric(async () => {
|
|
237
238
|
const issuer = deps.getIssuer();
|
|
@@ -248,7 +249,7 @@ function addOpenIdRoutes(http, deps) {
|
|
|
248
249
|
})
|
|
249
250
|
});
|
|
250
251
|
http.route({
|
|
251
|
-
path:
|
|
252
|
+
path: `${routeBase}/.well-known/jwks.json`,
|
|
252
253
|
method: "GET",
|
|
253
254
|
handler: httpActionGeneric(async () => {
|
|
254
255
|
return new Response(deps.getJwks(), {
|
|
@@ -261,20 +262,58 @@ function addOpenIdRoutes(http, deps) {
|
|
|
261
262
|
})
|
|
262
263
|
});
|
|
263
264
|
}
|
|
265
|
+
/** Register root `/.well-known/*` app discovery routes on an HTTP router. */
|
|
266
|
+
function addWellKnownRoutes(http, deps) {
|
|
267
|
+
for (const route of [
|
|
268
|
+
{
|
|
269
|
+
endpoint: "apple-app-site-association",
|
|
270
|
+
path: "/.well-known/apple-app-site-association"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
endpoint: "assetlinks.json",
|
|
274
|
+
path: "/.well-known/assetlinks.json"
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
endpoint: "webauthn",
|
|
278
|
+
path: "/.well-known/webauthn"
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
endpoint: "change-password",
|
|
282
|
+
path: "/.well-known/change-password"
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
endpoint: "security.txt",
|
|
286
|
+
path: "/.well-known/security.txt"
|
|
287
|
+
}
|
|
288
|
+
]) http.route({
|
|
289
|
+
path: route.path,
|
|
290
|
+
method: "GET",
|
|
291
|
+
handler: httpActionGeneric(async () => {
|
|
292
|
+
const result = deps.getResponse(route.endpoint);
|
|
293
|
+
if (result === null) return new Response(null, { status: 404 });
|
|
294
|
+
return new Response(result.body, {
|
|
295
|
+
status: result.status,
|
|
296
|
+
headers: result.headers
|
|
297
|
+
});
|
|
298
|
+
})
|
|
299
|
+
});
|
|
300
|
+
}
|
|
264
301
|
function addAuthRoutes(http, deps) {
|
|
302
|
+
const routeBase = deps.routeBase ?? "/api/auth";
|
|
303
|
+
const routePrefix = routeBase === "" ? "" : routeBase;
|
|
265
304
|
http.route({
|
|
266
|
-
pathPrefix:
|
|
305
|
+
pathPrefix: `${routePrefix}/signin/`,
|
|
267
306
|
method: "GET",
|
|
268
307
|
handler: httpActionGeneric(deps.handleSignIn)
|
|
269
308
|
});
|
|
270
309
|
const callbackHandler = httpActionGeneric(deps.handleCallback);
|
|
271
310
|
http.route({
|
|
272
|
-
pathPrefix:
|
|
311
|
+
pathPrefix: `${routePrefix}/callback/`,
|
|
273
312
|
method: "GET",
|
|
274
313
|
handler: callbackHandler
|
|
275
314
|
});
|
|
276
315
|
http.route({
|
|
277
|
-
pathPrefix:
|
|
316
|
+
pathPrefix: `${routePrefix}/callback/`,
|
|
278
317
|
method: "POST",
|
|
279
318
|
handler: callbackHandler
|
|
280
319
|
});
|
|
@@ -332,6 +371,7 @@ function addSSORoutes(http, deps) {
|
|
|
332
371
|
if (route.rest[0] === "acs") return await deps.handleSamlAcs(ctx, request, route);
|
|
333
372
|
if (route.rest[0] === "slo") return await deps.handleSamlSlo(ctx, request, route);
|
|
334
373
|
}
|
|
374
|
+
if (route?.protocol === "oidc" && route.rest.length === 1 && route.rest[0] === "callback") return await deps.handleOidcCallback(ctx, request, route);
|
|
335
375
|
if (route?.protocol === "scim" && route.rest[0] === "v2") return await deps.handleScimRequest(ctx, request);
|
|
336
376
|
throw new ConvexError({
|
|
337
377
|
code: "INVALID_PARAMETERS",
|
|
@@ -363,5 +403,5 @@ function addSSORoutes(http, deps) {
|
|
|
363
403
|
}
|
|
364
404
|
|
|
365
405
|
//#endregion
|
|
366
|
-
export { addAuthRoutes, addOpenIdRoutes, addSSORoutes, convertErrorsToResponse, createHttpAction, createHttpContext, createHttpRoute, getCookies };
|
|
406
|
+
export { addAuthRoutes, addOpenIdRoutes, addSSORoutes, addWellKnownRoutes, convertErrorsToResponse, createHttpAction, createHttpContext, createHttpRoute, getCookies };
|
|
367
407
|
//# sourceMappingURL=http.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GenericId } from "convex/values";
|
|
2
2
|
|
|
3
|
-
//#region src/server/
|
|
3
|
+
//#region src/server/identity/convex.d.ts
|
|
4
4
|
declare module "convex/server" {
|
|
5
5
|
interface UserIdentity {
|
|
6
6
|
/**
|
|
@@ -11,5 +11,5 @@ declare module "convex/server" {
|
|
|
11
11
|
*/
|
|
12
12
|
readonly sid?: GenericId<"Session">;
|
|
13
13
|
}
|
|
14
|
-
} //# sourceMappingURL=
|
|
15
|
-
//# sourceMappingURL=
|
|
14
|
+
} //# sourceMappingURL=convex.d.ts.map
|
|
15
|
+
//# sourceMappingURL=convex.d.ts.map
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AfterCtx, AuthCallbackContext, AuthCallbackProfile, AuthCallbacks, AuthEvent, BeforeCtx, BeforeEvent, BeforeResult } from "./types.js";
|
|
2
|
+
import { AuthConfig, AuthContext, AuthContextConfig, InferAuth, OptionalAuthContext, UserDoc } from "./facade.js";
|
|
3
|
+
import { WellKnownEndpoint, WellKnownOptions, WellKnownResponse, wellKnown } from "./wellknown.js";
|
|
2
4
|
import { HttpAuthContext, HttpAuthContextConfig, OptionalHttpAuthContext } from "./http.js";
|
|
3
5
|
import { AuthApi, AuthApiBase, ConvexAuthResult, InferClientApi, createAuth } from "./auth.js";
|
|
4
|
-
import "./
|
|
6
|
+
import "./identity/convex.js";
|
|
5
7
|
import { CreateAuthGroupSsoOptions, GroupSsoAccessHandler, GroupSsoAccessInput, GroupSsoAccessPermissions, GroupSsoPermission, GroupSsoResolvedAccessHandler, createAuthGroupSso, scim, sso } from "./mounts.js";
|
|
6
8
|
import { AuthCookie, AuthCookieConfig, AuthCookies, RefreshResult, ServerOptions, authCookieNames, parseAuthCookies, serializeAuthCookies, server, shouldProxyAuthAction, structuredAuthCookies } from "./prefetch.js";
|
|
7
|
-
export { type AuthApi, type AuthApiBase, type AuthConfig, type AuthContext, type AuthContextConfig, type AuthCookie, type AuthCookieConfig, type AuthCookies, type ConvexAuthResult, type CreateAuthGroupSsoOptions, type GroupSsoAccessHandler, type GroupSsoAccessInput, type GroupSsoAccessPermissions, type GroupSsoPermission, type GroupSsoResolvedAccessHandler, type HttpAuthContext, type HttpAuthContextConfig, type InferAuth, type InferClientApi, type OptionalAuthContext, type OptionalHttpAuthContext, type RefreshResult, type ServerOptions, type UserDoc, authCookieNames, createAuth, createAuthGroupSso, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies };
|
|
9
|
+
export { type AfterCtx, type AuthApi, type AuthApiBase, type AuthCallbackContext, type AuthCallbackProfile, type AuthCallbacks, type AuthConfig, type AuthContext, type AuthContextConfig, type AuthCookie, type AuthCookieConfig, type AuthCookies, type AuthEvent, type BeforeCtx, type BeforeEvent, type BeforeResult, type ConvexAuthResult, type CreateAuthGroupSsoOptions, type GroupSsoAccessHandler, type GroupSsoAccessInput, type GroupSsoAccessPermissions, type GroupSsoPermission, type GroupSsoResolvedAccessHandler, type HttpAuthContext, type HttpAuthContextConfig, type InferAuth, type InferClientApi, type OptionalAuthContext, type OptionalHttpAuthContext, type RefreshResult, type ServerOptions, type UserDoc, type WellKnownEndpoint, type WellKnownOptions, type WellKnownResponse, authCookieNames, createAuth, createAuthGroupSso, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies, wellKnown };
|
package/dist/server/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import "./
|
|
1
|
+
import "./identity/convex.js";
|
|
2
|
+
import { wellKnown } from "./wellknown.js";
|
|
2
3
|
import { createAuth } from "./auth.js";
|
|
3
4
|
import { createAuthGroupSso, scim, sso } from "./mounts.js";
|
|
4
5
|
import { authCookieNames, parseAuthCookies, serializeAuthCookies, server, shouldProxyAuthAction, structuredAuthCookies } from "./prefetch.js";
|
|
5
6
|
|
|
6
|
-
export { authCookieNames, createAuth, createAuthGroupSso, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies };
|
|
7
|
+
export { authCookieNames, createAuth, createAuthGroupSso, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies, wellKnown };
|