@absolutejs/auth 0.27.0-beta.1 → 0.27.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ export type AbuseAction = 'allow' | 'challenge' | 'deny';
2
+ export type AbuseSignal = 'blocked_ip' | 'bot' | 'captcha_failed' | 'not_allowlisted';
3
+ export type BotClass = 'agent' | 'bot' | 'crawler' | 'human';
4
+ export type AbuseContext = {
5
+ captchaToken?: string;
6
+ ip?: string;
7
+ userAgent?: string;
8
+ };
9
+ export type AbuseReason = {
10
+ action: AbuseAction;
11
+ signal: AbuseSignal;
12
+ };
13
+ export type AbuseAssessment = {
14
+ action: AbuseAction;
15
+ reasons: AbuseReason[];
16
+ };
17
+ export type AbuseConfig = {
18
+ botAction?: AbuseAction;
19
+ captchaAction?: AbuseAction;
20
+ classifyBot?: (context: AbuseContext) => BotClass | Promise<BotClass>;
21
+ ipAllow?: string[];
22
+ ipDeny?: string[];
23
+ verifyCaptcha?: (token: string | undefined, context: AbuseContext) => boolean | Promise<boolean>;
24
+ };
25
+ export declare const assessAbuse: (config: AbuseConfig, context: AbuseContext) => Promise<AbuseAssessment>;
26
+ export declare const createAbuseGuard: (config: AbuseConfig) => {
27
+ assess: (context: AbuseContext) => Promise<AbuseAssessment>;
28
+ };
29
+ export declare const defaultBotClassifier: (context: AbuseContext) => "bot" | "crawler" | "human";
@@ -0,0 +1,15 @@
1
+ import type { AuditEvent, AuditSink } from './types';
2
+ export type AuditIntegrity = {
3
+ hash: string;
4
+ previousHash: string;
5
+ };
6
+ export type AuditChainResult = {
7
+ brokenAt?: number;
8
+ ok: boolean;
9
+ };
10
+ export declare const createTamperEvidentSink: ({ secret, sink }: {
11
+ secret?: string;
12
+ sink: AuditSink;
13
+ }) => AuditSink;
14
+ export declare const hashAuditEvent: (event: AuditEvent, previousHash: string, secret?: string) => Promise<string>;
15
+ export declare const verifyAuditChain: (events: AuditEvent[], secret?: string) => Promise<AuditChainResult>;
@@ -0,0 +1,11 @@
1
+ import type { AuditSink } from './types';
2
+ export type SiemFormat = 'datadog' | 'generic' | 'splunk';
3
+ export type SiemEndpoint = {
4
+ format?: SiemFormat;
5
+ headers?: Record<string, string>;
6
+ token?: string;
7
+ url: string;
8
+ };
9
+ export declare const createSiemLogStream: ({ endpoints }: {
10
+ endpoints: SiemEndpoint[];
11
+ }) => AuditSink;
@@ -1,5 +1,5 @@
1
1
  import type { OrganizationId } from '../tenancy';
