@absolutejs/auth 0.27.0-beta.2 → 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.
- package/dist/abuse/config.d.ts +29 -0
- package/dist/audit/integrity.d.ts +15 -0
- package/dist/audit/siem.d.ts +11 -0
- package/dist/audit/types.d.ts +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +284 -4
- package/dist/index.js.map +9 -5
- package/dist/session/impersonation.d.ts +29 -0
- package/dist/session/promote.d.ts +2 -1
- package/dist/types.d.ts +13 -0
- package/package.json +1 -1
|
@@ -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;
|
package/dist/audit/types.d.ts
CHANGED
|
@@ -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';
|
|
@@ -8445,6 +8446,11 @@ export { createInMemoryMfaStore } from './mfa/inMemoryMfaStore';
|
|
|
8445
8446
|
export { createNeonMfaStore, createPostgresMfaStore, mfaEnrollmentsTable } from './mfa/postgresMfaStore';
|
|
8446
8447
|
export * from './audit/config';
|
|
8447
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';
|
|
8448
8454
|
export * from './authorization/config';
|
|
8449
8455
|
export { protectPermissionPlugin } from './authorization/protectPermission';
|
|
8450
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;
|
|
@@ -17963,6 +18045,194 @@ var createPostgresMfaStore = (db) => ({
|
|
|
17963
18045
|
});
|
|
17964
18046
|
}
|
|
17965
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
|
+
};
|
|
17966
18236
|
// src/compliance/redaction.ts
|
|
17967
18237
|
var createAuditRedactor = ({
|
|
17968
18238
|
dropFields = [],
|
|
@@ -18457,7 +18727,7 @@ var DEFAULT_VELOCITY_WINDOW_MS = MILLISECONDS_IN_A_MINUTE * DEFAULT_VELOCITY_WIN
|
|
|
18457
18727
|
var EARTH_RADIUS_KM = 6371;
|
|
18458
18728
|
var DEGREES_PER_HALF_TURN = 180;
|
|
18459
18729
|
var HALF = 2;
|
|
18460
|
-
var
|
|
18730
|
+
var ACTION_SEVERITY2 = {
|
|
18461
18731
|
allow: 0,
|
|
18462
18732
|
deny: 2,
|
|
18463
18733
|
step_up: 1
|
|
@@ -18480,7 +18750,7 @@ var haversineKm = (start, end) => {
|
|
|
18480
18750
|
const factor = sinLat * sinLat + Math.cos(toRadians(start.latitude)) * Math.cos(toRadians(end.latitude)) * sinLon * sinLon;
|
|
18481
18751
|
return HALF * EARTH_RADIUS_KM * Math.asin(Math.sqrt(factor));
|
|
18482
18752
|
};
|
|
18483
|
-
var
|
|
18753
|
+
var mostSevere2 = (reasons) => reasons.reduce((worst, reason) => ACTION_SEVERITY2[reason.action] > ACTION_SEVERITY2[worst] ? reason.action : worst, "allow");
|
|
18484
18754
|
var assessRisk = async (config, context) => {
|
|
18485
18755
|
const {
|
|
18486
18756
|
historyLimit = DEFAULT_HISTORY_LIMIT,
|
|
@@ -18524,7 +18794,7 @@ var assessRisk = async (config, context) => {
|
|
|
18524
18794
|
if (recentCount >= velocityMaxAttempts) {
|
|
18525
18795
|
reasons.push({ action: actions.velocity, signal: "velocity" });
|
|
18526
18796
|
}
|
|
18527
|
-
return { action:
|
|
18797
|
+
return { action: mostSevere2(reasons), reasons };
|
|
18528
18798
|
};
|
|
18529
18799
|
var createRiskEngine = (config) => ({
|
|
18530
18800
|
assessRisk: (context) => assessRisk(config, context),
|
|
@@ -19475,12 +19745,14 @@ export {
|
|
|
19475
19745
|
verifyWebhookSignature,
|
|
19476
19746
|
verifyTotp,
|
|
19477
19747
|
verifyPassword,
|
|
19748
|
+
verifyAuditChain,
|
|
19478
19749
|
verifyApiKey,
|
|
19479
19750
|
verifyAccessToken,
|
|
19480
19751
|
validateSession,
|
|
19481
19752
|
userSessionIdTypebox,
|
|
19482
19753
|
trustDevice,
|
|
19483
19754
|
stepUpPlugin,
|
|
19755
|
+
startImpersonation,
|
|
19484
19756
|
ssoDiscoveryRoute,
|
|
19485
19757
|
ssoConnectionsTable,
|
|
19486
19758
|
signWebhook,
|
|
@@ -19542,11 +19814,13 @@ export {
|
|
|
19542
19814
|
isPKCEProviderOption,
|
|
19543
19815
|
isOIDCProviderOption,
|
|
19544
19816
|
isMfaEnrolled,
|
|
19817
|
+
isImpersonating,
|
|
19545
19818
|
isAuthIntent,
|
|
19546
19819
|
inviteToOrganization,
|
|
19547
19820
|
instantiateUserSession,
|
|
19548
19821
|
hashToken,
|
|
19549
19822
|
hashPassword,
|
|
19823
|
+
hashAuditEvent,
|
|
19550
19824
|
hasScopes,
|
|
19551
19825
|
hasOrganizationScope,
|
|
19552
19826
|
getUserSessionId,
|
|
@@ -19559,12 +19833,14 @@ export {
|
|
|
19559
19833
|
extractPropFromIdentity,
|
|
19560
19834
|
exchangeClientCredentials,
|
|
19561
19835
|
evaluatePassword,
|
|
19836
|
+
endImpersonation,
|
|
19562
19837
|
encryptTotpSecret,
|
|
19563
19838
|
encryptSecret,
|
|
19564
19839
|
defineProvidersConfiguration,
|
|
19565
19840
|
defineAuthSettings,
|
|
19566
19841
|
defineAuthHtmxConfig,
|
|
19567
19842
|
defineAuthConfig,
|
|
19843
|
+
defaultBotClassifier,
|
|
19568
19844
|
decryptTotpSecret,
|
|
19569
19845
|
decryptSecret,
|
|
19570
19846
|
decodeJWT,
|
|
@@ -19578,6 +19854,8 @@ export {
|
|
|
19578
19854
|
credentialResetTokensTable,
|
|
19579
19855
|
createWebhookDispatcher,
|
|
19580
19856
|
createTotpKeyUri,
|
|
19857
|
+
createTamperEvidentSink,
|
|
19858
|
+
createSiemLogStream,
|
|
19581
19859
|
createSetupSession,
|
|
19582
19860
|
createSecretCipher,
|
|
19583
19861
|
createScimToken,
|
|
@@ -19649,6 +19927,7 @@ export {
|
|
|
19649
19927
|
createAuditEmitter,
|
|
19650
19928
|
createApiKey,
|
|
19651
19929
|
createApiClient,
|
|
19930
|
+
createAbuseGuard,
|
|
19652
19931
|
consumeBackupCode,
|
|
19653
19932
|
constantTimeEqual,
|
|
19654
19933
|
complianceRoutes,
|
|
@@ -19661,6 +19940,7 @@ export {
|
|
|
19661
19940
|
auth,
|
|
19662
19941
|
auditEventsTable,
|
|
19663
19942
|
assessRisk,
|
|
19943
|
+
assessAbuse,
|
|
19664
19944
|
apiKeysTable,
|
|
19665
19945
|
apiKeysRoutes,
|
|
19666
19946
|
apiClientsTable,
|
|
@@ -19695,5 +19975,5 @@ export {
|
|
|
19695
19975
|
AuthIdentityConflictError
|
|
19696
19976
|
};
|
|
19697
19977
|
|
|
19698
|
-
//# debugId=
|
|
19978
|
+
//# debugId=5C9E1C93D2A5368D64756E2164756E21
|
|
19699
19979
|
//# sourceMappingURL=index.js.map
|