@effect-auth/core 0.1.0-alpha.10 → 0.1.0-alpha.13
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/README.md +65 -4
- package/dist/AuditLog.d.ts +60 -0
- package/dist/AuditLog.d.ts.map +1 -1
- package/dist/AuditLog.js +105 -0
- package/dist/AuditLog.js.map +1 -1
- package/dist/AuthKernel.d.ts +1 -1
- package/dist/Client.d.ts +72 -1
- package/dist/Client.d.ts.map +1 -1
- package/dist/Client.js +218 -1
- package/dist/Client.js.map +1 -1
- package/dist/DomainVerification.d.ts +200 -0
- package/dist/DomainVerification.d.ts.map +1 -0
- package/dist/DomainVerification.js +304 -0
- package/dist/DomainVerification.js.map +1 -0
- package/dist/EffectQbSqliteStorage.d.ts +389 -4
- package/dist/EffectQbSqliteStorage.d.ts.map +1 -1
- package/dist/EffectQbSqliteStorage.js +1191 -4
- package/dist/EffectQbSqliteStorage.js.map +1 -1
- package/dist/EmailOtp.d.ts +2 -2
- package/dist/HttpApi/Api.d.ts +477 -23
- package/dist/HttpApi/Api.d.ts.map +1 -1
- package/dist/HttpApi/Api.js +705 -4
- package/dist/HttpApi/Api.js.map +1 -1
- package/dist/HttpApi/Endpoints.d.ts +133 -5
- package/dist/HttpApi/Endpoints.d.ts.map +1 -1
- package/dist/HttpApi/Endpoints.js +57 -2
- package/dist/HttpApi/Endpoints.js.map +1 -1
- package/dist/HttpApi/Errors.d.ts +32 -0
- package/dist/HttpApi/Errors.d.ts.map +1 -1
- package/dist/HttpApi/Errors.js +46 -0
- package/dist/HttpApi/Errors.js.map +1 -1
- package/dist/HttpApi/Schemas.d.ts +149 -8
- package/dist/HttpApi/Schemas.d.ts.map +1 -1
- package/dist/HttpApi/Schemas.js +128 -0
- package/dist/HttpApi/Schemas.js.map +1 -1
- package/dist/Identifiers.d.ts +3 -0
- package/dist/Identifiers.d.ts.map +1 -1
- package/dist/Identifiers.js +2 -0
- package/dist/Identifiers.js.map +1 -1
- package/dist/IncidentAction.d.ts +80 -0
- package/dist/IncidentAction.d.ts.map +1 -0
- package/dist/IncidentAction.js +158 -0
- package/dist/IncidentAction.js.map +1 -0
- package/dist/Jwt.d.ts +10 -0
- package/dist/Jwt.d.ts.map +1 -1
- package/dist/Jwt.js +209 -0
- package/dist/Jwt.js.map +1 -1
- package/dist/LoginNotification.d.ts +1 -1
- package/dist/LoginRisk.d.ts +272 -1
- package/dist/LoginRisk.d.ts.map +1 -1
- package/dist/LoginRisk.js +427 -0
- package/dist/LoginRisk.js.map +1 -1
- package/dist/MachineAuth.d.ts +73 -0
- package/dist/MachineAuth.d.ts.map +1 -0
- package/dist/MachineAuth.js +147 -0
- package/dist/MachineAuth.js.map +1 -0
- package/dist/MagicLink.d.ts +2 -2
- package/dist/OAuth.d.ts +957 -1
- package/dist/OAuth.d.ts.map +1 -1
- package/dist/OAuth.js +1403 -1
- package/dist/OAuth.js.map +1 -1
- package/dist/Password.d.ts +2 -2
- package/dist/Retention.d.ts +98 -0
- package/dist/Retention.d.ts.map +1 -0
- package/dist/Retention.js +204 -0
- package/dist/Retention.js.map +1 -0
- package/dist/SecurityTimeline.d.ts +8 -2
- package/dist/SecurityTimeline.d.ts.map +1 -1
- package/dist/SecurityTimeline.js +75 -0
- package/dist/SecurityTimeline.js.map +1 -1
- package/dist/StorageMigrations.d.ts +11 -1
- package/dist/StorageMigrations.d.ts.map +1 -1
- package/dist/StorageMigrations.js +206 -0
- package/dist/StorageMigrations.js.map +1 -1
- package/dist/Webhook.d.ts +310 -2
- package/dist/Webhook.d.ts.map +1 -1
- package/dist/Webhook.js +511 -1
- package/dist/Webhook.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/migrations/0014_auth_webhook_outbox.sql +16 -0
- package/migrations/0015_auth_webhook_replay.sql +7 -0
- package/migrations/0016_auth_login_risk_history.sql +23 -0
- package/migrations/0017_auth_audit_log.sql +17 -0
- package/migrations/0018_auth_domain_verification.sql +18 -0
- package/migrations/0019_auth_oauth_authorization_code.sql +17 -0
- package/migrations/0020_auth_oauth_provider_mode_token.sql +24 -0
- package/migrations/0021_auth_oauth_client_secret.sql +14 -0
- package/migrations/0022_auth_oauth_client.sql +15 -0
- package/migrations/0023_auth_oauth_consent.sql +15 -0
- package/package.json +17 -1
package/dist/HttpApi/Api.js
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
|
-
import { Effect, Layer, Option, Redacted } from "effect";
|
|
2
|
-
import { HttpServerResponse } from "effect/unstable/http";
|
|
1
|
+
import { Context, Effect, Encoding, Layer, Option, Redacted, Result } from "effect";
|
|
2
|
+
import { HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
|
|
3
3
|
import { HttpApi, HttpApiBuilder, HttpApiGroup } from "effect/unstable/httpapi";
|
|
4
4
|
import { ApiKeyId } from "../ApiKey.js";
|
|
5
|
+
import { Jwks } from "../Jwt.js";
|
|
5
6
|
import { AuthFlow, AuthFlowState, AuthResult, LoginApprovalFinalize, } from "../AuthFlow.js";
|
|
6
7
|
import { EmailOtpLogin } from "../EmailOtp.js";
|
|
7
8
|
import { EmailDeliveryError, EmailVerification, EmailVerificationFlow, EmailVerificationIssueError, } from "../EmailVerification.js";
|
|
9
|
+
import { OAuthClientId as makeOAuthClientId } from "../Identifiers.js";
|
|
8
10
|
import { currentUnixMillis } from "../Internal.js";
|
|
9
11
|
import { LoginApproval, LoginApprovalReview } from "../LoginApproval.js";
|
|
10
12
|
import { LoginNotification } from "../LoginNotification.js";
|
|
11
13
|
import { MagicLinkLogin } from "../MagicLink.js";
|
|
14
|
+
import { OAuthAuthorizationCode, OAuthAuthorizationCodeTokenGrant, OAuthClientCredentialsGrant, OAuthProviderAuthorization, OAuthRefreshToken, OAuthRefreshTokenGrant, OAuthTokenIntrospection, OAuthTokenRevocation, OAuthCodeVerifier as makeOAuthCodeVerifier, } from "../OAuth.js";
|
|
12
15
|
import { PasswordLogin, PasswordManagement, PasswordRegistration, PasswordReset, } from "../Password.js";
|
|
13
16
|
import { PasskeyCredentialId } from "../Passkey.js";
|
|
14
17
|
import { CurrentSession, SessionCookie, Sessions, sessionRequestMetadataKey, upgradeCurrentSession, } from "../Sessions.js";
|
|
15
18
|
import { SecurityTimelineStore } from "../SecurityTimeline.js";
|
|
16
19
|
import { UserStore } from "../Storage.js";
|
|
17
20
|
import { TrustedDevice, TrustedDeviceCookie, TrustedDeviceStore, } from "../TrustedDevice.js";
|
|
18
|
-
import { apiKeyCreateEndpoint, apiKeyListEndpoint, apiKeyRevokeEndpoint, currentSessionEndpoint, emailOtpStartEndpoint, emailOtpVerifyEndpoint, emailVerificationStartEndpoint, emailVerificationVerifyEndpoint, loginApprovalApproveEndpoint, loginApprovalFinalizeEndpoint, loginApprovalStatusEndpoint, loginNotificationReportEndpoint, jwtIntrospectEndpoint, jwtRevokeEndpoint, listSessionsEndpoint, logoutEndpoint, magicLinkStartEndpoint, magicLinkVerifyEndpoint, mfaOptionsEndpoint, oauthAccountUnlinkEndpoint, oauthAuthorizationStartEndpoint, oauthLinkConfirmationConfirmEndpoint, oauthLinkConfirmationInspectEndpoint, oauthLinkConfirmationStartEndpoint, passwordChangeEndpoint, passwordResetStartEndpoint, passwordResetVerifyEndpoint, passwordSetEndpoint, passwordSignInEndpoint, passwordSignUpEndpoint, passkeyMfaStartEndpoint, passkeyMfaVerifyEndpoint, recoveryCodeMfaVerifyEndpoint, recoveryCodeMfaVerifyForFlowEndpoint, refreshTokenRefreshEndpoint, refreshSessionEndpoint, revokeOtherSessionsEndpoint, revokeSessionEndpoint, securityTimelineListEndpoint, stepUpOptionsEndpoint, stepUpPasskeyStartEndpoint, stepUpPasskeyVerifyEndpoint, stepUpRecoveryCodeVerifyEndpoint, stepUpTotpVerifyEndpoint, trustedDeviceListEndpoint, trustedDeviceRevokeEndpoint, totpMfaVerifyEndpoint, totpMfaVerifyForFlowEndpoint, } from "./Endpoints.js";
|
|
19
|
-
import { AuthBadRequestError, AuthEmailAlreadyRegisteredError, AuthInternalError, AuthInvalidCredentialsError, AuthPolicyDeniedError, AuthRateLimitedError, AuthSchemaErrorMiddleware, AuthSchemaErrorMiddlewareLive, AuthUnauthenticatedError, } from "./Errors.js";
|
|
21
|
+
import { adminSecurityTimelineListEndpoint, adminSessionListEndpoint, adminSessionRevokeAllEndpoint, adminSessionRevokeEndpoint, adminTrustedDeviceListEndpoint, adminTrustedDeviceRevokeEndpoint, apiKeyCreateEndpoint, apiKeyListEndpoint, apiKeyRevokeEndpoint, currentSessionEndpoint, emailOtpStartEndpoint, emailOtpVerifyEndpoint, emailVerificationStartEndpoint, emailVerificationVerifyEndpoint, loginApprovalApproveEndpoint, loginApprovalFinalizeEndpoint, loginApprovalStatusEndpoint, loginNotificationReportEndpoint, jwtIntrospectEndpoint, jwtJwksEndpoint, jwtRevokeEndpoint, listSessionsEndpoint, logoutEndpoint, magicLinkStartEndpoint, magicLinkVerifyEndpoint, mfaOptionsEndpoint, oauthAccountUnlinkEndpoint, oauthAuthorizationStartEndpoint, oauthLinkConfirmationConfirmEndpoint, oauthLinkConfirmationInspectEndpoint, oauthLinkConfirmationStartEndpoint, oauthProviderAuthorizeEndpoint, oauthTokenEndpoint, oauthTokenIntrospectionEndpoint, oauthTokenRevocationEndpoint, oidcDiscoveryMetadataEndpoint, passwordChangeEndpoint, passwordResetStartEndpoint, passwordResetVerifyEndpoint, passwordSetEndpoint, passwordSignInEndpoint, passwordSignUpEndpoint, passkeyMfaStartEndpoint, passkeyMfaVerifyEndpoint, recoveryCodeMfaVerifyEndpoint, recoveryCodeMfaVerifyForFlowEndpoint, refreshTokenRefreshEndpoint, refreshSessionEndpoint, revokeOtherSessionsEndpoint, revokeSessionEndpoint, securityTimelineListEndpoint, stepUpOptionsEndpoint, stepUpPasskeyStartEndpoint, stepUpPasskeyVerifyEndpoint, stepUpRecoveryCodeVerifyEndpoint, stepUpTotpVerifyEndpoint, trustedDeviceListEndpoint, trustedDeviceRevokeEndpoint, totpMfaVerifyEndpoint, totpMfaVerifyForFlowEndpoint, } from "./Endpoints.js";
|
|
22
|
+
import { AuthBadRequestError, AuthEmailAlreadyRegisteredError, AuthInternalError, AuthInvalidCredentialsError, AuthPolicyDeniedError, AuthRateLimitedError, AuthSchemaErrorMiddleware, AuthSchemaErrorMiddlewareLive, AuthUnauthenticatedError, OAuthAuthorizationEndpointError, OAuthTokenEndpointError, OAuthTokenIntrospectionEndpointError, OAuthTokenRevocationEndpointError, } from "./Errors.js";
|
|
23
|
+
import { OAuthProviderAuthorizationQuery, OAuthTokenRequestBody, OAuthTokenIntrospectionRequestBody, OAuthTokenIntrospectionResponseBody, OAuthTokenRevocationRequestBody, } from "./Schemas.js";
|
|
20
24
|
import { AuthApiRateLimit, AuthApiRateLimitLive, AuthApiRateLimitNoopLive, AuthHttpApiConfig, AuthOriginCheckMiddleware, AuthOriginCheckMiddlewareConfigLive, AuthRateLimitMiddleware, makeAuthRequestMetadata, } from "./Security.js";
|
|
21
25
|
import { AuthHttp, LoginApprovalPendingCookie, makeLoginApprovalPendingCookie, } from "./Transport.js";
|
|
22
26
|
const canStartRequiredEmailVerification = (result) => result._tag === "RequiresEmailVerification" &&
|
|
@@ -257,6 +261,259 @@ export const oauthAuthorizationCallbackInput = (payload, options) => Effect.gen(
|
|
|
257
261
|
: { tokenParams: options.tokenParams }),
|
|
258
262
|
};
|
|
259
263
|
});
|
|
264
|
+
const oauthTokenTextDecoder = new TextDecoder();
|
|
265
|
+
const oauthTokenEndpointError = (reason, errorDescription) => new OAuthTokenEndpointError({
|
|
266
|
+
error: reason,
|
|
267
|
+
...(errorDescription === undefined ? {} : { errorDescription }),
|
|
268
|
+
});
|
|
269
|
+
const oauthTokenRevocationEndpointError = (reason, errorDescription) => new OAuthTokenRevocationEndpointError({
|
|
270
|
+
error: reason,
|
|
271
|
+
...(errorDescription === undefined ? {} : { errorDescription }),
|
|
272
|
+
});
|
|
273
|
+
const oauthTokenIntrospectionEndpointError = (reason, errorDescription) => new OAuthTokenIntrospectionEndpointError({
|
|
274
|
+
error: reason,
|
|
275
|
+
...(errorDescription === undefined ? {} : { errorDescription }),
|
|
276
|
+
});
|
|
277
|
+
const oauthAuthorizationEndpointError = (reason, errorDescription) => new OAuthAuthorizationEndpointError({
|
|
278
|
+
error: reason,
|
|
279
|
+
...(errorDescription === undefined ? {} : { errorDescription }),
|
|
280
|
+
});
|
|
281
|
+
const oauthAuthorizationRedirect = (redirectUri, params) => {
|
|
282
|
+
const url = new URL(redirectUri);
|
|
283
|
+
for (const [key, value] of Object.entries(params)) {
|
|
284
|
+
if (value !== undefined) {
|
|
285
|
+
url.searchParams.set(key, value);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return HttpServerResponse.empty({
|
|
289
|
+
status: 302,
|
|
290
|
+
headers: { location: url.toString() },
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
const oauthTokenGrantString = (value) => {
|
|
294
|
+
const trimmed = value?.trim();
|
|
295
|
+
return trimmed === undefined || trimmed === "" ? undefined : trimmed;
|
|
296
|
+
};
|
|
297
|
+
const formUrlDecodeComponent = (value) => {
|
|
298
|
+
try {
|
|
299
|
+
return new URLSearchParams(`value=${value}`).get("value") ?? value;
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
return value;
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
const decodeOAuthBasicAuthentication = (request, invalidClient) => {
|
|
306
|
+
const { authorization } = request.headers;
|
|
307
|
+
if (authorization === undefined || authorization.trim() === "") {
|
|
308
|
+
return Effect.succeed(Option.none());
|
|
309
|
+
}
|
|
310
|
+
if (!authorization.toLowerCase().startsWith("basic ")) {
|
|
311
|
+
return Effect.fail(invalidClient());
|
|
312
|
+
}
|
|
313
|
+
const encoded = authorization.slice("Basic ".length).trim();
|
|
314
|
+
if (encoded === "") {
|
|
315
|
+
return Effect.fail(invalidClient());
|
|
316
|
+
}
|
|
317
|
+
return Result.match(Encoding.decodeBase64(encoded), {
|
|
318
|
+
onFailure: () => Effect.fail(invalidClient()),
|
|
319
|
+
onSuccess: (bytes) => {
|
|
320
|
+
const decoded = oauthTokenTextDecoder.decode(bytes);
|
|
321
|
+
const separator = decoded.indexOf(":");
|
|
322
|
+
if (separator <= 0) {
|
|
323
|
+
return Effect.fail(invalidClient());
|
|
324
|
+
}
|
|
325
|
+
const clientId = oauthTokenGrantString(formUrlDecodeComponent(decoded.slice(0, separator)));
|
|
326
|
+
const clientSecret = formUrlDecodeComponent(decoded.slice(separator + 1));
|
|
327
|
+
if (clientId === undefined || clientSecret === "") {
|
|
328
|
+
return Effect.fail(invalidClient());
|
|
329
|
+
}
|
|
330
|
+
return Effect.succeed(Option.some({
|
|
331
|
+
clientId: makeOAuthClientId(clientId),
|
|
332
|
+
method: "client_secret_basic",
|
|
333
|
+
clientSecret: Redacted.make(clientSecret),
|
|
334
|
+
}));
|
|
335
|
+
},
|
|
336
|
+
});
|
|
337
|
+
};
|
|
338
|
+
const oauthTokenRequestBody = (request) => HttpServerRequest.schemaBodyUrlParams(OAuthTokenRequestBody).pipe(Effect.provideService(HttpServerRequest.HttpServerRequest, request), Effect.mapError(() => oauthTokenEndpointError("invalid_request")));
|
|
339
|
+
const oauthTokenRevocationRequestBody = (request) => HttpServerRequest.schemaBodyUrlParams(OAuthTokenRevocationRequestBody).pipe(Effect.provideService(HttpServerRequest.HttpServerRequest, request), Effect.mapError(() => oauthTokenRevocationEndpointError("invalid_request")));
|
|
340
|
+
const oauthTokenIntrospectionRequestBody = (request) => HttpServerRequest.schemaBodyUrlParams(OAuthTokenIntrospectionRequestBody).pipe(Effect.provideService(HttpServerRequest.HttpServerRequest, request), Effect.mapError(() => oauthTokenIntrospectionEndpointError("invalid_request")));
|
|
341
|
+
const oauthPostClientAuthentication = (payload) => {
|
|
342
|
+
const clientSecret = oauthTokenGrantString(payload.client_secret);
|
|
343
|
+
const clientId = oauthTokenGrantString(payload.client_id);
|
|
344
|
+
if (clientSecret === undefined) {
|
|
345
|
+
return undefined;
|
|
346
|
+
}
|
|
347
|
+
return clientId === undefined
|
|
348
|
+
? undefined
|
|
349
|
+
: {
|
|
350
|
+
clientId: makeOAuthClientId(clientId),
|
|
351
|
+
method: "client_secret_post",
|
|
352
|
+
clientSecret: Redacted.make(clientSecret),
|
|
353
|
+
};
|
|
354
|
+
};
|
|
355
|
+
const oauthClientEndpointAuthentication = (input) => Effect.gen(function* () {
|
|
356
|
+
const basicAuth = yield* decodeOAuthBasicAuthentication(input.request, input.invalidClient);
|
|
357
|
+
const postAuth = oauthPostClientAuthentication(input.payload);
|
|
358
|
+
if (Option.isSome(basicAuth) && input.payload.client_secret !== undefined) {
|
|
359
|
+
return yield* Effect.fail(input.invalidRequest());
|
|
360
|
+
}
|
|
361
|
+
if (input.payload.client_secret !== undefined && postAuth === undefined) {
|
|
362
|
+
return yield* Effect.fail(input.invalidRequest());
|
|
363
|
+
}
|
|
364
|
+
const authentication = Option.isSome(basicAuth) ? basicAuth.value : postAuth;
|
|
365
|
+
const payloadClientId = oauthTokenGrantString(input.payload.client_id);
|
|
366
|
+
if (authentication !== undefined &&
|
|
367
|
+
payloadClientId !== undefined &&
|
|
368
|
+
authentication.clientId !== payloadClientId) {
|
|
369
|
+
return yield* Effect.fail(input.invalidRequest());
|
|
370
|
+
}
|
|
371
|
+
const clientAuthenticated = authentication === undefined
|
|
372
|
+
? false
|
|
373
|
+
: yield* Effect.gen(function* () {
|
|
374
|
+
if (input.authenticateClient === undefined) {
|
|
375
|
+
return yield* Effect.fail(input.invalidClient());
|
|
376
|
+
}
|
|
377
|
+
const authenticated = yield* input
|
|
378
|
+
.authenticateClient({
|
|
379
|
+
clientId: authentication.clientId,
|
|
380
|
+
method: authentication.method,
|
|
381
|
+
clientSecret: authentication.clientSecret,
|
|
382
|
+
request: input.request,
|
|
383
|
+
})
|
|
384
|
+
.pipe(Effect.mapError(() => oauthInternalError("Failed to authenticate OAuth client")));
|
|
385
|
+
if (!authenticated) {
|
|
386
|
+
return yield* Effect.fail(input.invalidClient());
|
|
387
|
+
}
|
|
388
|
+
return true;
|
|
389
|
+
});
|
|
390
|
+
const clientId = authentication === undefined
|
|
391
|
+
? payloadClientId === undefined
|
|
392
|
+
? undefined
|
|
393
|
+
: makeOAuthClientId(payloadClientId)
|
|
394
|
+
: authentication.clientId;
|
|
395
|
+
return {
|
|
396
|
+
...(clientId === undefined ? {} : { clientId }),
|
|
397
|
+
clientAuthenticated,
|
|
398
|
+
};
|
|
399
|
+
});
|
|
400
|
+
const oauthTokenResponseHttpBody = (tokens) => ({
|
|
401
|
+
access_token: Redacted.value(tokens.accessToken),
|
|
402
|
+
token_type: tokens.tokenType,
|
|
403
|
+
...(tokens.expiresIn === undefined ? {} : { expires_in: tokens.expiresIn }),
|
|
404
|
+
...(tokens.refreshToken === undefined
|
|
405
|
+
? {}
|
|
406
|
+
: { refresh_token: Redacted.value(tokens.refreshToken) }),
|
|
407
|
+
...(tokens.idToken === undefined
|
|
408
|
+
? {}
|
|
409
|
+
: { id_token: Redacted.value(tokens.idToken) }),
|
|
410
|
+
...(tokens.scopes === undefined ? {} : { scope: tokens.scopes.join(" ") }),
|
|
411
|
+
...(tokens.extra === undefined ? {} : { extra: tokens.extra }),
|
|
412
|
+
});
|
|
413
|
+
const oauthUnixMillisToSeconds = (value) => Math.floor(Number(value) / 1000);
|
|
414
|
+
const oauthTokenIntrospectionResponseHttpBody = (introspection) => {
|
|
415
|
+
if (!introspection.active) {
|
|
416
|
+
return { active: false };
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
active: true,
|
|
420
|
+
...(introspection.scopes === undefined
|
|
421
|
+
? {}
|
|
422
|
+
: { scope: introspection.scopes.join(" ") }),
|
|
423
|
+
...(introspection.clientId === undefined
|
|
424
|
+
? {}
|
|
425
|
+
: { client_id: String(introspection.clientId) }),
|
|
426
|
+
...(introspection.username === undefined
|
|
427
|
+
? {}
|
|
428
|
+
: { username: introspection.username }),
|
|
429
|
+
...(introspection.tokenType === undefined
|
|
430
|
+
? {}
|
|
431
|
+
: { token_type: introspection.tokenType }),
|
|
432
|
+
...(introspection.expiresAt === undefined
|
|
433
|
+
? {}
|
|
434
|
+
: { exp: oauthUnixMillisToSeconds(introspection.expiresAt) }),
|
|
435
|
+
...(introspection.issuedAt === undefined
|
|
436
|
+
? {}
|
|
437
|
+
: { iat: oauthUnixMillisToSeconds(introspection.issuedAt) }),
|
|
438
|
+
...(introspection.notBefore === undefined
|
|
439
|
+
? {}
|
|
440
|
+
: { nbf: oauthUnixMillisToSeconds(introspection.notBefore) }),
|
|
441
|
+
...(introspection.subject === undefined ? {} : { sub: introspection.subject }),
|
|
442
|
+
...(introspection.audience === undefined
|
|
443
|
+
? {}
|
|
444
|
+
: {
|
|
445
|
+
aud: Array.isArray(introspection.audience)
|
|
446
|
+
? [...introspection.audience]
|
|
447
|
+
: introspection.audience,
|
|
448
|
+
}),
|
|
449
|
+
...(introspection.issuer === undefined ? {} : { iss: introspection.issuer }),
|
|
450
|
+
...(introspection.jwtId === undefined ? {} : { jti: introspection.jwtId }),
|
|
451
|
+
...(introspection.extra === undefined ? {} : { extra: introspection.extra }),
|
|
452
|
+
};
|
|
453
|
+
};
|
|
454
|
+
const oauthRefreshTokenResponse = (input) => Effect.gen(function* () {
|
|
455
|
+
if (input.dependencies.refreshTokenGrant === undefined) {
|
|
456
|
+
return yield* oauthTokenEndpointError("unsupported_grant_type");
|
|
457
|
+
}
|
|
458
|
+
const refreshToken = oauthTokenGrantString(input.payload.refresh_token);
|
|
459
|
+
const scope = oauthTokenGrantString(input.payload.scope);
|
|
460
|
+
const result = yield* input.dependencies.refreshTokenGrant
|
|
461
|
+
.exchange({
|
|
462
|
+
grantType: input.payload.grant_type,
|
|
463
|
+
...(refreshToken === undefined
|
|
464
|
+
? {}
|
|
465
|
+
: { refreshToken: Redacted.make(OAuthRefreshToken(refreshToken)) }),
|
|
466
|
+
...(input.clientId === undefined ? {} : { clientId: input.clientId }),
|
|
467
|
+
...(scope === undefined ? {} : { scopes: scope }),
|
|
468
|
+
clientAuthenticated: input.clientAuthenticated,
|
|
469
|
+
})
|
|
470
|
+
.pipe(Effect.mapError(() => oauthInternalError("Failed to exchange OAuth token")));
|
|
471
|
+
if (!result.valid) {
|
|
472
|
+
return yield* oauthTokenEndpointError(result.reason);
|
|
473
|
+
}
|
|
474
|
+
return oauthTokenResponseHttpBody(result.tokens);
|
|
475
|
+
});
|
|
476
|
+
const oauthClientCredentialsTokenResponse = (input) => Effect.gen(function* () {
|
|
477
|
+
if (input.dependencies.clientCredentialsGrant === undefined) {
|
|
478
|
+
return yield* oauthTokenEndpointError("unsupported_grant_type");
|
|
479
|
+
}
|
|
480
|
+
const scope = oauthTokenGrantString(input.payload.scope);
|
|
481
|
+
const result = yield* input.dependencies.clientCredentialsGrant
|
|
482
|
+
.exchange({
|
|
483
|
+
grantType: input.payload.grant_type,
|
|
484
|
+
...(input.clientId === undefined ? {} : { clientId: input.clientId }),
|
|
485
|
+
...(scope === undefined ? {} : { scopes: scope }),
|
|
486
|
+
clientAuthenticated: input.clientAuthenticated,
|
|
487
|
+
})
|
|
488
|
+
.pipe(Effect.mapError(() => oauthInternalError("Failed to exchange OAuth token")));
|
|
489
|
+
if (!result.valid) {
|
|
490
|
+
return yield* oauthTokenEndpointError(result.reason);
|
|
491
|
+
}
|
|
492
|
+
return oauthTokenResponseHttpBody(result.tokens);
|
|
493
|
+
});
|
|
494
|
+
const oauthAuthorizationCodeTokenResponse = (input) => Effect.gen(function* () {
|
|
495
|
+
const code = oauthTokenGrantString(input.payload.code);
|
|
496
|
+
const codeVerifier = oauthTokenGrantString(input.payload.code_verifier);
|
|
497
|
+
const redirectUri = oauthTokenGrantString(input.payload.redirect_uri);
|
|
498
|
+
const result = yield* input.dependencies.tokenGrant
|
|
499
|
+
.exchange({
|
|
500
|
+
grantType: input.payload.grant_type,
|
|
501
|
+
...(code === undefined
|
|
502
|
+
? {}
|
|
503
|
+
: { code: Redacted.make(OAuthAuthorizationCode(code)) }),
|
|
504
|
+
...(input.clientId === undefined ? {} : { clientId: input.clientId }),
|
|
505
|
+
...(redirectUri === undefined ? {} : { redirectUri }),
|
|
506
|
+
...(codeVerifier === undefined
|
|
507
|
+
? {}
|
|
508
|
+
: { codeVerifier: Redacted.make(makeOAuthCodeVerifier(codeVerifier)) }),
|
|
509
|
+
clientAuthenticated: input.clientAuthenticated,
|
|
510
|
+
})
|
|
511
|
+
.pipe(Effect.mapError(() => oauthInternalError("Failed to exchange OAuth token")));
|
|
512
|
+
if (!result.valid) {
|
|
513
|
+
return yield* oauthTokenEndpointError(result.reason);
|
|
514
|
+
}
|
|
515
|
+
return oauthTokenResponseHttpBody(result.tokens);
|
|
516
|
+
});
|
|
260
517
|
const oauthLinkedAccountHttpBody = (account) => ({
|
|
261
518
|
accountId: account.id,
|
|
262
519
|
providerId: account.providerId,
|
|
@@ -593,6 +850,9 @@ const jwtIntrospectionHttpBody = (result) => result.active
|
|
|
593
850
|
? {}
|
|
594
851
|
: { revokedReason: result.revokedReason }),
|
|
595
852
|
};
|
|
853
|
+
export const jwtJwksHttpBody = (document) => ({
|
|
854
|
+
keys: document.keys,
|
|
855
|
+
});
|
|
596
856
|
export const totpMfaVerifyInput = (payload, options = {}) => ({
|
|
597
857
|
userId: payload.userId,
|
|
598
858
|
code: Redacted.make(payload.code),
|
|
@@ -776,6 +1036,38 @@ const activeSessionBody = (session, currentSessionId) => {
|
|
|
776
1036
|
...(session.metadata === undefined ? {} : { metadata: session.metadata }),
|
|
777
1037
|
};
|
|
778
1038
|
};
|
|
1039
|
+
export const adminSessionHttpBody = (session) => {
|
|
1040
|
+
const request = sessionRequestMetadata(session.metadata);
|
|
1041
|
+
const ip = metadataString(request, "ip");
|
|
1042
|
+
const userAgent = metadataString(request, "userAgent");
|
|
1043
|
+
const country = metadataString(request, "country");
|
|
1044
|
+
const region = metadataString(request, "region");
|
|
1045
|
+
const city = metadataString(request, "city");
|
|
1046
|
+
const latitude = metadataNumber(request, "latitude");
|
|
1047
|
+
const longitude = metadataNumber(request, "longitude");
|
|
1048
|
+
return {
|
|
1049
|
+
sessionId: session.sessionId,
|
|
1050
|
+
userId: session.userId,
|
|
1051
|
+
createdAt: session.createdAt,
|
|
1052
|
+
authTime: session.authTime,
|
|
1053
|
+
...(session.lastSeenAt === undefined
|
|
1054
|
+
? {}
|
|
1055
|
+
: { lastSeenAt: session.lastSeenAt }),
|
|
1056
|
+
expiresAt: session.expiresAt,
|
|
1057
|
+
aal: session.aal,
|
|
1058
|
+
amr: session.amr,
|
|
1059
|
+
...(session.mfaVerifiedAt === undefined
|
|
1060
|
+
? {}
|
|
1061
|
+
: { mfaVerifiedAt: session.mfaVerifiedAt }),
|
|
1062
|
+
...(ip === undefined ? {} : { ip }),
|
|
1063
|
+
...(userAgent === undefined ? {} : { userAgent }),
|
|
1064
|
+
...(country === undefined ? {} : { country }),
|
|
1065
|
+
...(region === undefined ? {} : { region }),
|
|
1066
|
+
...(city === undefined ? {} : { city }),
|
|
1067
|
+
...(latitude === undefined ? {} : { latitude }),
|
|
1068
|
+
...(longitude === undefined ? {} : { longitude }),
|
|
1069
|
+
};
|
|
1070
|
+
};
|
|
779
1071
|
export const stepUpAuthenticatedHttpBody = (session) => {
|
|
780
1072
|
const body = {
|
|
781
1073
|
type: "authenticated",
|
|
@@ -1050,6 +1342,27 @@ const trustedDeviceSetCookies = (dependencies) => Effect.gen(function* () {
|
|
|
1050
1342
|
return [cookie];
|
|
1051
1343
|
});
|
|
1052
1344
|
const catchAuthApiRateLimit = (effect, internalMessage) => effect.pipe(Effect.catchTag("RateLimitExceededError", (error) => Effect.fail(rateLimited(error.retryAfter))), Effect.catchTag("RateLimitStoreError", () => Effect.fail(passwordInternalError(internalMessage))), Effect.catchTag("PrivacyError", () => Effect.fail(passwordInternalError(internalMessage))));
|
|
1345
|
+
export class AdminSessionAuthorization extends Context.Service()("auth/AdminSessionAuthorization") {
|
|
1346
|
+
}
|
|
1347
|
+
(function (AdminSessionAuthorization) {
|
|
1348
|
+
AdminSessionAuthorization.make = (service) => AdminSessionAuthorization.of(service);
|
|
1349
|
+
})(AdminSessionAuthorization || (AdminSessionAuthorization = {}));
|
|
1350
|
+
export class AdminSecurityTimelineAuthorization extends Context.Service()("auth/AdminSecurityTimelineAuthorization") {
|
|
1351
|
+
}
|
|
1352
|
+
(function (AdminSecurityTimelineAuthorization) {
|
|
1353
|
+
AdminSecurityTimelineAuthorization.make = (service) => AdminSecurityTimelineAuthorization.of(service);
|
|
1354
|
+
})(AdminSecurityTimelineAuthorization || (AdminSecurityTimelineAuthorization = {}));
|
|
1355
|
+
export class AdminTrustedDeviceAuthorization extends Context.Service()("auth/AdminTrustedDeviceAuthorization") {
|
|
1356
|
+
}
|
|
1357
|
+
(function (AdminTrustedDeviceAuthorization) {
|
|
1358
|
+
AdminTrustedDeviceAuthorization.make = (service) => AdminTrustedDeviceAuthorization.of(service);
|
|
1359
|
+
})(AdminTrustedDeviceAuthorization || (AdminTrustedDeviceAuthorization = {}));
|
|
1360
|
+
export class OidcDiscoveryMetadata extends Context.Service()("auth/OidcDiscoveryMetadata") {
|
|
1361
|
+
}
|
|
1362
|
+
(function (OidcDiscoveryMetadata) {
|
|
1363
|
+
OidcDiscoveryMetadata.make = (service) => OidcDiscoveryMetadata.of(service);
|
|
1364
|
+
})(OidcDiscoveryMetadata || (OidcDiscoveryMetadata = {}));
|
|
1365
|
+
export const OidcDiscoveryMetadataLive = (metadata) => Layer.succeed(OidcDiscoveryMetadata, OidcDiscoveryMetadata.make({ load: () => Effect.succeed(metadata) }));
|
|
1053
1366
|
export const makePasswordSignInHandler = (dependencies) => Effect.fn("auth.http.password.sign_in")(function* ({ payload, request, }) {
|
|
1054
1367
|
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "password.sign_in");
|
|
1055
1368
|
const trustedDeviceToken = yield* trustedDeviceTokenFromRequest(dependencies.trustedDeviceCookie, request).pipe(Effect.mapError(() => passwordInternalError("Failed to read trusted device cookie")));
|
|
@@ -1263,6 +1576,60 @@ export const makeRevokeOtherSessionsHandler = (dependencies) => Effect.fn("auth.
|
|
|
1263
1576
|
})));
|
|
1264
1577
|
return HttpServerResponse.empty({ status: 204 });
|
|
1265
1578
|
});
|
|
1579
|
+
export const makeAdminSessionListHandler = (dependencies) => Effect.fn("auth.http.admin_session.list")(function* ({ query, request, }) {
|
|
1580
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "admin_session.list");
|
|
1581
|
+
const current = yield* readRequiredSession(dependencies, request);
|
|
1582
|
+
yield* dependencies.authorization.authorize({
|
|
1583
|
+
currentSession: current.currentSession,
|
|
1584
|
+
targetUserId: query.userId,
|
|
1585
|
+
action: "list",
|
|
1586
|
+
request,
|
|
1587
|
+
});
|
|
1588
|
+
const sessions = yield* dependencies.sessions
|
|
1589
|
+
.listForUser({ userId: query.userId })
|
|
1590
|
+
.pipe(Effect.mapError(() => new AuthInternalError({
|
|
1591
|
+
code: "internal_error",
|
|
1592
|
+
message: "Failed to list admin sessions",
|
|
1593
|
+
})));
|
|
1594
|
+
return { sessions: sessions.map(adminSessionHttpBody) };
|
|
1595
|
+
});
|
|
1596
|
+
export const makeAdminSessionRevokeHandler = (dependencies) => Effect.fn("auth.http.admin_session.revoke")(function* ({ payload, request, }) {
|
|
1597
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "admin_session.revoke");
|
|
1598
|
+
const current = yield* readRequiredSession(dependencies, request);
|
|
1599
|
+
yield* dependencies.authorization.authorize({
|
|
1600
|
+
currentSession: current.currentSession,
|
|
1601
|
+
targetUserId: payload.userId,
|
|
1602
|
+
action: "revoke",
|
|
1603
|
+
request,
|
|
1604
|
+
sessionId: payload.sessionId,
|
|
1605
|
+
});
|
|
1606
|
+
yield* dependencies.sessions
|
|
1607
|
+
.revokeForUser({
|
|
1608
|
+
userId: payload.userId,
|
|
1609
|
+
sessionId: payload.sessionId,
|
|
1610
|
+
reason: "admin_revoked_session",
|
|
1611
|
+
})
|
|
1612
|
+
.pipe(Effect.mapError(() => new AuthInternalError({
|
|
1613
|
+
code: "internal_error",
|
|
1614
|
+
message: "Failed to revoke admin session",
|
|
1615
|
+
})));
|
|
1616
|
+
return HttpServerResponse.empty({ status: 204 });
|
|
1617
|
+
});
|
|
1618
|
+
export const makeAdminSessionRevokeAllHandler = (dependencies) => Effect.fn("auth.http.admin_session.revoke_all")(function* ({ payload, request, }) {
|
|
1619
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "admin_session.revoke_all");
|
|
1620
|
+
const current = yield* readRequiredSession(dependencies, request);
|
|
1621
|
+
yield* dependencies.authorization.authorize({
|
|
1622
|
+
currentSession: current.currentSession,
|
|
1623
|
+
targetUserId: payload.userId,
|
|
1624
|
+
action: "revoke_all",
|
|
1625
|
+
request,
|
|
1626
|
+
});
|
|
1627
|
+
yield* dependencies.sessions.revokeAllForUser(payload.userId).pipe(Effect.mapError(() => new AuthInternalError({
|
|
1628
|
+
code: "internal_error",
|
|
1629
|
+
message: "Failed to revoke admin sessions",
|
|
1630
|
+
})));
|
|
1631
|
+
return HttpServerResponse.empty({ status: 204 });
|
|
1632
|
+
});
|
|
1266
1633
|
export const makeLoginNotificationReportHandler = (dependencies) => Effect.fn("auth.http.security.login_notification.report")(function* ({ payload, }) {
|
|
1267
1634
|
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "security.login_notification.report");
|
|
1268
1635
|
if (dependencies.loginNotification === undefined) {
|
|
@@ -1314,6 +1681,7 @@ const securityTimelineListInput = (query, userId) => ({
|
|
|
1314
1681
|
...(query.types === undefined ? {} : { types: query.types }),
|
|
1315
1682
|
...(query.categories === undefined ? {} : { categories: query.categories }),
|
|
1316
1683
|
});
|
|
1684
|
+
const adminSecurityTimelineListInput = (query) => securityTimelineListInput(query, query.userId);
|
|
1317
1685
|
export const makeSecurityTimelineListHandler = (dependencies) => Effect.fn("auth.http.security_timeline.list")(function* ({ query, request, }) {
|
|
1318
1686
|
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "security_timeline.list");
|
|
1319
1687
|
const current = yield* readRequiredSession(dependencies, request);
|
|
@@ -1325,6 +1693,22 @@ export const makeSecurityTimelineListHandler = (dependencies) => Effect.fn("auth
|
|
|
1325
1693
|
})));
|
|
1326
1694
|
return { events: events.map(securityTimelineEventHttpBody) };
|
|
1327
1695
|
});
|
|
1696
|
+
export const makeAdminSecurityTimelineListHandler = (dependencies) => Effect.fn("auth.http.admin_security_timeline.list")(function* ({ query, request, }) {
|
|
1697
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "admin_security_timeline.list");
|
|
1698
|
+
const current = yield* readRequiredSession(dependencies, request);
|
|
1699
|
+
yield* dependencies.authorization.authorize({
|
|
1700
|
+
currentSession: current.currentSession,
|
|
1701
|
+
targetUserId: query.userId,
|
|
1702
|
+
request,
|
|
1703
|
+
});
|
|
1704
|
+
const events = yield* dependencies.securityTimeline
|
|
1705
|
+
.listByUser(adminSecurityTimelineListInput(query))
|
|
1706
|
+
.pipe(Effect.mapError(() => new AuthInternalError({
|
|
1707
|
+
code: "internal_error",
|
|
1708
|
+
message: "Failed to list admin security timeline",
|
|
1709
|
+
})));
|
|
1710
|
+
return { events: events.map(securityTimelineEventHttpBody) };
|
|
1711
|
+
});
|
|
1328
1712
|
export const trustedDeviceHttpBody = (device) => ({
|
|
1329
1713
|
deviceId: device.tokenHash,
|
|
1330
1714
|
createdAt: device.createdAt,
|
|
@@ -1358,6 +1742,45 @@ export const makeTrustedDeviceRevokeHandler = (dependencies) => Effect.fn("auth.
|
|
|
1358
1742
|
})));
|
|
1359
1743
|
return HttpServerResponse.empty({ status: 204 });
|
|
1360
1744
|
});
|
|
1745
|
+
export const makeAdminTrustedDeviceListHandler = (dependencies) => Effect.fn("auth.http.admin_trusted_device.list")(function* ({ query, request, }) {
|
|
1746
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "admin_trusted_device.list");
|
|
1747
|
+
const current = yield* readRequiredSession(dependencies, request);
|
|
1748
|
+
yield* dependencies.authorization.authorize({
|
|
1749
|
+
currentSession: current.currentSession,
|
|
1750
|
+
targetUserId: query.userId,
|
|
1751
|
+
action: "list",
|
|
1752
|
+
request,
|
|
1753
|
+
});
|
|
1754
|
+
const now = yield* currentUnixMillis;
|
|
1755
|
+
const devices = yield* dependencies.trustedDevices
|
|
1756
|
+
.listForUser({ userId: query.userId, now })
|
|
1757
|
+
.pipe(Effect.mapError(() => new AuthInternalError({
|
|
1758
|
+
code: "internal_error",
|
|
1759
|
+
message: "Failed to list admin trusted devices",
|
|
1760
|
+
})));
|
|
1761
|
+
return { devices: devices.map(trustedDeviceHttpBody) };
|
|
1762
|
+
});
|
|
1763
|
+
export const makeAdminTrustedDeviceRevokeHandler = (dependencies) => Effect.fn("auth.http.admin_trusted_device.revoke")(function* ({ payload, request, }) {
|
|
1764
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "admin_trusted_device.revoke");
|
|
1765
|
+
const current = yield* readRequiredSession(dependencies, request);
|
|
1766
|
+
yield* dependencies.authorization.authorize({
|
|
1767
|
+
currentSession: current.currentSession,
|
|
1768
|
+
targetUserId: payload.userId,
|
|
1769
|
+
action: "revoke",
|
|
1770
|
+
request,
|
|
1771
|
+
deviceId: payload.deviceId,
|
|
1772
|
+
});
|
|
1773
|
+
yield* dependencies.trustedDevices
|
|
1774
|
+
.revokeForUser({
|
|
1775
|
+
userId: payload.userId,
|
|
1776
|
+
tokenHash: payload.deviceId,
|
|
1777
|
+
})
|
|
1778
|
+
.pipe(Effect.mapError(() => new AuthInternalError({
|
|
1779
|
+
code: "internal_error",
|
|
1780
|
+
message: "Failed to revoke admin trusted device",
|
|
1781
|
+
})));
|
|
1782
|
+
return HttpServerResponse.empty({ status: 204 });
|
|
1783
|
+
});
|
|
1361
1784
|
export const makeEmailVerificationStartHandler = (dependencies) => Effect.fn("auth.http.email_verification.start")(function* ({ payload, }) {
|
|
1362
1785
|
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "email_verification.start");
|
|
1363
1786
|
const input = emailVerificationStartInput(payload);
|
|
@@ -1458,6 +1881,133 @@ export const makeOAuthAuthorizationStartHandler = (dependencies) => Effect.fn("a
|
|
|
1458
1881
|
}
|
|
1459
1882
|
return oauthAuthorizationStartedHttpBody(started);
|
|
1460
1883
|
});
|
|
1884
|
+
export const makeOAuthProviderAuthorizationHandler = (dependencies) => Effect.fn("auth.http.oauth.authorize")(function* ({ query, }) {
|
|
1885
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "oauth.authorize");
|
|
1886
|
+
const result = yield* dependencies.authorization
|
|
1887
|
+
.authorize({
|
|
1888
|
+
responseType: query.response_type,
|
|
1889
|
+
...(query.client_id === undefined ? {} : { clientId: query.client_id }),
|
|
1890
|
+
...(query.redirect_uri === undefined
|
|
1891
|
+
? {}
|
|
1892
|
+
: { redirectUri: query.redirect_uri }),
|
|
1893
|
+
...(query.scope === undefined ? {} : { scopes: query.scope }),
|
|
1894
|
+
...(query.state === undefined ? {} : { state: query.state }),
|
|
1895
|
+
...(query.code_challenge === undefined
|
|
1896
|
+
? {}
|
|
1897
|
+
: { codeChallenge: query.code_challenge }),
|
|
1898
|
+
...(query.code_challenge_method === undefined
|
|
1899
|
+
? {}
|
|
1900
|
+
: { codeChallengeMethod: query.code_challenge_method }),
|
|
1901
|
+
})
|
|
1902
|
+
.pipe(Effect.mapError(() => oauthInternalError("Failed to authorize OAuth request")));
|
|
1903
|
+
if (result.valid) {
|
|
1904
|
+
return oauthAuthorizationRedirect(result.redirectUri, {
|
|
1905
|
+
code: Redacted.value(result.code.code),
|
|
1906
|
+
state: result.state,
|
|
1907
|
+
});
|
|
1908
|
+
}
|
|
1909
|
+
if (result.redirectUri !== undefined) {
|
|
1910
|
+
return oauthAuthorizationRedirect(result.redirectUri, {
|
|
1911
|
+
error: result.reason,
|
|
1912
|
+
error_description: result.errorDescription,
|
|
1913
|
+
state: result.state,
|
|
1914
|
+
});
|
|
1915
|
+
}
|
|
1916
|
+
return yield* oauthAuthorizationEndpointError(result.reason, result.errorDescription);
|
|
1917
|
+
});
|
|
1918
|
+
export const makeOAuthAuthorizationCodeTokenHandler = (dependencies) => Effect.fn("auth.http.oauth.token")(function* ({ request, }) {
|
|
1919
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "oauth.token");
|
|
1920
|
+
const payload = yield* oauthTokenRequestBody(request);
|
|
1921
|
+
const { clientId, clientAuthenticated } = yield* oauthClientEndpointAuthentication({
|
|
1922
|
+
request,
|
|
1923
|
+
payload,
|
|
1924
|
+
authenticateClient: dependencies.authenticateClient,
|
|
1925
|
+
invalidRequest: () => oauthTokenEndpointError("invalid_request"),
|
|
1926
|
+
invalidClient: () => oauthTokenEndpointError("invalid_client"),
|
|
1927
|
+
});
|
|
1928
|
+
if (payload.grant_type === "refresh_token") {
|
|
1929
|
+
return yield* oauthRefreshTokenResponse({
|
|
1930
|
+
dependencies,
|
|
1931
|
+
payload,
|
|
1932
|
+
...(clientId === undefined ? {} : { clientId }),
|
|
1933
|
+
clientAuthenticated,
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
if (payload.grant_type === "client_credentials") {
|
|
1937
|
+
return yield* oauthClientCredentialsTokenResponse({
|
|
1938
|
+
dependencies,
|
|
1939
|
+
payload,
|
|
1940
|
+
...(clientId === undefined ? {} : { clientId }),
|
|
1941
|
+
clientAuthenticated,
|
|
1942
|
+
});
|
|
1943
|
+
}
|
|
1944
|
+
return yield* oauthAuthorizationCodeTokenResponse({
|
|
1945
|
+
dependencies,
|
|
1946
|
+
payload,
|
|
1947
|
+
...(clientId === undefined ? {} : { clientId }),
|
|
1948
|
+
clientAuthenticated,
|
|
1949
|
+
});
|
|
1950
|
+
});
|
|
1951
|
+
export const makeOAuthTokenRevocationHandler = (dependencies) => Effect.fn("auth.http.oauth.revoke")(function* ({ request, }) {
|
|
1952
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "oauth.revoke");
|
|
1953
|
+
const payload = yield* oauthTokenRevocationRequestBody(request);
|
|
1954
|
+
const { clientId, clientAuthenticated } = yield* oauthClientEndpointAuthentication({
|
|
1955
|
+
request,
|
|
1956
|
+
payload,
|
|
1957
|
+
authenticateClient: dependencies.authenticateClient,
|
|
1958
|
+
invalidRequest: () => oauthTokenRevocationEndpointError("invalid_request"),
|
|
1959
|
+
invalidClient: () => oauthTokenRevocationEndpointError("invalid_client"),
|
|
1960
|
+
});
|
|
1961
|
+
const token = oauthTokenGrantString(payload.token);
|
|
1962
|
+
const tokenTypeHint = oauthTokenGrantString(payload.token_type_hint);
|
|
1963
|
+
const result = yield* dependencies.tokenRevocation
|
|
1964
|
+
.revoke({
|
|
1965
|
+
...(token === undefined ? {} : { token: Redacted.make(token) }),
|
|
1966
|
+
...(tokenTypeHint === undefined ? {} : { tokenTypeHint }),
|
|
1967
|
+
...(clientId === undefined ? {} : { clientId }),
|
|
1968
|
+
clientAuthenticated,
|
|
1969
|
+
})
|
|
1970
|
+
.pipe(Effect.mapError(() => oauthInternalError("Failed to revoke OAuth token")));
|
|
1971
|
+
if (!result.valid) {
|
|
1972
|
+
return yield* oauthTokenRevocationEndpointError(result.reason);
|
|
1973
|
+
}
|
|
1974
|
+
return HttpServerResponse.empty({ status: 204 });
|
|
1975
|
+
});
|
|
1976
|
+
export const makeOAuthTokenIntrospectionHandler = (dependencies) => Effect.fn("auth.http.oauth.introspect")(function* ({ request, }) {
|
|
1977
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "oauth.introspect");
|
|
1978
|
+
const payload = yield* oauthTokenIntrospectionRequestBody(request);
|
|
1979
|
+
const { clientId, clientAuthenticated } = yield* oauthClientEndpointAuthentication({
|
|
1980
|
+
request,
|
|
1981
|
+
payload,
|
|
1982
|
+
authenticateClient: dependencies.authenticateClient,
|
|
1983
|
+
invalidRequest: () => oauthTokenIntrospectionEndpointError("invalid_request"),
|
|
1984
|
+
invalidClient: () => oauthTokenIntrospectionEndpointError("invalid_client"),
|
|
1985
|
+
});
|
|
1986
|
+
const token = oauthTokenGrantString(payload.token);
|
|
1987
|
+
const tokenTypeHint = oauthTokenGrantString(payload.token_type_hint);
|
|
1988
|
+
const result = yield* dependencies.tokenIntrospection
|
|
1989
|
+
.introspect({
|
|
1990
|
+
...(token === undefined ? {} : { token: Redacted.make(token) }),
|
|
1991
|
+
...(tokenTypeHint === undefined ? {} : { tokenTypeHint }),
|
|
1992
|
+
...(clientId === undefined ? {} : { clientId }),
|
|
1993
|
+
clientAuthenticated,
|
|
1994
|
+
})
|
|
1995
|
+
.pipe(Effect.mapError(() => oauthInternalError("Failed to introspect OAuth token")));
|
|
1996
|
+
if (!result.valid) {
|
|
1997
|
+
return yield* oauthTokenIntrospectionEndpointError(result.reason);
|
|
1998
|
+
}
|
|
1999
|
+
return oauthTokenIntrospectionResponseHttpBody(result.introspection);
|
|
2000
|
+
});
|
|
2001
|
+
const makeOAuthTokenRevocationNotConfiguredHandler = () => Effect.fn("auth.http.oauth.revoke_not_configured")(function* ({ request, }) {
|
|
2002
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "oauth.revoke");
|
|
2003
|
+
yield* oauthTokenRevocationRequestBody(request);
|
|
2004
|
+
return yield* oauthTokenRevocationEndpointError("invalid_request");
|
|
2005
|
+
});
|
|
2006
|
+
const makeOAuthTokenIntrospectionNotConfiguredHandler = () => Effect.fn("auth.http.oauth.introspect_not_configured")(function* ({ request, }) {
|
|
2007
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "oauth.introspect");
|
|
2008
|
+
yield* oauthTokenIntrospectionRequestBody(request);
|
|
2009
|
+
return yield* oauthTokenIntrospectionEndpointError("invalid_request");
|
|
2010
|
+
});
|
|
1461
2011
|
export const makeOAuthAccountUnlinkHandler = (dependencies) => Effect.fn("auth.http.oauth.account_unlink")(function* ({ payload, request, }) {
|
|
1462
2012
|
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "oauth.account_unlink");
|
|
1463
2013
|
const session = yield* readRequiredSession(dependencies, request);
|
|
@@ -1714,6 +2264,15 @@ export const makeJwtRevokeHandler = (dependencies) => Effect.fn("auth.http.jwt.r
|
|
|
1714
2264
|
.pipe(Effect.mapError(jwtRevocationHttpError));
|
|
1715
2265
|
return HttpServerResponse.empty({ status: 204 });
|
|
1716
2266
|
});
|
|
2267
|
+
export const makeJwtJwksHandler = (dependencies) => Effect.fn("auth.http.jwt.jwks")(function* (_) {
|
|
2268
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "jwt.jwks");
|
|
2269
|
+
const document = yield* dependencies.jwks.document().pipe(Effect.mapError(() => jwtInternalError("Failed to load JWT JWKS document")));
|
|
2270
|
+
return jwtJwksHttpBody(document);
|
|
2271
|
+
});
|
|
2272
|
+
export const makeOidcDiscoveryMetadataHandler = (dependencies) => Effect.fn("auth.http.oidc.discovery_metadata")(function* (_) {
|
|
2273
|
+
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "oidc.discovery_metadata");
|
|
2274
|
+
return yield* dependencies.metadata.load().pipe(Effect.mapError(() => jwtInternalError("Failed to load OIDC discovery metadata")));
|
|
2275
|
+
});
|
|
1717
2276
|
export const makeMfaOptionsHandler = (dependencies) => Effect.fn("auth.http.mfa.options")(function* ({ payload, }) {
|
|
1718
2277
|
yield* Effect.annotateCurrentSpan("auth.http.endpoint", "mfa.options");
|
|
1719
2278
|
const pending = yield* dependencies.authFlowState
|
|
@@ -2051,6 +2610,14 @@ export class SessionApi extends HttpApiGroup.make("session")
|
|
|
2051
2610
|
.add(currentSessionEndpoint, refreshSessionEndpoint.middleware(AuthOriginCheckMiddleware), logoutEndpoint.middleware(AuthOriginCheckMiddleware), listSessionsEndpoint, revokeSessionEndpoint.middleware(AuthOriginCheckMiddleware), revokeOtherSessionsEndpoint.middleware(AuthOriginCheckMiddleware))
|
|
2052
2611
|
.prefix("/auth") {
|
|
2053
2612
|
}
|
|
2613
|
+
export class AdminSessionApi extends HttpApiGroup.make("adminSession")
|
|
2614
|
+
.add(adminSessionListEndpoint, adminSessionRevokeEndpoint, adminSessionRevokeAllEndpoint)
|
|
2615
|
+
.prefix("/auth/admin/sessions")
|
|
2616
|
+
.middleware(AuthSchemaErrorMiddleware)
|
|
2617
|
+
.middleware(AuthOriginCheckMiddleware) {
|
|
2618
|
+
}
|
|
2619
|
+
export class AdminSessionHttpApi extends HttpApi.make("AdminSessionHttpApi").add(AdminSessionApi) {
|
|
2620
|
+
}
|
|
2054
2621
|
export class EmailVerificationApi extends HttpApiGroup.make("emailVerification")
|
|
2055
2622
|
.add(emailVerificationStartEndpoint.middleware(AuthRateLimitMiddleware), emailVerificationVerifyEndpoint)
|
|
2056
2623
|
.prefix("/auth/email-verification")
|
|
@@ -2075,6 +2642,20 @@ export class OAuthApi extends HttpApiGroup.make("oauth")
|
|
|
2075
2642
|
.middleware(AuthSchemaErrorMiddleware)
|
|
2076
2643
|
.middleware(AuthOriginCheckMiddleware) {
|
|
2077
2644
|
}
|
|
2645
|
+
export class OAuthTokenApi extends HttpApiGroup.make("oauthToken")
|
|
2646
|
+
.add(oauthTokenEndpoint, oauthTokenIntrospectionEndpoint, oauthTokenRevocationEndpoint)
|
|
2647
|
+
.prefix("/auth/oauth")
|
|
2648
|
+
.middleware(AuthSchemaErrorMiddleware) {
|
|
2649
|
+
}
|
|
2650
|
+
export class OAuthTokenHttpApi extends HttpApi.make("OAuthTokenHttpApi").add(OAuthTokenApi) {
|
|
2651
|
+
}
|
|
2652
|
+
export class OAuthProviderAuthorizationApi extends HttpApiGroup.make("oauthProviderAuthorization")
|
|
2653
|
+
.add(oauthProviderAuthorizeEndpoint)
|
|
2654
|
+
.prefix("/auth/oauth")
|
|
2655
|
+
.middleware(AuthSchemaErrorMiddleware) {
|
|
2656
|
+
}
|
|
2657
|
+
export class OAuthProviderAuthorizationHttpApi extends HttpApi.make("OAuthProviderAuthorizationHttpApi").add(OAuthProviderAuthorizationApi) {
|
|
2658
|
+
}
|
|
2078
2659
|
export class LoginApprovalApi extends HttpApiGroup.make("loginApproval")
|
|
2079
2660
|
.add(loginApprovalApproveEndpoint, loginApprovalStatusEndpoint, loginApprovalFinalizeEndpoint)
|
|
2080
2661
|
.prefix("/auth/login-approval")
|
|
@@ -2109,6 +2690,20 @@ export class JwtApi extends HttpApiGroup.make("jwt")
|
|
|
2109
2690
|
.prefix("/auth/jwt")
|
|
2110
2691
|
.middleware(AuthSchemaErrorMiddleware) {
|
|
2111
2692
|
}
|
|
2693
|
+
export class JwtDiscoveryApi extends HttpApiGroup.make("jwtDiscovery")
|
|
2694
|
+
.add(jwtJwksEndpoint)
|
|
2695
|
+
.prefix("/.well-known")
|
|
2696
|
+
.middleware(AuthSchemaErrorMiddleware) {
|
|
2697
|
+
}
|
|
2698
|
+
export class JwtDiscoveryHttpApi extends HttpApi.make("JwtDiscoveryHttpApi").add(JwtDiscoveryApi) {
|
|
2699
|
+
}
|
|
2700
|
+
export class OidcDiscoveryApi extends HttpApiGroup.make("oidcDiscovery")
|
|
2701
|
+
.add(oidcDiscoveryMetadataEndpoint)
|
|
2702
|
+
.prefix("/.well-known")
|
|
2703
|
+
.middleware(AuthSchemaErrorMiddleware) {
|
|
2704
|
+
}
|
|
2705
|
+
export class OidcDiscoveryHttpApi extends HttpApi.make("OidcDiscoveryHttpApi").add(OidcDiscoveryApi) {
|
|
2706
|
+
}
|
|
2112
2707
|
export class SecurityApi extends HttpApiGroup.make("security")
|
|
2113
2708
|
.add(loginNotificationReportEndpoint)
|
|
2114
2709
|
.prefix("/auth/security")
|
|
@@ -2124,6 +2719,14 @@ export class SecurityTimelineApi extends HttpApiGroup.make("securityTimeline")
|
|
|
2124
2719
|
export class SecurityTimelineHttpApi extends HttpApi.make("SecurityTimelineHttpApi")
|
|
2125
2720
|
.add(SecurityTimelineApi) {
|
|
2126
2721
|
}
|
|
2722
|
+
export class AdminSecurityTimelineApi extends HttpApiGroup.make("adminSecurityTimeline")
|
|
2723
|
+
.add(adminSecurityTimelineListEndpoint)
|
|
2724
|
+
.prefix("/auth/admin/security")
|
|
2725
|
+
.middleware(AuthSchemaErrorMiddleware)
|
|
2726
|
+
.middleware(AuthOriginCheckMiddleware) {
|
|
2727
|
+
}
|
|
2728
|
+
export class AdminSecurityTimelineHttpApi extends HttpApi.make("AdminSecurityTimelineHttpApi").add(AdminSecurityTimelineApi) {
|
|
2729
|
+
}
|
|
2127
2730
|
export class TrustedDeviceApi extends HttpApiGroup.make("trustedDevice")
|
|
2128
2731
|
.add(trustedDeviceListEndpoint, trustedDeviceRevokeEndpoint)
|
|
2129
2732
|
.prefix("/auth/trusted-devices")
|
|
@@ -2133,6 +2736,14 @@ export class TrustedDeviceApi extends HttpApiGroup.make("trustedDevice")
|
|
|
2133
2736
|
export class TrustedDeviceHttpApi extends HttpApi.make("TrustedDeviceHttpApi")
|
|
2134
2737
|
.add(TrustedDeviceApi) {
|
|
2135
2738
|
}
|
|
2739
|
+
export class AdminTrustedDeviceApi extends HttpApiGroup.make("adminTrustedDevice")
|
|
2740
|
+
.add(adminTrustedDeviceListEndpoint, adminTrustedDeviceRevokeEndpoint)
|
|
2741
|
+
.prefix("/auth/admin/trusted-devices")
|
|
2742
|
+
.middleware(AuthSchemaErrorMiddleware)
|
|
2743
|
+
.middleware(AuthOriginCheckMiddleware) {
|
|
2744
|
+
}
|
|
2745
|
+
export class AdminTrustedDeviceHttpApi extends HttpApi.make("AdminTrustedDeviceHttpApi").add(AdminTrustedDeviceApi) {
|
|
2746
|
+
}
|
|
2136
2747
|
export class AuthApi extends HttpApi.make("AuthApi")
|
|
2137
2748
|
.add(PasswordApi)
|
|
2138
2749
|
.add(SessionApi)
|
|
@@ -2199,6 +2810,20 @@ export const SessionApiLive = HttpApiBuilder.group(AuthApi, "session", Effect.fn
|
|
|
2199
2810
|
.handle("revoke", makeRevokeSessionHandler({ sessions, sessionCookie, authHttp }))
|
|
2200
2811
|
.handle("revokeOthers", makeRevokeOtherSessionsHandler({ sessions, sessionCookie }));
|
|
2201
2812
|
}));
|
|
2813
|
+
export const AdminSessionApiLive = HttpApiBuilder.group(AdminSessionHttpApi, "adminSession", Effect.fn("auth.http.admin_session.group")(function* (handlers) {
|
|
2814
|
+
const sessions = yield* Sessions;
|
|
2815
|
+
const sessionCookie = yield* SessionCookie;
|
|
2816
|
+
const authorization = yield* AdminSessionAuthorization;
|
|
2817
|
+
return handlers
|
|
2818
|
+
.handle("list", makeAdminSessionListHandler({ sessions, sessionCookie, authorization }))
|
|
2819
|
+
.handle("revoke", makeAdminSessionRevokeHandler({ sessions, sessionCookie, authorization }))
|
|
2820
|
+
.handle("revokeAll", makeAdminSessionRevokeAllHandler({
|
|
2821
|
+
sessions,
|
|
2822
|
+
sessionCookie,
|
|
2823
|
+
authorization,
|
|
2824
|
+
}));
|
|
2825
|
+
}));
|
|
2826
|
+
export const AdminSessionHttpApiLive = HttpApiBuilder.layer(AdminSessionHttpApi).pipe(Layer.provide(AdminSessionApiLive), Layer.provide(AuthOriginCheckMiddlewareConfigLive), Layer.provide(AuthSchemaErrorMiddlewareLive));
|
|
2202
2827
|
export const EmailVerificationApiLive = HttpApiBuilder.group(AuthApi, "emailVerification", Effect.fn("auth.http.email_verification.group")(function* (handlers) {
|
|
2203
2828
|
const emailVerificationFlow = yield* EmailVerificationFlow;
|
|
2204
2829
|
const emailVerification = yield* EmailVerification;
|
|
@@ -2309,6 +2934,62 @@ export const SecurityTimelineApiLive = HttpApiBuilder.group(SecurityTimelineHttp
|
|
|
2309
2934
|
}));
|
|
2310
2935
|
}));
|
|
2311
2936
|
export const SecurityTimelineHttpApiLive = HttpApiBuilder.layer(SecurityTimelineHttpApi).pipe(Layer.provide(SecurityTimelineApiLive), Layer.provide(AuthOriginCheckMiddlewareConfigLive), Layer.provide(AuthSchemaErrorMiddlewareLive));
|
|
2937
|
+
export const OAuthProviderAuthorizationApiLive = HttpApiBuilder.group(OAuthProviderAuthorizationHttpApi, "oauthProviderAuthorization", Effect.fn("auth.http.oauth_provider_authorization.group")(function* (handlers) {
|
|
2938
|
+
const authorization = yield* OAuthProviderAuthorization;
|
|
2939
|
+
return handlers.handle("authorize", makeOAuthProviderAuthorizationHandler({ authorization }));
|
|
2940
|
+
}));
|
|
2941
|
+
export const OAuthProviderAuthorizationHttpApiLive = HttpApiBuilder.layer(OAuthProviderAuthorizationHttpApi).pipe(Layer.provide(OAuthProviderAuthorizationApiLive), Layer.provide(AuthSchemaErrorMiddlewareLive));
|
|
2942
|
+
export const OAuthTokenApiLive = HttpApiBuilder.group(OAuthTokenHttpApi, "oauthToken", Effect.fn("auth.http.oauth_token.group")(function* (handlers) {
|
|
2943
|
+
const tokenGrant = yield* OAuthAuthorizationCodeTokenGrant;
|
|
2944
|
+
const refreshTokenGrant = yield* Effect.serviceOption(OAuthRefreshTokenGrant);
|
|
2945
|
+
const clientCredentialsGrant = yield* Effect.serviceOption(OAuthClientCredentialsGrant);
|
|
2946
|
+
const tokenIntrospection = yield* Effect.serviceOption(OAuthTokenIntrospection);
|
|
2947
|
+
const tokenRevocation = yield* Effect.serviceOption(OAuthTokenRevocation);
|
|
2948
|
+
return handlers
|
|
2949
|
+
.handle("token", makeOAuthAuthorizationCodeTokenHandler({
|
|
2950
|
+
tokenGrant,
|
|
2951
|
+
...(Option.isNone(refreshTokenGrant)
|
|
2952
|
+
? {}
|
|
2953
|
+
: { refreshTokenGrant: refreshTokenGrant.value }),
|
|
2954
|
+
...(Option.isNone(clientCredentialsGrant)
|
|
2955
|
+
? {}
|
|
2956
|
+
: { clientCredentialsGrant: clientCredentialsGrant.value }),
|
|
2957
|
+
}))
|
|
2958
|
+
.handle("introspect", Option.isNone(tokenIntrospection)
|
|
2959
|
+
? makeOAuthTokenIntrospectionNotConfiguredHandler()
|
|
2960
|
+
: makeOAuthTokenIntrospectionHandler({
|
|
2961
|
+
tokenIntrospection: tokenIntrospection.value,
|
|
2962
|
+
}))
|
|
2963
|
+
.handle("revoke", Option.isNone(tokenRevocation)
|
|
2964
|
+
? makeOAuthTokenRevocationNotConfiguredHandler()
|
|
2965
|
+
: makeOAuthTokenRevocationHandler({
|
|
2966
|
+
tokenRevocation: tokenRevocation.value,
|
|
2967
|
+
}));
|
|
2968
|
+
}));
|
|
2969
|
+
export const OAuthTokenHttpApiLive = HttpApiBuilder.layer(OAuthTokenHttpApi).pipe(Layer.provide(OAuthTokenApiLive), Layer.provide(AuthSchemaErrorMiddlewareLive));
|
|
2970
|
+
export const JwtDiscoveryApiLive = HttpApiBuilder.group(JwtDiscoveryHttpApi, "jwtDiscovery", Effect.fn("auth.http.jwt_discovery.group")(function* (handlers) {
|
|
2971
|
+
const jwks = yield* Jwks;
|
|
2972
|
+
return handlers.handle("jwks", makeJwtJwksHandler({ jwks }));
|
|
2973
|
+
}));
|
|
2974
|
+
export const JwtDiscoveryHttpApiLive = HttpApiBuilder.layer(JwtDiscoveryHttpApi).pipe(Layer.provide(JwtDiscoveryApiLive), Layer.provide(AuthSchemaErrorMiddlewareLive));
|
|
2975
|
+
export const OidcDiscoveryApiLive = HttpApiBuilder.group(OidcDiscoveryHttpApi, "oidcDiscovery", Effect.fn("auth.http.oidc_discovery.group")(function* (handlers) {
|
|
2976
|
+
const metadata = yield* OidcDiscoveryMetadata;
|
|
2977
|
+
return handlers.handle("openidConfiguration", makeOidcDiscoveryMetadataHandler({ metadata }));
|
|
2978
|
+
}));
|
|
2979
|
+
export const OidcDiscoveryHttpApiLive = HttpApiBuilder.layer(OidcDiscoveryHttpApi).pipe(Layer.provide(OidcDiscoveryApiLive), Layer.provide(AuthSchemaErrorMiddlewareLive));
|
|
2980
|
+
export const AdminSecurityTimelineApiLive = HttpApiBuilder.group(AdminSecurityTimelineHttpApi, "adminSecurityTimeline", Effect.fn("auth.http.admin_security_timeline.group")(function* (handlers) {
|
|
2981
|
+
const sessions = yield* Sessions;
|
|
2982
|
+
const sessionCookie = yield* SessionCookie;
|
|
2983
|
+
const securityTimeline = yield* SecurityTimelineStore;
|
|
2984
|
+
const authorization = yield* AdminSecurityTimelineAuthorization;
|
|
2985
|
+
return handlers.handle("list", makeAdminSecurityTimelineListHandler({
|
|
2986
|
+
sessions,
|
|
2987
|
+
sessionCookie,
|
|
2988
|
+
securityTimeline,
|
|
2989
|
+
authorization,
|
|
2990
|
+
}));
|
|
2991
|
+
}));
|
|
2992
|
+
export const AdminSecurityTimelineHttpApiLive = HttpApiBuilder.layer(AdminSecurityTimelineHttpApi).pipe(Layer.provide(AdminSecurityTimelineApiLive), Layer.provide(AuthOriginCheckMiddlewareConfigLive), Layer.provide(AuthSchemaErrorMiddlewareLive));
|
|
2312
2993
|
export const TrustedDeviceApiLive = HttpApiBuilder.group(TrustedDeviceHttpApi, "trustedDevice", Effect.fn("auth.http.trusted_device.group")(function* (handlers) {
|
|
2313
2994
|
const sessions = yield* Sessions;
|
|
2314
2995
|
const sessionCookie = yield* SessionCookie;
|
|
@@ -2318,6 +2999,26 @@ export const TrustedDeviceApiLive = HttpApiBuilder.group(TrustedDeviceHttpApi, "
|
|
|
2318
2999
|
.handle("revoke", makeTrustedDeviceRevokeHandler({ sessions, sessionCookie, trustedDevices }));
|
|
2319
3000
|
}));
|
|
2320
3001
|
export const TrustedDeviceHttpApiLive = HttpApiBuilder.layer(TrustedDeviceHttpApi).pipe(Layer.provide(TrustedDeviceApiLive), Layer.provide(AuthOriginCheckMiddlewareConfigLive), Layer.provide(AuthSchemaErrorMiddlewareLive));
|
|
3002
|
+
export const AdminTrustedDeviceApiLive = HttpApiBuilder.group(AdminTrustedDeviceHttpApi, "adminTrustedDevice", Effect.fn("auth.http.admin_trusted_device.group")(function* (handlers) {
|
|
3003
|
+
const sessions = yield* Sessions;
|
|
3004
|
+
const sessionCookie = yield* SessionCookie;
|
|
3005
|
+
const trustedDevices = yield* TrustedDeviceStore;
|
|
3006
|
+
const authorization = yield* AdminTrustedDeviceAuthorization;
|
|
3007
|
+
return handlers
|
|
3008
|
+
.handle("list", makeAdminTrustedDeviceListHandler({
|
|
3009
|
+
sessions,
|
|
3010
|
+
sessionCookie,
|
|
3011
|
+
trustedDevices,
|
|
3012
|
+
authorization,
|
|
3013
|
+
}))
|
|
3014
|
+
.handle("revoke", makeAdminTrustedDeviceRevokeHandler({
|
|
3015
|
+
sessions,
|
|
3016
|
+
sessionCookie,
|
|
3017
|
+
trustedDevices,
|
|
3018
|
+
authorization,
|
|
3019
|
+
}));
|
|
3020
|
+
}));
|
|
3021
|
+
export const AdminTrustedDeviceHttpApiLive = HttpApiBuilder.layer(AdminTrustedDeviceHttpApi).pipe(Layer.provide(AdminTrustedDeviceApiLive), Layer.provide(AuthOriginCheckMiddlewareConfigLive), Layer.provide(AuthSchemaErrorMiddlewareLive));
|
|
2321
3022
|
const AuthHttpApiBaseLive = HttpApiBuilder.layer(AuthApi).pipe(Layer.provide(PasswordApiLive), Layer.provide(SessionApiLive), Layer.provide(EmailVerificationApiLive), Layer.provide(EmailOtpApiLive), Layer.provide(MagicLinkApiLive), Layer.provide(LoginApprovalApiLive), Layer.provide(SecurityApiLive), Layer.provide(AuthOriginCheckMiddlewareConfigLive), Layer.provide(AuthSchemaErrorMiddlewareLive));
|
|
2322
3023
|
export const AuthHttpApiBareLive = AuthHttpApiBaseLive.pipe(Layer.provide(AuthApiRateLimitNoopLive));
|
|
2323
3024
|
export const AuthHttpApiLive = AuthHttpApiBaseLive.pipe(Layer.provide(AuthApiRateLimitLive));
|