@robelest/convex-auth 0.0.4-preview.29 → 0.0.4-preview.30
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 +34 -1
- package/dist/browser/passkey.js +2 -2
- package/dist/client/core/types.d.ts +4 -15
- package/dist/client/factors/device.js +3 -3
- package/dist/client/factors/totp.js +8 -8
- package/dist/client/index.js +7 -7
- package/dist/component/convex.config.d.ts +2 -2
- package/dist/component/model.d.ts +25 -25
- package/dist/component/schema.d.ts +289 -289
- package/dist/core/index.d.ts +5 -24
- package/dist/core/index.js +3 -16
- package/dist/server/auth-context.d.ts +1 -1
- package/dist/server/auth-context.js +14 -1
- package/dist/server/auth.d.ts +3 -17
- package/dist/server/auth.js +2 -7
- package/dist/server/config.js +10 -0
- package/dist/server/context.js +2 -4
- package/dist/server/contract.d.ts +1 -1
- package/dist/server/convexIdentity.d.ts +15 -0
- package/dist/server/convexIdentity.js +1 -0
- package/dist/server/core.js +0 -13
- package/dist/server/device.js +13 -12
- package/dist/server/env.js +10 -2
- package/dist/server/http.d.ts +1 -1
- package/dist/server/identity.js +30 -4
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/mounts.d.ts +79 -79
- package/dist/server/mutations/refresh.js +38 -7
- package/dist/server/mutations/signin.js +12 -2
- package/dist/server/mutations/signout.js +27 -10
- package/dist/server/mutations/store.js +1 -1
- package/dist/server/oauth/factory.js +2 -1
- package/dist/server/passkey.js +12 -13
- package/dist/server/prefetch.js +8 -8
- package/dist/server/runtime.d.ts +19 -25
- package/dist/server/runtime.js +7 -40
- package/dist/server/sessions.d.ts +2 -1
- package/dist/server/sessions.js +21 -11
- package/dist/server/signin.js +17 -16
- package/dist/server/sso/domain.d.ts +1 -1
- package/dist/server/telemetry.js +58 -0
- package/dist/server/tokens.js +24 -4
- package/dist/server/totp.js +13 -11
- package/dist/server/types.d.ts +58 -2
- package/dist/server/utils/span.js +10 -1
- package/dist/shared/authResults.d.ts +16 -0
- package/package.json +6 -3
- package/dist/server/constants.js +0 -6
package/dist/server/signin.js
CHANGED
|
@@ -36,7 +36,11 @@ const describeUnknown = (value) => {
|
|
|
36
36
|
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || value === null) return String(value);
|
|
37
37
|
return JSON.stringify(value) ?? Object.prototype.toString.call(value);
|
|
38
38
|
};
|
|
39
|
-
const asConvexError = (error, code, message) =>
|
|
39
|
+
const asConvexError = (error, code, message) => {
|
|
40
|
+
if (error instanceof ConvexError) return error;
|
|
41
|
+
if (error instanceof Error) return toConvexError(authFlowError(code, error.message || message));
|
|
42
|
+
return toConvexError(authFlowError(code, `${message} ${describeUnknown(error)}`.trim()));
|
|
43
|
+
};
|
|
40
44
|
const asCredentialsError = (error) => {
|
|
41
45
|
if (error instanceof ConvexError) return error;
|
|
42
46
|
if (error instanceof Error) return new ConvexError({
|
|
@@ -55,14 +59,14 @@ async function signInFx(ctx, provider, args, options) {
|
|
|
55
59
|
hasRefreshToken: args.refreshToken !== void 0
|
|
56
60
|
}, async () => {
|
|
57
61
|
if (provider === null && args.refreshToken) try {
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
62
|
+
const session = await callRefreshSession(ctx, { refreshToken: args.refreshToken });
|
|
63
|
+
if (session === null) return {
|
|
60
64
|
kind: "signedIn",
|
|
61
|
-
|
|
65
|
+
session: null
|
|
62
66
|
};
|
|
63
67
|
return {
|
|
64
|
-
kind: "
|
|
65
|
-
|
|
68
|
+
kind: "signedIn",
|
|
69
|
+
session
|
|
66
70
|
};
|
|
67
71
|
} catch (error) {
|
|
68
72
|
throw asConvexError(error, "INTERNAL_ERROR", "Failed to refresh session.");
|
|
@@ -70,7 +74,7 @@ async function signInFx(ctx, provider, args, options) {
|
|
|
70
74
|
if (provider === null && args.params?.code !== void 0) try {
|
|
71
75
|
return {
|
|
72
76
|
kind: "signedIn",
|
|
73
|
-
|
|
77
|
+
session: await callVerifyCodeAndSignIn(ctx, {
|
|
74
78
|
params: args.params,
|
|
75
79
|
verifier: args.verifier,
|
|
76
80
|
generateTokens: true,
|
|
@@ -114,7 +118,7 @@ async function handleEmailAndPhoneProviderFx(ctx, provider, args, options) {
|
|
|
114
118
|
if (result === null) throw toConvexError(authFlowError("INVALID_VERIFICATION_CODE", "Invalid or expired verification code."));
|
|
115
119
|
return {
|
|
116
120
|
kind: "signedIn",
|
|
117
|
-
|
|
121
|
+
session: result
|
|
118
122
|
};
|
|
119
123
|
}
|
|
120
124
|
const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
@@ -169,10 +173,7 @@ async function handleEmailAndPhoneProviderFx(ctx, provider, args, options) {
|
|
|
169
173
|
} catch {
|
|
170
174
|
throw toConvexError(authFlowError("INTERNAL_ERROR", "Failed to send phone code"));
|
|
171
175
|
}
|
|
172
|
-
return {
|
|
173
|
-
kind: "started",
|
|
174
|
-
started: true
|
|
175
|
-
};
|
|
176
|
+
return { kind: "started" };
|
|
176
177
|
});
|
|
177
178
|
}
|
|
178
179
|
async function handleCredentialsFx(ctx, provider, args, options) {
|
|
@@ -185,7 +186,7 @@ async function handleCredentialsFx(ctx, provider, args, options) {
|
|
|
185
186
|
}
|
|
186
187
|
if (result === null) return {
|
|
187
188
|
kind: "signedIn",
|
|
188
|
-
|
|
189
|
+
session: null
|
|
189
190
|
};
|
|
190
191
|
const hintedHasTotp = result.hasTotp;
|
|
191
192
|
const preIssuedIssuance = result.issuance;
|
|
@@ -225,7 +226,7 @@ async function handleCredentialsFx(ctx, provider, args, options) {
|
|
|
225
226
|
if (preIssuedIssuance !== void 0) try {
|
|
226
227
|
return {
|
|
227
228
|
kind: "signedIn",
|
|
228
|
-
|
|
229
|
+
session: await withSpan("convex-auth.signin.credentials.finalize", {
|
|
229
230
|
generateTokens: options.generateTokens,
|
|
230
231
|
fromAuthorize: true
|
|
231
232
|
}, () => finalizeSessionIssuance(ctx.auth.config, {
|
|
@@ -248,7 +249,7 @@ async function handleCredentialsFx(ctx, provider, args, options) {
|
|
|
248
249
|
}
|
|
249
250
|
return {
|
|
250
251
|
kind: "signedIn",
|
|
251
|
-
|
|
252
|
+
session: idsAndTokens
|
|
252
253
|
};
|
|
253
254
|
});
|
|
254
255
|
}
|
|
@@ -268,7 +269,7 @@ async function handleOAuthProviderFx(ctx, provider, args, options) {
|
|
|
268
269
|
}
|
|
269
270
|
return {
|
|
270
271
|
kind: "signedIn",
|
|
271
|
-
|
|
272
|
+
session: result
|
|
272
273
|
};
|
|
273
274
|
}
|
|
274
275
|
const redirect = new URL((readConfigSync(envOptionalString("CUSTOM_AUTH_SITE_URL")) ?? requireEnv("CONVEX_SITE_URL")) + `/api/auth/signin/${provider.id}`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ComponentCtx, ComponentReadCtx } from "../componentContext.js";
|
|
2
1
|
import { ConvexAuthMaterializedConfig, GroupConnectionDeprovisionMode, GroupConnectionPolicy, GroupConnectionPolicyPatch, OIDCClaimMapping } from "../types.js";
|
|
2
|
+
import { ComponentCtx, ComponentReadCtx } from "../componentContext.js";
|
|
3
3
|
import { AuditEventRecord, ConnectionDomainRecord, GroupConnectionDomainLookupRecord, GroupConnectionListResult, GroupConnectionRecord, ScimConfigRecord, ScimIdentityRecord, WebhookDeliveryRecord, WebhookEndpointRecord } from "../contract.js";
|
|
4
4
|
import { GenericActionCtx, GenericDataModel } from "convex/server";
|
|
5
5
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { authDb } from "./db.js";
|
|
2
|
+
import { envOptionalString, readConfigSync } from "./env.js";
|
|
3
|
+
|
|
4
|
+
//#region src/server/telemetry.ts
|
|
5
|
+
function tokenIdentifierForUser(userId) {
|
|
6
|
+
const issuer = readConfigSync(envOptionalString("CONVEX_SITE_URL"));
|
|
7
|
+
return typeof issuer === "string" && issuer.length > 0 ? `${userId}${issuer}` : userId;
|
|
8
|
+
}
|
|
9
|
+
const AUTH_IDENTITY_ATTRIBUTE_KEYS = {
|
|
10
|
+
userId: "auth.user.id",
|
|
11
|
+
sessionId: "auth.session.id",
|
|
12
|
+
refreshTokenId: "auth.refresh_token.id",
|
|
13
|
+
email: "auth.user.email",
|
|
14
|
+
tokenIdentifier: "auth.token_identifier"
|
|
15
|
+
};
|
|
16
|
+
function projectIdentityValue(config, field, value) {
|
|
17
|
+
if (value === void 0) return;
|
|
18
|
+
const mode = config.telemetry?.includeIdentity ?? "none";
|
|
19
|
+
if (mode === "none") return;
|
|
20
|
+
if (mode === "hashed") return config.telemetry?.hashIdentity?.(value, field);
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
async function buildAuthIdentityAttributes(ctx, config, args) {
|
|
24
|
+
const fields = config.telemetry?.identityFields ?? {};
|
|
25
|
+
const mode = config.telemetry?.includeIdentity ?? "none";
|
|
26
|
+
if (mode === "none") return {};
|
|
27
|
+
const values = {
|
|
28
|
+
userId: args.userId,
|
|
29
|
+
sessionId: args.sessionId,
|
|
30
|
+
tokenIdentifier: tokenIdentifierForUser(args.userId)
|
|
31
|
+
};
|
|
32
|
+
if (args.refreshTokenId !== void 0) values.refreshTokenId = args.refreshTokenId;
|
|
33
|
+
if (fields.email) {
|
|
34
|
+
const user = await authDb(ctx, config).users.getById(args.userId);
|
|
35
|
+
if (typeof user?.email === "string") values.email = user.email;
|
|
36
|
+
}
|
|
37
|
+
const attributes = {};
|
|
38
|
+
for (const field of Object.keys(fields)) {
|
|
39
|
+
if (!fields[field]) continue;
|
|
40
|
+
const projected = projectIdentityValue(config, field, values[field]);
|
|
41
|
+
if (projected !== void 0) attributes[AUTH_IDENTITY_ATTRIBUTE_KEYS[field]] = projected;
|
|
42
|
+
}
|
|
43
|
+
if (Object.keys(attributes).length > 0) attributes["auth.identity.mode"] = mode;
|
|
44
|
+
return attributes;
|
|
45
|
+
}
|
|
46
|
+
async function buildRefreshIdentityAttributes(ctx, config, args) {
|
|
47
|
+
return await buildAuthIdentityAttributes(ctx, config, args);
|
|
48
|
+
}
|
|
49
|
+
async function buildSignInIdentityAttributes(ctx, config, args) {
|
|
50
|
+
return await buildAuthIdentityAttributes(ctx, config, args);
|
|
51
|
+
}
|
|
52
|
+
async function buildSignOutIdentityAttributes(ctx, config, args) {
|
|
53
|
+
return await buildAuthIdentityAttributes(ctx, config, args);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
export { buildRefreshIdentityAttributes, buildSignInIdentityAttributes, buildSignOutIdentityAttributes };
|
|
58
|
+
//# sourceMappingURL=telemetry.js.map
|
package/dist/server/tokens.js
CHANGED
|
@@ -4,16 +4,26 @@ import { withSpan } from "./utils/span.js";
|
|
|
4
4
|
import { SignJWT, importPKCS8 } from "jose";
|
|
5
5
|
|
|
6
6
|
//#region src/server/tokens.ts
|
|
7
|
-
const TOKEN_SUB_CLAIM_DIVIDER = "|";
|
|
8
7
|
const DEFAULT_JWT_DURATION_MS = 1e3 * 60 * 60;
|
|
9
8
|
const TOKEN_JTI_LENGTH = 24;
|
|
10
9
|
const TOKEN_JTI_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
11
10
|
let cachedPrivateKeyPromise = null;
|
|
12
11
|
let cachedIssuer = null;
|
|
13
12
|
const JWT_ALG = "EdDSA";
|
|
13
|
+
function normalizePkcs8Pem(value) {
|
|
14
|
+
const trimmed = value.trim();
|
|
15
|
+
if (!trimmed.includes("-----BEGIN PRIVATE KEY-----")) return trimmed;
|
|
16
|
+
const withEscapedNewlines = trimmed.replace(/\\n/g, "\n");
|
|
17
|
+
if (withEscapedNewlines.includes("\n")) return withEscapedNewlines;
|
|
18
|
+
const beginMarker = "-----BEGIN PRIVATE KEY-----";
|
|
19
|
+
const endMarker = "-----END PRIVATE KEY-----";
|
|
20
|
+
const body = trimmed.replace(beginMarker, "").replace(endMarker, "").trim().replace(/\s+/g, "");
|
|
21
|
+
if (body.length === 0) return trimmed;
|
|
22
|
+
return `${beginMarker}\n${body.match(/.{1,64}/g)?.join("\n") ?? body}\n${endMarker}`;
|
|
23
|
+
}
|
|
14
24
|
const getPrivateKey = () => {
|
|
15
25
|
if (cachedPrivateKeyPromise === null) try {
|
|
16
|
-
cachedPrivateKeyPromise = importPKCS8(requireEnv("JWT_PRIVATE_KEY"), JWT_ALG).catch((error) => {
|
|
26
|
+
cachedPrivateKeyPromise = importPKCS8(normalizePkcs8Pem(requireEnv("JWT_PRIVATE_KEY")), JWT_ALG).catch((error) => {
|
|
17
27
|
cachedPrivateKeyPromise = null;
|
|
18
28
|
throw error;
|
|
19
29
|
});
|
|
@@ -37,9 +47,19 @@ try {
|
|
|
37
47
|
async function generateToken(args, config) {
|
|
38
48
|
const privateKey = await withSpan("convex-auth.tokens.import-key", { alg: JWT_ALG }, () => getPrivateKey());
|
|
39
49
|
const expirationTime = new Date(Date.now() + (config.jwt?.durationMs ?? DEFAULT_JWT_DURATION_MS));
|
|
40
|
-
|
|
50
|
+
const claims = {
|
|
51
|
+
sub: args.identity.subject,
|
|
52
|
+
sid: args.identity.sessionId,
|
|
53
|
+
...args.identity.name !== void 0 ? { name: args.identity.name } : null,
|
|
54
|
+
...args.identity.email !== void 0 ? { email: args.identity.email } : null,
|
|
55
|
+
...args.identity.emailVerified !== void 0 ? { email_verified: args.identity.emailVerified } : null,
|
|
56
|
+
...args.identity.picture !== void 0 ? { picture: args.identity.picture } : null,
|
|
57
|
+
...args.identity.phoneNumber !== void 0 ? { phone_number: args.identity.phoneNumber } : null,
|
|
58
|
+
...args.identity.phoneNumberVerified !== void 0 ? { phone_number_verified: args.identity.phoneNumberVerified } : null
|
|
59
|
+
};
|
|
60
|
+
return await withSpan("convex-auth.tokens.sign", { alg: JWT_ALG }, () => new SignJWT(claims).setProtectedHeader({ alg: JWT_ALG }).setIssuedAt().setJti(generateRandomString(TOKEN_JTI_LENGTH, TOKEN_JTI_ALPHABET)).setIssuer(getIssuer()).setAudience("convex").setExpirationTime(expirationTime).sign(privateKey));
|
|
41
61
|
}
|
|
42
62
|
|
|
43
63
|
//#endregion
|
|
44
|
-
export {
|
|
64
|
+
export { generateToken };
|
|
45
65
|
//# sourceMappingURL=tokens.js.map
|
package/dist/server/totp.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getAuthenticatedUserIdOrNull } from "./identity.js";
|
|
2
2
|
import { callSignIn } from "./mutations/signin.js";
|
|
3
3
|
import { callVerifier } from "./mutations/verifier.js";
|
|
4
4
|
import { authFlowError } from "../shared/errors.js";
|
|
@@ -64,14 +64,14 @@ function resolveTotpDispatch(params, verifier) {
|
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
async function requireAuthenticatedUserId(ctx) {
|
|
67
|
-
let identity;
|
|
68
67
|
try {
|
|
69
|
-
|
|
68
|
+
const userId = await getAuthenticatedUserIdOrNull(ctx);
|
|
69
|
+
if (userId === null) throw convexError("TOTP_AUTH_REQUIRED", "Sign in first, then set up two-factor authentication.");
|
|
70
|
+
return userId;
|
|
70
71
|
} catch (error) {
|
|
72
|
+
if (error instanceof ConvexError) throw error;
|
|
71
73
|
throw asConvexError(error, "INTERNAL_ERROR", String(error));
|
|
72
74
|
}
|
|
73
|
-
if (identity === null) throw convexError("TOTP_AUTH_REQUIRED", "Sign in first, then set up two-factor authentication.");
|
|
74
|
-
return userIdFromIdentitySubject(identity.subject);
|
|
75
75
|
}
|
|
76
76
|
/** @internal */
|
|
77
77
|
const handleTotp = async (ctx, provider, args) => {
|
|
@@ -121,10 +121,12 @@ const handleTotp = async (ctx, provider, args) => {
|
|
|
121
121
|
}
|
|
122
122
|
return {
|
|
123
123
|
kind: "totpSetup",
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
totpSetup: {
|
|
125
|
+
uri,
|
|
126
|
+
secret: base32Secret,
|
|
127
|
+
totpId
|
|
128
|
+
},
|
|
129
|
+
verifier
|
|
128
130
|
};
|
|
129
131
|
},
|
|
130
132
|
confirm: async () => {
|
|
@@ -152,7 +154,7 @@ const handleTotp = async (ctx, provider, args) => {
|
|
|
152
154
|
}
|
|
153
155
|
return {
|
|
154
156
|
kind: "signedIn",
|
|
155
|
-
|
|
157
|
+
session: signInResult
|
|
156
158
|
};
|
|
157
159
|
},
|
|
158
160
|
verify: async () => {
|
|
@@ -186,7 +188,7 @@ const handleTotp = async (ctx, provider, args) => {
|
|
|
186
188
|
}
|
|
187
189
|
return {
|
|
188
190
|
kind: "signedIn",
|
|
189
|
-
|
|
191
|
+
session: signInResult
|
|
190
192
|
};
|
|
191
193
|
}
|
|
192
194
|
}[dispatch.flow];
|
package/dist/server/types.d.ts
CHANGED
|
@@ -35,6 +35,44 @@ type AuthRoleDefinition = {
|
|
|
35
35
|
type AuthAuthorizationConfig = {
|
|
36
36
|
roles: Record<string, AuthRoleDefinition>;
|
|
37
37
|
};
|
|
38
|
+
/** Identity enrichment mode for auth telemetry spans. */
|
|
39
|
+
type AuthTelemetryIdentityMode = "none" | "hashed" | "raw";
|
|
40
|
+
/** Individual identity fields that can be attached to telemetry spans. */
|
|
41
|
+
type AuthTelemetryIdentityFields = {
|
|
42
|
+
userId?: boolean;
|
|
43
|
+
sessionId?: boolean;
|
|
44
|
+
refreshTokenId?: boolean;
|
|
45
|
+
email?: boolean;
|
|
46
|
+
tokenIdentifier?: boolean;
|
|
47
|
+
};
|
|
48
|
+
/** Names of identity fields that can be attached to telemetry spans. */
|
|
49
|
+
type AuthTelemetryIdentityField = keyof AuthTelemetryIdentityFields;
|
|
50
|
+
/**
|
|
51
|
+
* Telemetry enrichment config for auth spans.
|
|
52
|
+
*
|
|
53
|
+
* Defaults to privacy-safe behavior with no identity fields attached.
|
|
54
|
+
*/
|
|
55
|
+
type AuthTelemetryConfig = {
|
|
56
|
+
/**
|
|
57
|
+
* Whether to include no identity values, hashed values, or raw values.
|
|
58
|
+
*
|
|
59
|
+
* @defaultValue "none"
|
|
60
|
+
*/
|
|
61
|
+
includeIdentity?: AuthTelemetryIdentityMode;
|
|
62
|
+
/**
|
|
63
|
+
* Opt-in identity fields to attach to telemetry spans.
|
|
64
|
+
*
|
|
65
|
+
* Ignored when `includeIdentity` is `"none"`.
|
|
66
|
+
*/
|
|
67
|
+
identityFields?: AuthTelemetryIdentityFields;
|
|
68
|
+
/**
|
|
69
|
+
* Required when `includeIdentity` is `"hashed"`.
|
|
70
|
+
*
|
|
71
|
+
* Use this to provide an application-defined hashing strategy for
|
|
72
|
+
* correlating auth spans without exposing raw identifiers.
|
|
73
|
+
*/
|
|
74
|
+
hashIdentity?: (value: string, field: AuthTelemetryIdentityField) => string;
|
|
75
|
+
};
|
|
38
76
|
/**
|
|
39
77
|
* Extracts the union of role ID strings from an authorization config.
|
|
40
78
|
*
|
|
@@ -315,6 +353,13 @@ type ConvexAuthConfig = {
|
|
|
315
353
|
grants: string[];
|
|
316
354
|
}>;
|
|
317
355
|
};
|
|
356
|
+
/**
|
|
357
|
+
* Optional OpenTelemetry enrichment for auth spans.
|
|
358
|
+
*
|
|
359
|
+
* Defaults to no identity attributes. Set `includeIdentity` to `"hashed"`
|
|
360
|
+
* or `"raw"` to opt into richer correlation.
|
|
361
|
+
*/
|
|
362
|
+
telemetry?: AuthTelemetryConfig;
|
|
318
363
|
};
|
|
319
364
|
/**
|
|
320
365
|
* Union of all supported auth provider config types.
|
|
@@ -841,7 +886,7 @@ type GenericActionCtxWithAuthConfig<DataModel extends GenericDataModel> = Generi
|
|
|
841
886
|
*/
|
|
842
887
|
type ConvexAuthMaterializedConfig = {
|
|
843
888
|
providers: AuthProviderMaterializedConfig[];
|
|
844
|
-
} & Pick<ConvexAuthConfig, "component" | "session" | "jwt" | "signIn" | "callbacks" | "authorization" | "sso">;
|
|
889
|
+
} & Pick<ConvexAuthConfig, "component" | "session" | "jwt" | "signIn" | "callbacks" | "authorization" | "sso" | "telemetry">;
|
|
845
890
|
interface SSOProfileMapping {
|
|
846
891
|
subject?: string;
|
|
847
892
|
email?: string;
|
|
@@ -1155,7 +1200,18 @@ type GenericDoc<DataModel extends GenericDataModel, TableName extends TableNames
|
|
|
1155
1200
|
type AuthDataModel = DataModelFromSchemaDefinition<typeof _default>;
|
|
1156
1201
|
/** A document from any table in the auth component schema. */
|
|
1157
1202
|
type Doc<T extends TableNamesInDataModel<AuthDataModel>> = GenericDoc<AuthDataModel, T>;
|
|
1203
|
+
/** Canonical identity claims mirrored into access tokens for Convex auth. */
|
|
1204
|
+
type SessionTokenIdentityClaims = {
|
|
1205
|
+
subject: GenericId<"User">;
|
|
1206
|
+
sessionId: GenericId<"Session">;
|
|
1207
|
+
name?: string;
|
|
1208
|
+
email?: string;
|
|
1209
|
+
emailVerified?: boolean;
|
|
1210
|
+
picture?: string;
|
|
1211
|
+
phoneNumber?: string;
|
|
1212
|
+
phoneNumberVerified?: boolean;
|
|
1213
|
+
};
|
|
1158
1214
|
type KeyDoc = Infer<typeof vApiKeyDoc>;
|
|
1159
1215
|
//#endregion
|
|
1160
|
-
export { AuthAuthorizationConfig, AuthGrant, AuthProviderConfig, AuthRoleId, ConvexAuthConfig, ConvexAuthMaterializedConfig, ConvexCredentialsConfig, CorsConfig, DeviceProviderConfig, Doc, EmailConfig, EmailUserConfig, GenericActionCtxWithAuthConfig, GenericDoc, GroupConnectionDeprovisionMode, GroupConnectionPolicy, GroupConnectionPolicyPatch, HasDeviceProvider, HasPasskeyProvider, HasSSO, HasTotpProvider, HttpKeyContext, KeyDoc, KeyScope, OAuthMaterializedConfig, OAuthProfile, OAuthTokens, OIDCClaimMapping, PasskeyProviderConfig, PhoneConfig, PhoneUserConfig, SSOProviderConfig, ScopeChecker, TotpProviderConfig, UserOrderBy, UserWhere };
|
|
1216
|
+
export { AuthAuthorizationConfig, AuthGrant, AuthProviderConfig, AuthRoleId, ConvexAuthConfig, ConvexAuthMaterializedConfig, ConvexCredentialsConfig, CorsConfig, DeviceProviderConfig, Doc, EmailConfig, EmailUserConfig, GenericActionCtxWithAuthConfig, GenericDoc, GroupConnectionDeprovisionMode, GroupConnectionPolicy, GroupConnectionPolicyPatch, HasDeviceProvider, HasPasskeyProvider, HasSSO, HasTotpProvider, HttpKeyContext, KeyDoc, KeyScope, OAuthMaterializedConfig, OAuthProfile, OAuthTokens, OIDCClaimMapping, PasskeyProviderConfig, PhoneConfig, PhoneUserConfig, SSOProviderConfig, ScopeChecker, SessionTokenIdentityClaims, TotpProviderConfig, UserOrderBy, UserWhere };
|
|
1161
1217
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -44,7 +44,16 @@ async function withSpan(name, attributes, fn) {
|
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Attach attributes to the current active span when tracing is enabled.
|
|
49
|
+
*/
|
|
50
|
+
function setActiveSpanAttributes(attributes) {
|
|
51
|
+
if (!isTracingActive()) return;
|
|
52
|
+
const span = trace.getActiveSpan();
|
|
53
|
+
if (!span) return;
|
|
54
|
+
for (const [key, value] of Object.entries(attributes)) if (value !== void 0) span.setAttribute(key, value);
|
|
55
|
+
}
|
|
47
56
|
|
|
48
57
|
//#endregion
|
|
49
|
-
export { withSpan };
|
|
58
|
+
export { setActiveSpanAttributes, withSpan };
|
|
50
59
|
//# sourceMappingURL=span.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/shared/authResults.d.ts
|
|
2
|
+
type AuthTokens = {
|
|
3
|
+
token: string;
|
|
4
|
+
refreshToken: string;
|
|
5
|
+
};
|
|
6
|
+
type DeviceCodePayload = {
|
|
7
|
+
deviceCode: string;
|
|
8
|
+
userCode: string;
|
|
9
|
+
verificationUri: string;
|
|
10
|
+
verificationUriComplete: string;
|
|
11
|
+
expiresIn: number;
|
|
12
|
+
interval: number;
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { AuthTokens, DeviceCodePayload };
|
|
16
|
+
//# sourceMappingURL=authResults.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robelest/convex-auth",
|
|
3
|
-
"version": "0.0.4-preview.
|
|
3
|
+
"version": "0.0.4-preview.30",
|
|
4
4
|
"description": "Authentication for Convex",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"auth",
|
|
@@ -27,7 +27,10 @@
|
|
|
27
27
|
"!dist/schema.d.ts.map"
|
|
28
28
|
],
|
|
29
29
|
"type": "module",
|
|
30
|
-
"sideEffects":
|
|
30
|
+
"sideEffects": [
|
|
31
|
+
"./src/server/convexIdentity.ts",
|
|
32
|
+
"./dist/server/convexIdentity.js"
|
|
33
|
+
],
|
|
31
34
|
"exports": {
|
|
32
35
|
"./_generated/component.js": {
|
|
33
36
|
"types": "./dist/component/_generated/component.d.ts"
|
|
@@ -118,7 +121,7 @@
|
|
|
118
121
|
"@oslojs/encoding": "^1.1.0",
|
|
119
122
|
"@oslojs/otp": "^1.1.0",
|
|
120
123
|
"@oslojs/webauthn": "^1.0.0",
|
|
121
|
-
"@robelest/samlify": "
|
|
124
|
+
"@robelest/samlify": "^0.0.1-preview.2",
|
|
122
125
|
"arctic": "^3.7.0",
|
|
123
126
|
"cookie": "^1.1.1",
|
|
124
127
|
"fluent-convex": "^0.12.3",
|