2
- export type AuditEventType = 'account_deleted' | 'authorization_denied' | 'credentials_login' | 'credentials_login_failed' | 'data_exported' | 'email_verified' | 'identity_conflict' | 'invitation_accepted' | 'invitation_created' | 'logout' | 'membership_removed' | 'mfa_challenge' | 'mfa_challenge_failed' | 'mfa_enrolled' | 'oauth_login' | 'organization_created' | 'password_reset' | 'passwordless_login' | 'register' | 'role_assigned' | 'scim_provision' | 'scim_token_created' | 'session_revoked' | 'setup_session_created' | 'sso_connection_configured' | 'sso_login' | 'token_refreshed' | 'token_revoked' | 'webauthn_authenticated' | 'webauthn_registered';
2
+ export type AuditEventType = 'account_deleted' | 'authorization_denied' | 'credentials_login' | 'credentials_login_failed' | 'data_exported' | 'email_verified' | 'identity_conflict' | 'impersonation_ended' | 'impersonation_started' | 'invitation_accepted' | 'invitation_created' | 'logout' | 'membership_removed' | 'mfa_challenge' | 'mfa_challenge_failed' | 'mfa_enrolled' | 'oauth_login' | 'organization_created' | 'password_reset' | 'passwordless_login' | 'register' | 'role_assigned' | 'scim_provision' | 'scim_token_created' | 'session_revoked' | 'setup_session_created' | 'sso_connection_configured' | 'sso_login' | 'token_refreshed' | 'token_revoked' | 'webauthn_authenticated' | 'webauthn_registered';
3
3
  export type AuditEvent = {
4
4
  at: number;
5
5
  ip?: string;
package/dist/index.d.ts CHANGED
@@ -8407,6 +8407,7 @@ export { protectRoutePlugin } from './routes/protectRoute';
8407
8407
  export { sessionRoutes } from './routes/sessions';
8408
8408
  export { stepUpPlugin } from './routes/stepUp';
8409
8409
  export * from './session/sessionsConfig';
8410
+ export { endImpersonation, isImpersonating, startImpersonation } from './session/impersonation';
8410
8411
  export { listUserSessions, revokeUserSessions } from './session/userSessions';
8411
8412
  export type { UserSession } from './session/userSessions';
8412
8413
  export { sessionCleanup } from './session/cleanup';
@@ -8437,12 +8438,19 @@ export { consumeBackupCode, generateBackupCodes } from './mfa/backupCodes';
8437
8438
  export { createMfaGate } from './mfa/gate';
8438
8439
  export { mfaChallenge } from './mfa/challenge';
8439
8440
  export { mfaRoutes } from './mfa/routes';
8441
+ export { rotateMfaEncryptionKey } from './mfa/rotation';
8442
+ export type { MfaKeyRotationResult } from './mfa/rotation';
8440
8443
  export { mfaTotpRoutes } from './mfa/totp';
8441
8444
  export { decryptTotpSecret, encryptTotpSecret } from './mfa/secret';
8442
8445
  export { createInMemoryMfaStore } from './mfa/inMemoryMfaStore';
8443
8446
  export { createNeonMfaStore, createPostgresMfaStore, mfaEnrollmentsTable } from './mfa/postgresMfaStore';
8444
8447
  export * from './audit/config';
8445
8448
  export * from './audit/types';
8449
+ export { createTamperEvidentSink, hashAuditEvent, verifyAuditChain } from './audit/integrity';
8450
+ export type { AuditChainResult, AuditIntegrity } from './audit/integrity';
8451
+ export { createSiemLogStream } from './audit/siem';
8452
+ export type { SiemEndpoint, SiemFormat } from './audit/siem';
8453
+ export * from './abuse/config';
8446
8454
  export * from './authorization/config';
8447
8455
  export { protectPermissionPlugin } from './authorization/protectPermission';
8448
8456
  export * from './compliance/config';
package/dist/index.js CHANGED
@@ -3215,6 +3215,7 @@ var persistWhen = async (shouldPersist, persist) => {
3215
3215
  var promoteToSession = async ({
3216
3216
  authSessionStore,
3217
3217
  cookie,
3218
+ impersonator,
3218
3219
  inMemorySession,
3219
3220
  samlLogout,
3220
3221
  sessionDurationMs,
@@ -3233,6 +3234,8 @@ var promoteToSession = async ({
3233
3234
  };
3234
3235
  if (samlLogout !== undefined)
3235
3236
  data.samlLogout = samlLogout;
3237
+ if (impersonator !== undefined)
3238
+ data.impersonator = impersonator;
3236
3239
  targetSession[userSessionId] = data;
3237
3240
  cookie.set({
3238
3241
  httpOnly: true,
@@ -17531,6 +17534,85 @@ var createInMemoryLinkedProviderStores = (input = {}) => {
17531
17534
  };
17532
17535
  return { bindingStore, grantStore };
17533
17536
  };
17537
+ // src/session/impersonation.ts
17538
+ var DEFAULT_IMPERSONATION_TTL_MS = MILLISECONDS_IN_AN_HOUR;
17539
+ var endImpersonation = async ({
17540
+ authSessionStore,
17541
+ cookie,
17542
+ emit,
17543
+ inMemorySession
17544
+ }) => {
17545
+ const currentId = cookie.value;
17546
+ if (currentId === undefined)
17547
+ return { restored: false };
17548
+ const current = await loadSessionFromSource({
17549
+ authSessionStore,
17550
+ removeExpired: false,
17551
+ session: inMemorySession,
17552
+ userSessionId: currentId
17553
+ });
17554
+ const impersonator = current?.impersonator;
17555
+ if (authSessionStore)
17556
+ await authSessionStore.removeSession(currentId);
17557
+ else
17558
+ delete inMemorySession[currentId];
17559
+ await emit?.({
17560
+ at: Date.now(),
17561
+ metadata: impersonator === undefined ? undefined : { actorId: impersonator.actorId },
17562
+ type: "impersonation_ended"
17563
+ });
17564
+ const returnTo = impersonator?.returnToSessionId;
17565
+ const prior = returnTo === undefined ? undefined : await loadSessionFromSource({
17566
+ authSessionStore,
17567
+ session: inMemorySession,
17568
+ userSessionId: returnTo
17569
+ });
17570
+ if (prior !== undefined && returnTo !== undefined) {
17571
+ cookie.set({
17572
+ httpOnly: true,
17573
+ sameSite: "lax",
17574
+ secure: true,
17575
+ value: returnTo
17576
+ });
17577
+ return { restored: true };
17578
+ }
17579
+ cookie.remove();
17580
+ return { restored: false };
17581
+ };
17582
+ var isImpersonating = (session) => session?.impersonator !== undefined;
17583
+ var startImpersonation = async ({
17584
+ authSessionStore,
17585
+ cookie,
17586
+ emit,
17587
+ getUserId,
17588
+ impersonator,
17589
+ inMemorySession,
17590
+ sessionDurationMs = DEFAULT_IMPERSONATION_TTL_MS,
17591
+ user
17592
+ }) => {
17593
+ const stamp = {
17594
+ actorEmail: impersonator.actorEmail,
17595
+ actorId: impersonator.actorId,
17596
+ reason: impersonator.reason,
17597
+ returnToSessionId: cookie.value,
17598
+ startedAt: Date.now()
17599
+ };
17600
+ const sessionId = await promoteToSession({
17601
+ authSessionStore,
17602
+ cookie,
17603
+ impersonator: stamp,
17604
+ inMemorySession,
17605
+ sessionDurationMs,
17606
+ user
17607
+ });
17608
+ await emit?.({
17609
+ at: Date.now(),
17610
+ metadata: { actorId: stamp.actorId, reason: stamp.reason },
17611
+ type: "impersonation_started",
17612
+ userId: getUserId?.(user)
17613
+ });
17614
+ return sessionId;
17615
+ };
17534
17616
  // src/utils.ts
17535
17617
  var defineAuthConfig = (configuration) => configuration;
17536
17618
  var defineAuthHtmxConfig = (htmxConfig) => htmxConfig;
@@ -17843,6 +17925,56 @@ var createPostgresCredentialStore = (db) => ({
17843
17925
  await db.update(credentialsTable).set({ email_verified: true, updated_at_ms: Date.now() }).where(eq(credentialsTable.email, email.toLowerCase()));
17844
17926
  }
17845
17927
  });
17928
+ // src/mfa/rotation.ts
17929
+ var tryDecrypt = async (ciphertext, key) => {
17930
+ try {
17931
+ return await decryptTotpSecret(ciphertext, key);
17932
+ } catch {
17933
+ return;
17934
+ }
17935
+ };
17936
+ var ensureReadable = async (ciphertext, key, userId) => {
17937
+ if (await tryDecrypt(ciphertext, key) === undefined) {
17938
+ throw new Error(`TOTP secret for ${userId} decrypts with neither the old nor the new key`);
17939
+ }
17940
+ };
17941
+ var planEnrollment = async (enrollment, oldKey, newKey) => {
17942
+ const ciphertext = enrollment.totpSecretCiphertext;
17943
+ if (ciphertext === undefined || ciphertext.length === 0) {
17944
+ const plan2 = { kind: "skip" };
17945
+ return plan2;
17946
+ }
17947
+ const secret = await tryDecrypt(ciphertext, oldKey);
17948
+ if (secret === undefined) {
17949
+ await ensureReadable(ciphertext, newKey, enrollment.userId);
17950
+ const plan2 = { kind: "already" };
17951
+ return plan2;
17952
+ }
17953
+ const plan = {
17954
+ enrollment: {
17955
+ ...enrollment,
17956
+ totpSecretCiphertext: await encryptTotpSecret(secret, newKey),
17957
+ updatedAt: Date.now()
17958
+ },
17959
+ kind: "rotate"
17960
+ };
17961
+ return plan;
17962
+ };
17963
+ var rotateMfaEncryptionKey = async ({
17964
+ mfaStore,
17965
+ newKey,
17966
+ oldKey
17967
+ }) => {
17968
+ const enrollments = await mfaStore.listEnrollments();
17969
+ const plans = await Promise.all(enrollments.map((enrollment) => planEnrollment(enrollment, oldKey, newKey)));
17970
+ await Promise.all(plans.map((plan) => plan.kind === "rotate" ? mfaStore.saveEnrollment(plan.enrollment) : Promise.resolve()));
17971
+ return {
17972
+ alreadyRotated: plans.filter((plan) => plan.kind === "already").length,
17973
+ rotated: plans.filter((plan) => plan.kind === "rotate").length,
17974
+ skippedNoSecret: plans.filter((plan) => plan.kind === "skip").length,
17975
+ total: plans.length
17976
+ };
17977
+ };
17846
17978
  // src/mfa/inMemoryMfaStore.ts
17847
17979
  var cloneEnrollment = (value) => ({
17848
17980
  ...value,
@@ -17855,6 +17987,7 @@ var createInMemoryMfaStore = () => {
17855
17987
  const enrollment = enrollments.get(userId);
17856
17988
  return enrollment ? cloneEnrollment(enrollment) : undefined;
17857
17989
  },
17990
+ listEnrollments: async () => Array.from(enrollments.values()).map(cloneEnrollment),
17858
17991
  removeEnrollment: async (userId) => {
17859
17992
  enrollments.delete(userId);
17860
17993
  },
@@ -17889,6 +18022,10 @@ var createPostgresMfaStore = (db) => ({
17889
18022
  const [row] = await db.select().from(mfaEnrollmentsTable).where(eq(mfaEnrollmentsTable.user_id, userId)).limit(1);
17890
18023
  return row ? toEnrollment(row) : undefined;
17891
18024
  },
18025
+ listEnrollments: async () => {
18026
+ const rows = await db.select().from(mfaEnrollmentsTable);
18027
+ return rows.map(toEnrollment);
18028
+ },
17892
18029
  removeEnrollment: async (userId) => {
17893
18030
  await db.delete(mfaEnrollmentsTable).where(eq(mfaEnrollmentsTable.user_id, userId));
17894
18031
  },
@@ -17908,6 +18045,194 @@ var createPostgresMfaStore = (db) => ({
17908
18045
  });
17909
18046
  }
17910
18047
  });
18048
+ // src/audit/integrity.ts
18049
+ var INTEGRITY_KEY = "__integrity";
18050
+ var GENESIS = "";
18051
+ var HEX_RADIX2 = 16;
18052
+ var HEX_PAD = 2;
18053
+ var encoder = new TextEncoder;
18054
+ var toHex = (buffer) => [...new Uint8Array(buffer)].map((byte) => byte.toString(HEX_RADIX2).padStart(HEX_PAD, "0")).join("");
18055
+ var sha256Hex = async (message) => toHex(await crypto.subtle.digest("SHA-256", encoder.encode(message)));
18056
+ var hmacSha256Hex = async (secret, message) => {
18057
+ const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { hash: "SHA-256", name: "HMAC" }, false, ["sign"]);
18058
+ return toHex(await crypto.subtle.sign("HMAC", key, encoder.encode(message)));
18059
+ };
18060
+ var sortKeys = (value) => value === null || typeof value !== "object" || Array.isArray(value) ? value : Object.fromEntries(Object.entries(value).sort((left, right) => left[0].localeCompare(right[0])));
18061
+ var stableStringify = (value) => JSON.stringify(value, (_key, val) => sortKeys(val));
18062
+ var cleanMetadata = (metadata) => {
18063
+ if (metadata === undefined)
18064
+ return;
18065
+ const result = {};
18066
+ for (const [key, val] of Object.entries(metadata)) {
18067
+ if (key !== INTEGRITY_KEY)
18068
+ result[key] = val;
18069
+ }
18070
+ return Object.keys(result).length === 0 ? undefined : result;
18071
+ };
18072
+ var readIntegrity = (event) => {
18073
+ const raw = event.metadata?.[INTEGRITY_KEY];
18074
+ if (raw === undefined)
18075
+ return;
18076
+ return raw;
18077
+ };
18078
+ var brokenAt = (index) => {
18079
+ const result = { brokenAt: index, ok: false };
18080
+ return result;
18081
+ };
18082
+ var createTamperEvidentSink = ({
18083
+ secret,
18084
+ sink
18085
+ }) => {
18086
+ let lastHash;
18087
+ const seed = async () => {
18088
+ if (lastHash !== undefined)
18089
+ return;
18090
+ const [recent] = await sink.list?.({ limit: 1 }) ?? [];
18091
+ lastHash = recent ? readIntegrity(recent)?.hash ?? GENESIS : GENESIS;
18092
+ };
18093
+ return {
18094
+ list: sink.list,
18095
+ append: async (event) => {
18096
+ await seed();
18097
+ const previousHash = lastHash ?? GENESIS;
18098
+ const hash = await hashAuditEvent(event, previousHash, secret);
18099
+ lastHash = hash;
18100
+ const integrity = { hash, previousHash };
18101
+ await sink.append({
18102
+ ...event,
18103
+ metadata: { ...event.metadata, [INTEGRITY_KEY]: integrity }
18104
+ });
18105
+ }
18106
+ };
18107
+ };
18108
+ var hashAuditEvent = async (event, previousHash, secret) => {
18109
+ const message = `${previousHash}.${stableStringify({
18110
+ ...event,
18111
+ metadata: cleanMetadata(event.metadata)
18112
+ })}`;
18113
+ return secret === undefined ? sha256Hex(message) : hmacSha256Hex(secret, message);
18114
+ };
18115
+ var verifyAuditChain = async (events, secret) => {
18116
+ let previousHash = GENESIS;
18117
+ for (let index = 0;index < events.length; index += 1) {
18118
+ const event = events[index];
18119
+ if (event === undefined)
18120
+ return brokenAt(index);
18121
+ const integrity = readIntegrity(event);
18122
+ const expected = await hashAuditEvent(event, previousHash, secret);
18123
+ if (integrity === undefined || integrity.previousHash !== previousHash || integrity.hash !== expected) {
18124
+ return brokenAt(index);
18125
+ }
18126
+ previousHash = integrity.hash;
18127
+ }
18128
+ const valid = { ok: true };
18129
+ return valid;
18130
+ };
18131
+ // src/audit/siem.ts
18132
+ var SOURCE = "absolutejs-auth";
18133
+ var requestFor = (endpoint, event) => {
18134
+ const base = {
18135
+ "content-type": "application/json",
18136
+ ...endpoint.headers
18137
+ };
18138
+ if (endpoint.format === "datadog") {
18139
+ return {
18140
+ body: JSON.stringify({
18141
+ ...event,
18142
+ ddsource: SOURCE,
18143
+ service: SOURCE
18144
+ }),
18145
+ headers: endpoint.token === undefined ? base : { ...base, "DD-API-KEY": endpoint.token }
18146
+ };
18147
+ }
18148
+ if (endpoint.format === "splunk") {
18149
+ return {
18150
+ body: JSON.stringify({ event, sourcetype: SOURCE }),
18151
+ headers: endpoint.token === undefined ? base : { ...base, authorization: `Splunk ${endpoint.token}` }
18152
+ };
18153
+ }
18154
+ return {
18155
+ body: JSON.stringify(event),
18156
+ headers: endpoint.token === undefined ? base : { ...base, authorization: `Bearer ${endpoint.token}` }
18157
+ };
18158
+ };
18159
+ var createSiemLogStream = ({
18160
+ endpoints
18161
+ }) => ({
18162
+ append: async (event) => {
18163
+ await Promise.all(endpoints.map(async (endpoint) => {
18164
+ const { body, headers } = requestFor(endpoint, event);
18165
+ await fetch(endpoint.url, {
18166
+ body,
18167
+ headers,
18168
+ method: "POST"
18169
+ }).catch(() => {
18170
+ return;
18171
+ });
18172
+ }));
18173
+ }
18174
+ });
18175
+ // src/abuse/config.ts
18176
+ var IPV4_BITS = 32;
18177
+ var IPV4_OCTET_SPACE = 256;
18178
+ var FULL_MASK = -1;
18179
+ var ACTION_SEVERITY = {
18180
+ allow: 0,
18181
+ challenge: 1,
18182
+ deny: 2
18183
+ };
18184
+ var BOT_PATTERN = /bot|crawl|spider|curl|wget|python-requests|headless|scrapy/iu;
18185
+ var CRAWLER_PATTERN = /googlebot|bingbot|duckduckbot|baiduspider|yandex/iu;
18186
+ var ipv4ToInt = (ipAddress) => ipAddress.split(".").reduce((acc, octet) => acc * IPV4_OCTET_SPACE + Number(octet), 0) >>> 0;
18187
+ var matchCidrV4 = (ipAddress, cidr2) => {
18188
+ const [range, bitsRaw] = cidr2.split("/");
18189
+ const bits = Number(bitsRaw);
18190
+ if (range === undefined || !Number.isInteger(bits) || !ipAddress.includes(".")) {
18191
+ return false;
18192
+ }
18193
+ const mask = bits === 0 ? 0 : FULL_MASK << IPV4_BITS - bits >>> 0;
18194
+ return (ipv4ToInt(ipAddress) & mask) === (ipv4ToInt(range) & mask);
18195
+ };
18196
+ var ipInList = (ipAddress, list) => list.some((entry) => entry.includes("/") ? matchCidrV4(ipAddress, entry) : entry === ipAddress);
18197
+ var mostSevere = (reasons) => reasons.reduce((worst, reason) => ACTION_SEVERITY[reason.action] > ACTION_SEVERITY[worst] ? reason.action : worst, "allow");
18198
+ var assessAbuse = async (config, context) => {
18199
+ const ipAddress = context.ip;
18200
+ if (ipAddress !== undefined && config.ipAllow !== undefined && config.ipAllow.length > 0 && ipInList(ipAddress, config.ipAllow)) {
18201
+ return { action: "allow", reasons: [] };
18202
+ }
18203
+ const reasons = [];
18204
+ if (ipAddress !== undefined && config.ipDeny !== undefined && ipInList(ipAddress, config.ipDeny)) {
18205
+ reasons.push({ action: "deny", signal: "blocked_ip" });
18206
+ }
18207
+ if (ipAddress !== undefined && config.ipAllow !== undefined && config.ipAllow.length > 0 && !ipInList(ipAddress, config.ipAllow)) {
18208
+ reasons.push({ action: "deny", signal: "not_allowlisted" });
18209
+ }
18210
+ const captchaPassed = config.verifyCaptcha === undefined || await config.verifyCaptcha(context.captchaToken, context);
18211
+ if (!captchaPassed) {
18212
+ reasons.push({
18213
+ action: config.captchaAction ?? "deny",
18214
+ signal: "captcha_failed"
18215
+ });
18216
+ }
18217
+ const botClass = config.classifyBot === undefined ? "human" : await config.classifyBot(context);
18218
+ if (botClass !== "human") {
18219
+ reasons.push({ action: config.botAction ?? "deny", signal: "bot" });
18220
+ }
18221
+ return { action: mostSevere(reasons), reasons };
18222
+ };
18223
+ var createAbuseGuard = (config) => ({
18224
+ assess: (context) => assessAbuse(config, context)
18225
+ });
18226
+ var defaultBotClassifier = (context) => {
18227
+ const userAgent = context.userAgent ?? "";
18228
+ if (userAgent.trim() === "")
18229
+ return "bot";
18230
+ if (CRAWLER_PATTERN.test(userAgent))
18231
+ return "crawler";
18232
+ if (BOT_PATTERN.test(userAgent))
18233
+ return "bot";
18234
+ return "human";
18235
+ };
17911
18236
  // src/compliance/redaction.ts
17912
18237
  var createAuditRedactor = ({
17913
18238
  dropFields = [],
@@ -18402,7 +18727,7 @@ var DEFAULT_VELOCITY_WINDOW_MS = MILLISECONDS_IN_A_MINUTE * DEFAULT_VELOCITY_WIN
18402
18727
  var EARTH_RADIUS_KM = 6371;
18403
18728
  var DEGREES_PER_HALF_TURN = 180;
18404
18729
  var HALF = 2;
18405
- var ACTION_SEVERITY = {
18730
+ var ACTION_SEVERITY2 = {
18406
18731
  allow: 0,
18407
18732
  deny: 2,
18408
18733
  step_up: 1
@@ -18425,7 +18750,7 @@ var haversineKm = (start, end) => {
18425
18750
  const factor = sinLat * sinLat + Math.cos(toRadians(start.latitude)) * Math.cos(toRadians(end.latitude)) * sinLon * sinLon;
18426
18751
  return HALF * EARTH_RADIUS_KM * Math.asin(Math.sqrt(factor));
18427
18752
  };
18428
- var mostSevere = (reasons) => reasons.reduce((worst, reason) => ACTION_SEVERITY[reason.action] > ACTION_SEVERITY[worst] ? reason.action : worst, "allow");
18753
+ var mostSevere2 = (reasons) => reasons.reduce((worst, reason) => ACTION_SEVERITY2[reason.action] > ACTION_SEVERITY2[worst] ? reason.action : worst, "allow");
18429
18754
  var assessRisk = async (config, context) => {
18430
18755
  const {
18431
18756
  historyLimit = DEFAULT_HISTORY_LIMIT,
@@ -18469,7 +18794,7 @@ var assessRisk = async (config, context) => {
18469
18794
  if (recentCount >= velocityMaxAttempts) {
18470
18795
  reasons.push({ action: actions.velocity, signal: "velocity" });
18471
18796
  }
18472
- return { action: mostSevere(reasons), reasons };
18797
+ return { action: mostSevere2(reasons), reasons };
18473
18798
  };
18474
18799
  var createRiskEngine = (config) => ({
18475
18800
  assessRisk: (context) => assessRisk(config, context),
@@ -19420,12 +19745,14 @@ export {
19420
19745
  verifyWebhookSignature,
19421
19746
  verifyTotp,
19422
19747
  verifyPassword,
19748
+ verifyAuditChain,
19423
19749
  verifyApiKey,
19424
19750
  verifyAccessToken,
19425
19751
  validateSession,
19426
19752
  userSessionIdTypebox,
19427
19753
  trustDevice,
19428
19754
  stepUpPlugin,
19755
+ startImpersonation,
19429
19756
  ssoDiscoveryRoute,
19430
19757
  ssoConnectionsTable,
19431
19758
  signWebhook,
@@ -19438,6 +19765,7 @@ export {
19438
19765
  scimTokensTable,
19439
19766
  scimRoutes,
19440
19767
  samlSsoRoutes,
19768
+ rotateMfaEncryptionKey,
19441
19769
  rolesTable,
19442
19770
  roleRoutes,
19443
19771
  revokeUserSessions,
@@ -19486,11 +19814,13 @@ export {
19486
19814
  isPKCEProviderOption,
19487
19815
  isOIDCProviderOption,
19488
19816
  isMfaEnrolled,
19817
+ isImpersonating,
19489
19818
  isAuthIntent,
19490
19819
  inviteToOrganization,
19491
19820
  instantiateUserSession,
19492
19821
  hashToken,
19493
19822
  hashPassword,
19823
+ hashAuditEvent,
19494
19824
  hasScopes,
19495
19825
  hasOrganizationScope,
19496
19826
  getUserSessionId,
@@ -19503,12 +19833,14 @@ export {
19503
19833
  extractPropFromIdentity,
19504
19834
  exchangeClientCredentials,
19505
19835
  evaluatePassword,
19836
+ endImpersonation,
19506
19837
  encryptTotpSecret,
19507
19838
  encryptSecret,
19508
19839
  defineProvidersConfiguration,
19509
19840
  defineAuthSettings,
19510
19841
  defineAuthHtmxConfig,
19511
19842
  defineAuthConfig,
19843
+ defaultBotClassifier,
19512
19844
  decryptTotpSecret,
19513
19845
  decryptSecret,
19514
19846
  decodeJWT,
@@ -19522,6 +19854,8 @@ export {
19522
19854
  credentialResetTokensTable,
19523
19855
  createWebhookDispatcher,
19524
19856
  createTotpKeyUri,
19857
+ createTamperEvidentSink,
19858
+ createSiemLogStream,
19525
19859
  createSetupSession,
19526
19860
  createSecretCipher,
19527
19861
  createScimToken,
@@ -19593,6 +19927,7 @@ export {
19593
19927
  createAuditEmitter,
19594
19928
  createApiKey,
19595
19929
  createApiClient,
19930
+ createAbuseGuard,
19596
19931
  consumeBackupCode,
19597
19932
  constantTimeEqual,
19598
19933
  complianceRoutes,
@@ -19605,6 +19940,7 @@ export {
19605
19940
  auth,
19606
19941
  auditEventsTable,
19607
19942
  assessRisk,
19943
+ assessAbuse,
19608
19944
  apiKeysTable,
19609
19945
  apiKeysRoutes,
19610
19946
  apiClientsTable,
@@ -19639,5 +19975,5 @@ export {
19639
19975
  AuthIdentityConflictError
19640
19976
  };
19641
19977
 
19642
- //# debugId=E141C00026B64EA864756E2164756E21
19978
+ //# debugId=5C9E1C93D2A5368D64756E2164756E21
19643
19979
  //# sourceMappingURL=index.js.map