@effect-auth/core 0.1.0-alpha.1 → 0.1.0-alpha.2
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 +622 -61
- package/dist/AuditLog.d.ts.map +1 -1
- package/dist/AuditLog.js +1 -1
- package/dist/AuditLog.js.map +1 -1
- package/dist/AuthConfig.d.ts +51 -0
- package/dist/AuthConfig.d.ts.map +1 -0
- package/dist/AuthConfig.js +56 -0
- package/dist/AuthConfig.js.map +1 -0
- package/dist/AuthFlow.d.ts +292 -35
- package/dist/AuthFlow.d.ts.map +1 -1
- package/dist/AuthFlow.js +130 -6
- package/dist/AuthFlow.js.map +1 -1
- package/dist/AuthKernel.d.ts +3 -0
- package/dist/AuthKernel.d.ts.map +1 -0
- package/dist/AuthKernel.js +9 -0
- package/dist/AuthKernel.js.map +1 -0
- package/dist/Challenge.d.ts +19 -3
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +157 -1
- package/dist/Challenge.js.map +1 -1
- package/dist/Client.d.ts +36 -0
- package/dist/Client.d.ts.map +1 -0
- package/dist/Client.js +55 -0
- package/dist/Client.js.map +1 -0
- package/dist/Crypto.d.ts +6 -1
- package/dist/Crypto.d.ts.map +1 -1
- package/dist/Crypto.js +62 -1
- package/dist/Crypto.js.map +1 -1
- package/dist/D1Kysely.d.ts +6 -3
- package/dist/D1Kysely.d.ts.map +1 -1
- package/dist/D1Kysely.js +8 -5
- package/dist/D1Kysely.js.map +1 -1
- package/dist/EffectQbSqliteStorage.d.ts +183 -0
- package/dist/EffectQbSqliteStorage.d.ts.map +1 -0
- package/dist/EffectQbSqliteStorage.js +446 -0
- package/dist/EffectQbSqliteStorage.js.map +1 -0
- package/dist/EmailOtp.d.ts +117 -0
- package/dist/EmailOtp.d.ts.map +1 -0
- package/dist/EmailOtp.js +279 -0
- package/dist/EmailOtp.js.map +1 -0
- package/dist/EmailVerification.d.ts +121 -0
- package/dist/EmailVerification.d.ts.map +1 -0
- package/dist/EmailVerification.js +201 -0
- package/dist/EmailVerification.js.map +1 -0
- package/dist/HttpApi/Api.d.ts +175 -0
- package/dist/HttpApi/Api.d.ts.map +1 -0
- package/dist/HttpApi/Api.js +340 -0
- package/dist/HttpApi/Api.js.map +1 -0
- package/dist/HttpApi/Endpoints.d.ts +92 -0
- package/dist/HttpApi/Endpoints.d.ts.map +1 -0
- package/dist/HttpApi/Endpoints.js +48 -0
- package/dist/HttpApi/Endpoints.js.map +1 -0
- package/dist/HttpApi/Errors.d.ts +82 -0
- package/dist/HttpApi/Errors.d.ts.map +1 -0
- package/dist/HttpApi/Errors.js +184 -0
- package/dist/HttpApi/Errors.js.map +1 -0
- package/dist/HttpApi/Schemas.d.ts +86 -0
- package/dist/HttpApi/Schemas.d.ts.map +1 -0
- package/dist/HttpApi/Schemas.js +63 -0
- package/dist/HttpApi/Schemas.js.map +1 -0
- package/dist/HttpApi/Security.d.ts +147 -0
- package/dist/HttpApi/Security.d.ts.map +1 -0
- package/dist/HttpApi/Security.js +439 -0
- package/dist/HttpApi/Security.js.map +1 -0
- package/dist/HttpApi/Transport.d.ts +31 -0
- package/dist/HttpApi/Transport.d.ts.map +1 -0
- package/dist/HttpApi/Transport.js +169 -0
- package/dist/HttpApi/Transport.js.map +1 -0
- package/dist/HttpApi/index.d.ts +8 -0
- package/dist/HttpApi/index.d.ts.map +1 -0
- package/dist/HttpApi/index.js +7 -0
- package/dist/HttpApi/index.js.map +1 -0
- package/dist/HttpApi.d.ts +2 -0
- package/dist/HttpApi.d.ts.map +1 -0
- package/dist/HttpApi.js +2 -0
- package/dist/HttpApi.js.map +1 -0
- package/dist/Identifiers.d.ts.map +1 -1
- package/dist/Identifiers.js.map +1 -1
- package/dist/Internal.d.ts +7 -0
- package/dist/Internal.d.ts.map +1 -0
- package/dist/Internal.js +12 -0
- package/dist/Internal.js.map +1 -0
- package/dist/KyselyStorage.d.ts +28 -2
- package/dist/KyselyStorage.d.ts.map +1 -1
- package/dist/KyselyStorage.js +223 -33
- package/dist/KyselyStorage.js.map +1 -1
- package/dist/Mailer.d.ts +116 -0
- package/dist/Mailer.d.ts.map +1 -0
- package/dist/Mailer.js +101 -0
- package/dist/Mailer.js.map +1 -0
- package/dist/Password.d.ts +107 -0
- package/dist/Password.d.ts.map +1 -0
- package/dist/Password.js +252 -0
- package/dist/Password.js.map +1 -0
- package/dist/Policy.d.ts +7 -4
- package/dist/Policy.d.ts.map +1 -1
- package/dist/Policy.js +28 -5
- package/dist/Policy.js.map +1 -1
- package/dist/Privacy.d.ts +15 -0
- package/dist/Privacy.d.ts.map +1 -1
- package/dist/Privacy.js +58 -1
- package/dist/Privacy.js.map +1 -1
- package/dist/RateLimiter.d.ts +104 -0
- package/dist/RateLimiter.d.ts.map +1 -0
- package/dist/RateLimiter.js +118 -0
- package/dist/RateLimiter.js.map +1 -0
- package/dist/Sessions.d.ts +73 -11
- package/dist/Sessions.d.ts.map +1 -1
- package/dist/Sessions.js +412 -1
- package/dist/Sessions.js.map +1 -1
- package/dist/Storage.d.ts +60 -5
- package/dist/Storage.d.ts.map +1 -1
- package/dist/Storage.js +11 -1
- package/dist/Storage.js.map +1 -1
- package/dist/StorageMigrations.d.ts +2 -1
- package/dist/StorageMigrations.d.ts.map +1 -1
- package/dist/StorageMigrations.js +33 -2
- package/dist/StorageMigrations.js.map +1 -1
- package/dist/Testing.d.ts +9 -1
- package/dist/Testing.d.ts.map +1 -1
- package/dist/Testing.js +30 -2
- package/dist/Testing.js.map +1 -1
- package/dist/WaitUntil.d.ts.map +1 -1
- package/dist/WaitUntil.js +1 -1
- package/dist/WaitUntil.js.map +1 -1
- package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts +34 -0
- package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts.map +1 -0
- package/dist/alchemy/cloudflare/RateLimitDurableObject.js +30 -0
- package/dist/alchemy/cloudflare/RateLimitDurableObject.js.map +1 -0
- package/dist/cloudflare/RateLimitDurableObject.d.ts +50 -0
- package/dist/cloudflare/RateLimitDurableObject.d.ts.map +1 -0
- package/dist/cloudflare/RateLimitDurableObject.js +51 -0
- package/dist/cloudflare/RateLimitDurableObject.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/RateLimitDurableObject.d.ts +32 -0
- package/dist/internal/RateLimitDurableObject.d.ts.map +1 -0
- package/dist/internal/RateLimitDurableObject.js +80 -0
- package/dist/internal/RateLimitDurableObject.js.map +1 -0
- package/migrations/0002_auth_password.sql +25 -0
- package/package.json +76 -20
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Redacted } from "effect";
|
|
2
|
+
import { AuthFlow } from "./AuthFlow.js";
|
|
3
|
+
import type { AuthFlowCompleteError, AuthFlowPrimaryFactorResult, AuthFlowService, AuthResultOf } from "./AuthFlow.js";
|
|
4
|
+
import { Crypto } from "./Crypto.js";
|
|
5
|
+
import type { CryptoError, CryptoService } from "./Crypto.js";
|
|
6
|
+
import type { Email } from "./Identifiers.js";
|
|
7
|
+
import { CredentialStore, UserStore } from "./Storage.js";
|
|
8
|
+
import type { CredentialStoreService, StorageError, UserStoreService } from "./Storage.js";
|
|
9
|
+
export interface PasswordSignInInput {
|
|
10
|
+
readonly email: Email;
|
|
11
|
+
readonly password: Redacted.Redacted<string>;
|
|
12
|
+
}
|
|
13
|
+
export interface PasswordSignUpInput {
|
|
14
|
+
readonly email: Email;
|
|
15
|
+
readonly password: Redacted.Redacted<string>;
|
|
16
|
+
readonly emailVerified?: boolean;
|
|
17
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
18
|
+
}
|
|
19
|
+
export type PasswordHashOperation = "hash" | "verify";
|
|
20
|
+
declare const PasswordHashError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
21
|
+
readonly _tag: "PasswordHashError";
|
|
22
|
+
} & Readonly<A>;
|
|
23
|
+
export declare class PasswordHashError extends PasswordHashError_base<{
|
|
24
|
+
readonly operation: PasswordHashOperation;
|
|
25
|
+
readonly message: string;
|
|
26
|
+
readonly cause?: unknown;
|
|
27
|
+
}> {
|
|
28
|
+
}
|
|
29
|
+
export interface PasswordHashInput {
|
|
30
|
+
readonly password: Redacted.Redacted<string>;
|
|
31
|
+
}
|
|
32
|
+
export interface PasswordVerifyInput {
|
|
33
|
+
readonly hash: string;
|
|
34
|
+
readonly password: Redacted.Redacted<string>;
|
|
35
|
+
}
|
|
36
|
+
export interface PasswordHasherService {
|
|
37
|
+
readonly hash: (input: PasswordHashInput) => Effect.Effect<string, PasswordHashError>;
|
|
38
|
+
readonly verify: (input: PasswordVerifyInput) => Effect.Effect<boolean, PasswordHashError>;
|
|
39
|
+
}
|
|
40
|
+
declare const PasswordHasher_base: Context.ServiceClass<PasswordHasher, "auth/PasswordHasher", PasswordHasherService>;
|
|
41
|
+
export declare class PasswordHasher extends PasswordHasher_base {
|
|
42
|
+
}
|
|
43
|
+
export declare namespace PasswordHasher {
|
|
44
|
+
const make: (service: PasswordHasherService) => PasswordHasherService;
|
|
45
|
+
}
|
|
46
|
+
export interface Pbkdf2PasswordHasherOptions {
|
|
47
|
+
readonly webCrypto?: typeof globalThis.crypto;
|
|
48
|
+
readonly iterations?: number;
|
|
49
|
+
readonly saltBytes?: number;
|
|
50
|
+
readonly hashBytes?: number;
|
|
51
|
+
}
|
|
52
|
+
export interface Pbkdf2PasswordHasherDependencies extends Pbkdf2PasswordHasherOptions {
|
|
53
|
+
readonly crypto: CryptoService;
|
|
54
|
+
}
|
|
55
|
+
export declare const makePbkdf2PasswordHasher: (dependencies: Pbkdf2PasswordHasherDependencies) => PasswordHasherService;
|
|
56
|
+
export declare const Pbkdf2PasswordHasherLive: (options?: Pbkdf2PasswordHasherOptions) => Layer.Layer<PasswordHasher, never, Crypto>;
|
|
57
|
+
export type PasswordSignInError = StorageError | PasswordHashError | AuthFlowCompleteError;
|
|
58
|
+
export type PasswordSignInResult = AuthFlowPrimaryFactorResult<"password"> | AuthResultOf<"InvalidCredentials" | "AccountDisabled">;
|
|
59
|
+
export interface PasswordLoginService {
|
|
60
|
+
readonly signIn: (input: PasswordSignInInput) => Effect.Effect<PasswordSignInResult, PasswordSignInError>;
|
|
61
|
+
}
|
|
62
|
+
declare const PasswordLogin_base: Context.ServiceClass<PasswordLogin, "auth/login/Password", PasswordLoginService>;
|
|
63
|
+
export declare class PasswordLogin extends PasswordLogin_base {
|
|
64
|
+
}
|
|
65
|
+
export declare namespace PasswordLogin {
|
|
66
|
+
const make: (service: PasswordLoginService) => PasswordLoginService;
|
|
67
|
+
}
|
|
68
|
+
export interface PasswordLoginDependencies {
|
|
69
|
+
readonly users: UserStoreService;
|
|
70
|
+
readonly credentials: CredentialStoreService;
|
|
71
|
+
readonly hasher: PasswordHasherService;
|
|
72
|
+
readonly authFlow: AuthFlowService;
|
|
73
|
+
}
|
|
74
|
+
export declare const makePasswordLogin: (dependencies: PasswordLoginDependencies) => PasswordLoginService;
|
|
75
|
+
export declare const PasswordLoginLive: Layer.Layer<PasswordLogin, never, UserStore | CredentialStore | AuthFlow | PasswordHasher>;
|
|
76
|
+
declare const EmailAlreadyRegisteredError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
77
|
+
readonly _tag: "EmailAlreadyRegisteredError";
|
|
78
|
+
} & Readonly<A>;
|
|
79
|
+
export declare class EmailAlreadyRegisteredError extends EmailAlreadyRegisteredError_base<{
|
|
80
|
+
readonly email: Email;
|
|
81
|
+
}> {
|
|
82
|
+
}
|
|
83
|
+
export type PasswordSignUpError = EmailAlreadyRegisteredError | StorageError | PasswordHashError | CryptoError | AuthFlowCompleteError;
|
|
84
|
+
export type PasswordSignUpResult = AuthFlowPrimaryFactorResult<"password">;
|
|
85
|
+
export interface PasswordRegistrationService {
|
|
86
|
+
readonly signUp: (input: PasswordSignUpInput) => Effect.Effect<PasswordSignUpResult, PasswordSignUpError>;
|
|
87
|
+
}
|
|
88
|
+
declare const PasswordRegistration_base: Context.ServiceClass<PasswordRegistration, "auth/registration/Password", PasswordRegistrationService>;
|
|
89
|
+
export declare class PasswordRegistration extends PasswordRegistration_base {
|
|
90
|
+
}
|
|
91
|
+
export declare namespace PasswordRegistration {
|
|
92
|
+
const make: (service: PasswordRegistrationService) => PasswordRegistrationService;
|
|
93
|
+
}
|
|
94
|
+
export interface PasswordRegistrationDependencies {
|
|
95
|
+
readonly users: UserStoreService;
|
|
96
|
+
readonly credentials: CredentialStoreService;
|
|
97
|
+
readonly hasher: PasswordHasherService;
|
|
98
|
+
readonly authFlow: AuthFlowService;
|
|
99
|
+
readonly crypto: CryptoService;
|
|
100
|
+
readonly userIdBytes?: number;
|
|
101
|
+
readonly credentialIdBytes?: number;
|
|
102
|
+
}
|
|
103
|
+
export declare const makePasswordRegistration: (dependencies: PasswordRegistrationDependencies) => PasswordRegistrationService;
|
|
104
|
+
export declare const PasswordRegistrationLive: Layer.Layer<PasswordRegistration, never, Crypto | UserStore | CredentialStore | AuthFlow | PasswordHasher>;
|
|
105
|
+
export declare const PasswordFeatureLive: Layer.Layer<PasswordHasher | PasswordLogin | PasswordRegistration, never, Crypto | UserStore | CredentialStore | AuthFlow>;
|
|
106
|
+
export {};
|
|
107
|
+
//# sourceMappingURL=Password.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Password.d.ts","sourceRoot":"","sources":["../src/Password.ts"],"names":[],"mappings":"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"}
|
package/dist/Password.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { Context, Data, Effect, Encoding, Layer, Option, Redacted, Result, } from "effect";
|
|
2
|
+
import { AuthPasswordHasherConfig } from "./AuthConfig.js";
|
|
3
|
+
import { AuthFlow, AuthResult } from "./AuthFlow.js";
|
|
4
|
+
import { Crypto } from "./Crypto.js";
|
|
5
|
+
import { CredentialId, UserId } from "./Identifiers.js";
|
|
6
|
+
import { currentUnixMillis, timingSafeEqualString } from "./Internal.js";
|
|
7
|
+
import { CredentialStore, UserStore } from "./Storage.js";
|
|
8
|
+
export class PasswordHashError extends Data.TaggedError("PasswordHashError") {
|
|
9
|
+
}
|
|
10
|
+
export class PasswordHasher extends Context.Service()("auth/PasswordHasher") {
|
|
11
|
+
}
|
|
12
|
+
(function (PasswordHasher) {
|
|
13
|
+
PasswordHasher.make = (service) => PasswordHasher.of(service);
|
|
14
|
+
})(PasswordHasher || (PasswordHasher = {}));
|
|
15
|
+
const textEncoder = new TextEncoder();
|
|
16
|
+
const passwordHashPrefix = "pbkdf2-sha256";
|
|
17
|
+
const getWebCrypto = (options, operation) => Effect.gen(function* () {
|
|
18
|
+
const crypto = options.webCrypto ?? globalThis.crypto;
|
|
19
|
+
if (crypto === undefined) {
|
|
20
|
+
return yield* new PasswordHashError({
|
|
21
|
+
operation,
|
|
22
|
+
message: "Web Crypto is not available",
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return crypto;
|
|
26
|
+
});
|
|
27
|
+
const decodeBase64Url = (value, operation) => Result.match(Encoding.decodeBase64Url(value), {
|
|
28
|
+
onSuccess: Effect.succeed,
|
|
29
|
+
onFailure: (cause) => Effect.fail(new PasswordHashError({
|
|
30
|
+
operation,
|
|
31
|
+
message: "Invalid password hash encoding",
|
|
32
|
+
cause,
|
|
33
|
+
})),
|
|
34
|
+
});
|
|
35
|
+
const parsePasswordHash = (hash) => {
|
|
36
|
+
const [prefix, iterations, salt, derivedKey] = hash.split("$");
|
|
37
|
+
if (prefix !== passwordHashPrefix ||
|
|
38
|
+
iterations === undefined ||
|
|
39
|
+
salt === undefined ||
|
|
40
|
+
derivedKey === undefined) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
const parsedIterations = Number(iterations);
|
|
44
|
+
if (!Number.isInteger(parsedIterations) || parsedIterations <= 0) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
iterations: parsedIterations,
|
|
49
|
+
salt,
|
|
50
|
+
derivedKey,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
const derivePbkdf2Sha256 = (input) => Effect.tryPromise({
|
|
54
|
+
try: async () => {
|
|
55
|
+
const key = await input.webCrypto.subtle.importKey("raw", textEncoder.encode(Redacted.value(input.password)), "PBKDF2", false, ["deriveBits"]);
|
|
56
|
+
const bits = await input.webCrypto.subtle.deriveBits({
|
|
57
|
+
name: "PBKDF2",
|
|
58
|
+
hash: "SHA-256",
|
|
59
|
+
salt: input.salt,
|
|
60
|
+
iterations: input.iterations,
|
|
61
|
+
}, key, input.hashBytes * 8);
|
|
62
|
+
return new Uint8Array(bits);
|
|
63
|
+
},
|
|
64
|
+
catch: (cause) => new PasswordHashError({
|
|
65
|
+
operation: input.operation,
|
|
66
|
+
message: "Failed to derive PBKDF2 password hash",
|
|
67
|
+
cause,
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
export const makePbkdf2PasswordHasher = (dependencies) => {
|
|
71
|
+
const iterations = dependencies.iterations ?? 210_000;
|
|
72
|
+
const saltBytes = dependencies.saltBytes ?? 16;
|
|
73
|
+
const hashBytes = dependencies.hashBytes ?? 32;
|
|
74
|
+
return PasswordHasher.make({
|
|
75
|
+
hash: Effect.fn("auth.password_hash.pbkdf2.hash")(function* (input) {
|
|
76
|
+
const webCrypto = yield* getWebCrypto(dependencies, "hash");
|
|
77
|
+
const salt = yield* dependencies.crypto.randomBytes(saltBytes).pipe(Effect.mapError((cause) => new PasswordHashError({
|
|
78
|
+
operation: "hash",
|
|
79
|
+
message: "Failed to generate password salt",
|
|
80
|
+
cause,
|
|
81
|
+
})));
|
|
82
|
+
const derivedKey = yield* derivePbkdf2Sha256({
|
|
83
|
+
webCrypto,
|
|
84
|
+
password: input.password,
|
|
85
|
+
salt,
|
|
86
|
+
iterations,
|
|
87
|
+
hashBytes,
|
|
88
|
+
operation: "hash",
|
|
89
|
+
});
|
|
90
|
+
return [
|
|
91
|
+
passwordHashPrefix,
|
|
92
|
+
String(iterations),
|
|
93
|
+
Encoding.encodeBase64Url(salt),
|
|
94
|
+
Encoding.encodeBase64Url(derivedKey),
|
|
95
|
+
].join("$");
|
|
96
|
+
}),
|
|
97
|
+
verify: Effect.fn("auth.password_hash.pbkdf2.verify")(function* (input) {
|
|
98
|
+
const parsed = parsePasswordHash(input.hash);
|
|
99
|
+
if (parsed === undefined) {
|
|
100
|
+
return yield* new PasswordHashError({
|
|
101
|
+
operation: "verify",
|
|
102
|
+
message: "Invalid password hash format",
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
const webCrypto = yield* getWebCrypto(dependencies, "verify");
|
|
106
|
+
const salt = yield* decodeBase64Url(parsed.salt, "verify");
|
|
107
|
+
const expected = yield* decodeBase64Url(parsed.derivedKey, "verify");
|
|
108
|
+
const derivedKey = yield* derivePbkdf2Sha256({
|
|
109
|
+
webCrypto,
|
|
110
|
+
password: input.password,
|
|
111
|
+
salt,
|
|
112
|
+
iterations: parsed.iterations,
|
|
113
|
+
hashBytes: expected.byteLength,
|
|
114
|
+
operation: "verify",
|
|
115
|
+
});
|
|
116
|
+
return yield* timingSafeEqualString(dependencies.crypto, Encoding.encodeBase64Url(derivedKey), parsed.derivedKey).pipe(Effect.mapError((cause) => new PasswordHashError({
|
|
117
|
+
operation: "verify",
|
|
118
|
+
message: "Failed to compare password hash",
|
|
119
|
+
cause,
|
|
120
|
+
})));
|
|
121
|
+
}),
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
export const Pbkdf2PasswordHasherLive = (options) => Layer.effect(PasswordHasher)(Effect.gen(function* () {
|
|
125
|
+
const crypto = yield* Crypto;
|
|
126
|
+
const resolvedOptions = options ?? (yield* AuthPasswordHasherConfig);
|
|
127
|
+
return makePbkdf2PasswordHasher({
|
|
128
|
+
...resolvedOptions,
|
|
129
|
+
crypto,
|
|
130
|
+
});
|
|
131
|
+
}));
|
|
132
|
+
export class PasswordLogin extends Context.Service()("auth/login/Password") {
|
|
133
|
+
}
|
|
134
|
+
(function (PasswordLogin) {
|
|
135
|
+
PasswordLogin.make = (service) => PasswordLogin.of(service);
|
|
136
|
+
})(PasswordLogin || (PasswordLogin = {}));
|
|
137
|
+
export const makePasswordLogin = (dependencies) => PasswordLogin.make({
|
|
138
|
+
signIn: Effect.fn("auth.password.sign_in")(function* (input) {
|
|
139
|
+
yield* Effect.annotateCurrentSpan("auth.method", "password");
|
|
140
|
+
const user = yield* dependencies.users.findByEmail(input.email);
|
|
141
|
+
if (Option.isNone(user)) {
|
|
142
|
+
yield* Effect.annotateCurrentSpan("auth.result", "InvalidCredentials");
|
|
143
|
+
return AuthResult.InvalidCredentials();
|
|
144
|
+
}
|
|
145
|
+
if (user.value.disabledAt !== undefined) {
|
|
146
|
+
yield* Effect.annotateCurrentSpan("auth.result", "AccountDisabled");
|
|
147
|
+
return AuthResult.AccountDisabled();
|
|
148
|
+
}
|
|
149
|
+
const credential = yield* dependencies.credentials.findPasswordByUserId(user.value.id);
|
|
150
|
+
if (Option.isNone(credential) ||
|
|
151
|
+
credential.value.revokedAt !== undefined) {
|
|
152
|
+
yield* Effect.annotateCurrentSpan("auth.result", "InvalidCredentials");
|
|
153
|
+
return AuthResult.InvalidCredentials();
|
|
154
|
+
}
|
|
155
|
+
const verified = yield* dependencies.hasher.verify({
|
|
156
|
+
hash: credential.value.passwordHash,
|
|
157
|
+
password: input.password,
|
|
158
|
+
});
|
|
159
|
+
if (!verified) {
|
|
160
|
+
yield* Effect.annotateCurrentSpan("auth.result", "InvalidCredentials");
|
|
161
|
+
return AuthResult.InvalidCredentials();
|
|
162
|
+
}
|
|
163
|
+
return yield* dependencies.authFlow.completePrimaryFactor({
|
|
164
|
+
userId: user.value.id,
|
|
165
|
+
email: user.value.email,
|
|
166
|
+
method: "password",
|
|
167
|
+
amr: ["pwd"],
|
|
168
|
+
aal: "aal1",
|
|
169
|
+
claims: { emailVerified: user.value.emailVerified },
|
|
170
|
+
});
|
|
171
|
+
}),
|
|
172
|
+
});
|
|
173
|
+
export const PasswordLoginLive = Layer.effect(PasswordLogin)(Effect.gen(function* () {
|
|
174
|
+
const users = yield* UserStore;
|
|
175
|
+
const credentials = yield* CredentialStore;
|
|
176
|
+
const hasher = yield* PasswordHasher;
|
|
177
|
+
const authFlow = yield* AuthFlow;
|
|
178
|
+
return makePasswordLogin({
|
|
179
|
+
users,
|
|
180
|
+
credentials,
|
|
181
|
+
hasher,
|
|
182
|
+
authFlow,
|
|
183
|
+
});
|
|
184
|
+
}));
|
|
185
|
+
export class EmailAlreadyRegisteredError extends Data.TaggedError("EmailAlreadyRegisteredError") {
|
|
186
|
+
}
|
|
187
|
+
export class PasswordRegistration extends Context.Service()("auth/registration/Password") {
|
|
188
|
+
}
|
|
189
|
+
(function (PasswordRegistration) {
|
|
190
|
+
PasswordRegistration.make = (service) => PasswordRegistration.of(service);
|
|
191
|
+
})(PasswordRegistration || (PasswordRegistration = {}));
|
|
192
|
+
export const makePasswordRegistration = (dependencies) => {
|
|
193
|
+
const userIdBytes = dependencies.userIdBytes ?? 16;
|
|
194
|
+
const credentialIdBytes = dependencies.credentialIdBytes ?? 16;
|
|
195
|
+
return PasswordRegistration.make({
|
|
196
|
+
signUp: Effect.fn("auth.password.sign_up")(function* (input) {
|
|
197
|
+
yield* Effect.annotateCurrentSpan("auth.method", "password");
|
|
198
|
+
const existing = yield* dependencies.users.findByEmail(input.email);
|
|
199
|
+
if (Option.isSome(existing)) {
|
|
200
|
+
yield* Effect.annotateCurrentSpan("auth.result", "EmailAlreadyRegistered");
|
|
201
|
+
return yield* new EmailAlreadyRegisteredError({ email: input.email });
|
|
202
|
+
}
|
|
203
|
+
const now = yield* currentUnixMillis;
|
|
204
|
+
const emailVerified = input.emailVerified ?? false;
|
|
205
|
+
const userId = UserId(yield* dependencies.crypto.randomToken(userIdBytes));
|
|
206
|
+
const credentialId = CredentialId(yield* dependencies.crypto.randomToken(credentialIdBytes));
|
|
207
|
+
const passwordHash = yield* dependencies.hasher.hash({
|
|
208
|
+
password: input.password,
|
|
209
|
+
});
|
|
210
|
+
yield* dependencies.users.insert({
|
|
211
|
+
id: userId,
|
|
212
|
+
email: input.email,
|
|
213
|
+
emailVerified,
|
|
214
|
+
createdAt: now,
|
|
215
|
+
updatedAt: now,
|
|
216
|
+
metadata: input.metadata,
|
|
217
|
+
});
|
|
218
|
+
yield* dependencies.credentials.insertPassword({
|
|
219
|
+
id: credentialId,
|
|
220
|
+
userId,
|
|
221
|
+
passwordHash,
|
|
222
|
+
createdAt: now,
|
|
223
|
+
updatedAt: now,
|
|
224
|
+
});
|
|
225
|
+
yield* Effect.annotateCurrentSpan("auth.result", "registered");
|
|
226
|
+
return yield* dependencies.authFlow.completePrimaryFactor({
|
|
227
|
+
userId,
|
|
228
|
+
email: input.email,
|
|
229
|
+
method: "password",
|
|
230
|
+
amr: ["pwd"],
|
|
231
|
+
aal: "aal1",
|
|
232
|
+
claims: { emailVerified },
|
|
233
|
+
});
|
|
234
|
+
}),
|
|
235
|
+
});
|
|
236
|
+
};
|
|
237
|
+
export const PasswordRegistrationLive = Layer.effect(PasswordRegistration)(Effect.gen(function* () {
|
|
238
|
+
const users = yield* UserStore;
|
|
239
|
+
const credentials = yield* CredentialStore;
|
|
240
|
+
const hasher = yield* PasswordHasher;
|
|
241
|
+
const authFlow = yield* AuthFlow;
|
|
242
|
+
const crypto = yield* Crypto;
|
|
243
|
+
return makePasswordRegistration({
|
|
244
|
+
users,
|
|
245
|
+
credentials,
|
|
246
|
+
hasher,
|
|
247
|
+
authFlow,
|
|
248
|
+
crypto,
|
|
249
|
+
});
|
|
250
|
+
}));
|
|
251
|
+
export const PasswordFeatureLive = Layer.mergeAll(PasswordLoginLive, PasswordRegistrationLive).pipe(Layer.provideMerge(Pbkdf2PasswordHasherLive()));
|
|
252
|
+
//# sourceMappingURL=Password.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Password.js","sourceRoot":"","sources":["../src/Password.ts"],"names":[],"mappings":"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"}
|
package/dist/Policy.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import type { PolicyId } from "./Identifiers.js";
|
|
3
|
-
import
|
|
4
|
-
|
|
3
|
+
import { CurrentSession } from "./Sessions.js";
|
|
4
|
+
import type { CurrentActor, SessionRequirement } from "./Sessions.js";
|
|
5
|
+
export type AuthzDenyReason = "missing-permission" | "missing-role" | "missing-relation" | "missing-grant" | "not-owner" | "not-authenticated" | "session-requirement-unsatisfied" | "email-verification-required" | (string & {});
|
|
5
6
|
declare const AuthzError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
6
7
|
readonly _tag: "AuthzError";
|
|
7
8
|
} & Readonly<A>;
|
|
@@ -29,11 +30,13 @@ type EffectContext<T> = T extends Effect.Effect<unknown, unknown, infer R> ? R :
|
|
|
29
30
|
export declare const isAuthzError: (error: unknown) => error is AuthzError;
|
|
30
31
|
export declare const allow: Policy;
|
|
31
32
|
export declare const deny: (reason: AuthzDenyReason, policyId?: PolicyId) => Policy<never>;
|
|
32
|
-
export declare const all: <const Policies extends
|
|
33
|
-
export declare const any: <const Policies extends
|
|
33
|
+
export declare const all: <const Policies extends readonly Effect.Effect<unknown, unknown, unknown>[]>(...policies: Policies) => Effect.Effect<void, EffectError<Policies[number]>, EffectContext<Policies[number]>>;
|
|
34
|
+
export declare const any: <const Policies extends readonly Effect.Effect<unknown, unknown, unknown>[]>(...policies: Policies) => Effect.Effect<void, AuthzError | NonAuthzError<EffectError<Policies[number]>>, EffectContext<Policies[number]>>;
|
|
34
35
|
export declare const not: <A, E, R>(policy: Effect.Effect<A, E, R>, reason?: AuthzDenyReason) => Effect.Effect<void, AuthzError | NonAuthzError<E>, R>;
|
|
35
36
|
export declare const check: <A, E, R>(policy: Effect.Effect<A, E, R>) => Effect.Effect<PolicyDecision, NonAuthzError<E>, R>;
|
|
36
37
|
export declare const checkDetailed: <A, E, R>(policy: Effect.Effect<A, E, R>) => Effect.Effect<PolicyCheckResult<NonAuthzError<E>>, never, R>;
|
|
38
|
+
export declare const requireNoSessionRequirement: (requirement: SessionRequirement, policyId?: PolicyId) => Effect.Effect<void, AuthzError, CurrentSession>;
|
|
39
|
+
export declare const requireEmailVerified: (policyId?: PolicyId) => Effect.Effect<void, AuthzError, CurrentSession>;
|
|
37
40
|
export declare const require: <A, E, R>(policy: Effect.Effect<A, E, R>) => <B, E2, R2>(effect: Effect.Effect<B, E2, R2>) => Effect.Effect<B, E | E2, R | R2>;
|
|
38
41
|
export {};
|
|
39
42
|
//# sourceMappingURL=Policy.d.ts.map
|
package/dist/Policy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Policy.d.ts","sourceRoot":"","sources":["../src/Policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,MAAM,EAAE,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"Policy.d.ts","sourceRoot":"","sources":["../src/Policy.ts"],"names":[],"mappings":"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"}
|
package/dist/Policy.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Data, Effect } from "effect";
|
|
2
|
+
import { CurrentSession } from "./Sessions.js";
|
|
2
3
|
export class AuthzError extends Data.TaggedError("AuthzError") {
|
|
3
4
|
}
|
|
4
5
|
export const isAuthzError = (error) => {
|
|
@@ -25,26 +26,48 @@ export const any = (...policies) => {
|
|
|
25
26
|
onSuccess: () => Effect.void,
|
|
26
27
|
onFailure: (error) => isAuthzError(error)
|
|
27
28
|
? loop(index + 1, error)
|
|
28
|
-
: Effect.fail(error)
|
|
29
|
+
: Effect.fail(error),
|
|
29
30
|
}));
|
|
30
31
|
};
|
|
31
32
|
return loop(0, undefined);
|
|
32
33
|
};
|
|
33
34
|
export const not = (policy, reason = "policy-not-satisfied") => policy.pipe(Effect.matchEffect({
|
|
34
35
|
onSuccess: () => Effect.fail(new AuthzError({ reason })),
|
|
35
|
-
onFailure: (error) =>
|
|
36
|
+
onFailure: (error) => isAuthzError(error)
|
|
37
|
+
? Effect.void
|
|
38
|
+
: Effect.fail(error),
|
|
36
39
|
}));
|
|
37
40
|
export const check = (policy) => policy.pipe(Effect.matchEffect({
|
|
38
41
|
onSuccess: () => Effect.succeed({ type: "allowed" }),
|
|
39
42
|
onFailure: (error) => isAuthzError(error)
|
|
40
43
|
? Effect.succeed({ type: "denied", error })
|
|
41
|
-
: Effect.fail(error)
|
|
44
|
+
: Effect.fail(error),
|
|
42
45
|
}));
|
|
43
46
|
export const checkDetailed = (policy) => policy.pipe(Effect.match({
|
|
44
47
|
onSuccess: () => ({ type: "allowed" }),
|
|
45
48
|
onFailure: (error) => isAuthzError(error)
|
|
46
|
-
?
|
|
47
|
-
:
|
|
49
|
+
? { type: "denied", error }
|
|
50
|
+
: { type: "failed", error: error },
|
|
48
51
|
}));
|
|
52
|
+
export const requireNoSessionRequirement = (requirement, policyId) => Effect.gen(function* () {
|
|
53
|
+
const session = yield* CurrentSession;
|
|
54
|
+
if (session.claims?.requirements?.includes(requirement) === true) {
|
|
55
|
+
return yield* new AuthzError({
|
|
56
|
+
reason: "session-requirement-unsatisfied",
|
|
57
|
+
policyId,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
export const requireEmailVerified = (policyId) => Effect.gen(function* () {
|
|
62
|
+
const session = yield* CurrentSession;
|
|
63
|
+
const { claims } = session;
|
|
64
|
+
if (claims?.emailVerified !== true ||
|
|
65
|
+
claims.requirements?.includes("email_verification") === true) {
|
|
66
|
+
return yield* new AuthzError({
|
|
67
|
+
reason: "email-verification-required",
|
|
68
|
+
policyId,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
});
|
|
49
72
|
export const require = (policy) => (effect) => Effect.flatMap(policy, () => effect);
|
|
50
73
|
//# sourceMappingURL=Policy.js.map
|
package/dist/Policy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Policy.js","sourceRoot":"","sources":["../src/Policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"Policy.js","sourceRoot":"","sources":["../src/Policy.ts"],"names":[],"mappings":"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"}
|
package/dist/Privacy.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { AuthSecrets } from "./AuthConfig.js";
|
|
3
|
+
import { Crypto } from "./Crypto.js";
|
|
4
|
+
import type { CryptoKey, CryptoService } from "./Crypto.js";
|
|
2
5
|
import { EmailHash, IpHash, UserAgentHash } from "./Identifiers.js";
|
|
3
6
|
import type { Email, IpAddress } from "./Identifiers.js";
|
|
4
7
|
export type PrivacyOperation = "email-hash" | "ip-hash" | "user-agent-hash";
|
|
@@ -22,6 +25,18 @@ export declare class Privacy extends Privacy_base {
|
|
|
22
25
|
export declare namespace Privacy {
|
|
23
26
|
const make: (service: PrivacyService) => PrivacyService;
|
|
24
27
|
}
|
|
28
|
+
export interface PrivacyOptions {
|
|
29
|
+
readonly secret: CryptoKey;
|
|
30
|
+
readonly normalizeEmail?: (email: Email) => string;
|
|
31
|
+
readonly normalizeIp?: (ip: IpAddress) => string;
|
|
32
|
+
readonly normalizeUserAgent?: (userAgent: string) => string;
|
|
33
|
+
}
|
|
34
|
+
export interface PrivacyDependencies extends PrivacyOptions {
|
|
35
|
+
readonly crypto: CryptoService;
|
|
36
|
+
}
|
|
37
|
+
export declare const makeHmacPrivacy: (dependencies: PrivacyDependencies) => PrivacyService;
|
|
38
|
+
export declare function PrivacyLive(options: PrivacyOptions): Layer.Layer<Privacy, never, Crypto>;
|
|
39
|
+
export declare function PrivacyLive(): Layer.Layer<Privacy, never, Crypto | AuthSecrets>;
|
|
25
40
|
export declare const PrivacyTestLive: Layer.Layer<Privacy, never, never>;
|
|
26
41
|
export {};
|
|
27
42
|
//# sourceMappingURL=Privacy.d.ts.map
|
package/dist/Privacy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Privacy.d.ts","sourceRoot":"","sources":["../src/Privacy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"Privacy.d.ts","sourceRoot":"","sources":["../src/Privacy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEtD,OAAO,EAAqB,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,SAAS,GAAG,iBAAiB,CAAC;;;;AAE5E,qBAAa,YAAa,SAAQ,kBAAiC;IACjE,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;CAAG;AAEL,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC7E,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACxE,QAAQ,CAAC,aAAa,EAAE,CACtB,SAAS,EAAE,MAAM,KACd,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;CACjD;;AAED,qBAAa,OAAQ,SAAQ,YAE5B;CAAG;AAEJ,yBAAiB,OAAO,CAAC;IAChB,MAAM,IAAI,GAAI,SAAS,cAAc,KAAG,cAC1B,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,MAAM,CAAC;IACjD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CAC7D;AAED,MAAM,WAAW,mBAAoB,SAAQ,cAAc;IACzD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;CAChC;AAmDD,eAAO,MAAM,eAAe,GAC1B,cAAc,mBAAmB,KAChC,cA6CF,CAAC;AAEF,wBAAgB,WAAW,CACzB,OAAO,EAAE,cAAc,GACtB,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AACvC,wBAAgB,WAAW,IAAI,KAAK,CAAC,KAAK,CACxC,OAAO,EACP,KAAK,EACL,MAAM,GAAG,WAAW,CACrB,CAAC;AAoBF,eAAO,MAAM,eAAe,oCAO3B,CAAC"}
|
package/dist/Privacy.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Context, Data, Effect, Layer } from "effect";
|
|
2
|
+
import { AuthPrivacyConfig, AuthSecrets } from "./AuthConfig.js";
|
|
3
|
+
import { Crypto } from "./Crypto.js";
|
|
2
4
|
import { EmailHash, IpHash, UserAgentHash } from "./Identifiers.js";
|
|
3
5
|
export class PrivacyError extends Data.TaggedError("PrivacyError") {
|
|
4
6
|
}
|
|
@@ -7,9 +9,64 @@ export class Privacy extends Context.Service()("auth/Privacy") {
|
|
|
7
9
|
(function (Privacy) {
|
|
8
10
|
Privacy.make = (service) => Privacy.of(service);
|
|
9
11
|
})(Privacy || (Privacy = {}));
|
|
12
|
+
const hmacNamespace = "auth.privacy.v1";
|
|
13
|
+
const normalizeEmail = (email) => String(email).trim().toLowerCase();
|
|
14
|
+
const normalizeIp = (ip) => String(ip).trim();
|
|
15
|
+
const normalizeUserAgent = (userAgent) => userAgent.trim().replaceAll(/\s+/g, " ");
|
|
16
|
+
const normalizeInput = (operation, normalize, input) => Effect.try({
|
|
17
|
+
try: () => normalize(input),
|
|
18
|
+
catch: (cause) => new PrivacyError({
|
|
19
|
+
operation,
|
|
20
|
+
message: "Failed to normalize privacy input",
|
|
21
|
+
cause,
|
|
22
|
+
}),
|
|
23
|
+
});
|
|
24
|
+
const hmacHash = (dependencies, operation, kind, normalized, brand) => dependencies.crypto
|
|
25
|
+
.hmacSha256({
|
|
26
|
+
key: dependencies.secret,
|
|
27
|
+
data: `${hmacNamespace}.${kind}:${normalized}`,
|
|
28
|
+
})
|
|
29
|
+
.pipe(Effect.map(brand), Effect.mapError((cause) => new PrivacyError({
|
|
30
|
+
operation,
|
|
31
|
+
message: "Failed to hash privacy input",
|
|
32
|
+
cause,
|
|
33
|
+
})));
|
|
34
|
+
export const makeHmacPrivacy = (dependencies) => {
|
|
35
|
+
const emailNormalizer = dependencies.normalizeEmail ?? normalizeEmail;
|
|
36
|
+
const ipNormalizer = dependencies.normalizeIp ?? normalizeIp;
|
|
37
|
+
const userAgentNormalizer = dependencies.normalizeUserAgent ?? normalizeUserAgent;
|
|
38
|
+
return Privacy.make({
|
|
39
|
+
emailHash: Effect.fn("auth.privacy.email_hash")(function* (email) {
|
|
40
|
+
const normalized = yield* normalizeInput("email-hash", emailNormalizer, email);
|
|
41
|
+
return yield* hmacHash(dependencies, "email-hash", "email", normalized, EmailHash);
|
|
42
|
+
}),
|
|
43
|
+
ipHash: Effect.fn("auth.privacy.ip_hash")(function* (ip) {
|
|
44
|
+
const normalized = yield* normalizeInput("ip-hash", ipNormalizer, ip);
|
|
45
|
+
return yield* hmacHash(dependencies, "ip-hash", "ip", normalized, IpHash);
|
|
46
|
+
}),
|
|
47
|
+
userAgentHash: Effect.fn("auth.privacy.user_agent_hash")(function* (userAgent) {
|
|
48
|
+
const normalized = yield* normalizeInput("user-agent-hash", userAgentNormalizer, userAgent);
|
|
49
|
+
return yield* hmacHash(dependencies, "user-agent-hash", "user-agent", normalized, UserAgentHash);
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
export function PrivacyLive(options) {
|
|
54
|
+
return Layer.effect(Privacy)(Effect.gen(function* () {
|
|
55
|
+
const crypto = yield* Crypto;
|
|
56
|
+
const resolvedOptions = options ??
|
|
57
|
+
{
|
|
58
|
+
...(yield* AuthPrivacyConfig),
|
|
59
|
+
secret: (yield* AuthSecrets).privacy,
|
|
60
|
+
};
|
|
61
|
+
return makeHmacPrivacy({
|
|
62
|
+
...resolvedOptions,
|
|
63
|
+
crypto,
|
|
64
|
+
});
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
10
67
|
export const PrivacyTestLive = Layer.succeed(Privacy)(Privacy.make({
|
|
11
68
|
emailHash: (email) => Effect.succeed(EmailHash(`test:email:${email}`)),
|
|
12
69
|
ipHash: (ip) => Effect.succeed(IpHash(`test:ip:${ip}`)),
|
|
13
|
-
userAgentHash: (userAgent) => Effect.succeed(UserAgentHash(`test:user-agent:${userAgent}`))
|
|
70
|
+
userAgentHash: (userAgent) => Effect.succeed(UserAgentHash(`test:user-agent:${userAgent}`)),
|
|
14
71
|
}));
|
|
15
72
|
//# sourceMappingURL=Privacy.js.map
|