@yielded/auth-simplewebauthn 0.1.0-beta.16 → 0.1.0-beta.18

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.
@@ -346,7 +346,8 @@ const makeSimpleWebAuthnPasskeyProtocol = Effect.fn("makeSimpleWebAuthnPasskeyPr
346
346
  }[ceremony.purpose] !== ceremony.context._tag || !credential.active || credential.rpId !== profile.rpId || original.rpId !== profile.rpId || !original.algorithms.includes(credential.algorithm) || !profile.algorithms.includes(credential.algorithm)) return yield* rejected();
347
347
  yield* fresh(ceremony);
348
348
  const wire = yield* decode(Schema.fromJsonString(authenticationResponse), Redacted.value(fixed.response));
349
- const userHandle = wire.response.userHandle ?? void 0;
349
+ const { userHandle: rawUserHandle, ...assertionResponse } = wire.response;
350
+ const userHandle = rawUserHandle ?? void 0;
350
351
  if (wire.id !== wire.rawId || wire.id !== credential.protocolCredentialId || userHandle !== void 0 && userHandle !== credential.userHandle || ceremony.context._tag === "SignIn" && userHandle === void 0 || ceremony.allowedCredentials.length > 0 && !ceremony.allowedCredentials.some((value) => value.id === wire.id)) return yield* rejected();
351
352
  const client = yield* checkClient(wire.response.clientDataJSON, ceremony, "webauthn.get");
352
353
  const auth = yield* checkAuthenticator(yield* bytes(wire.response.authenticatorData), false, profile);
@@ -357,8 +358,8 @@ const makeSimpleWebAuthnPasskeyProtocol = Effect.fn("makeSimpleWebAuthnPasskeyPr
357
358
  response: {
358
359
  ...wire,
359
360
  response: {
360
- ...wire.response,
361
- userHandle
361
+ ...assertionResponse,
362
+ ...userHandle === void 0 ? {} : { userHandle }
362
363
  },
363
364
  clientExtensionResults: {}
364
365
  },
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.mjs","names":[],"sources":["../../../src/internal/server/protocol.ts"],"sourcesContent":["import {\n generateAuthenticationOptions,\n generateRegistrationOptions,\n verifyAuthenticationResponse,\n verifyRegistrationResponse,\n} from \"@simplewebauthn/server\";\nimport {\n decodeAttestationObject,\n decodeClientDataJSON,\n decodeCredentialPublicKey,\n isoCBOR,\n parseAuthenticatorData,\n} from \"@simplewebauthn/server/helpers\";\nimport {\n type PasskeyConfigurationError,\n PasskeyProtocolRejected,\n PasskeyUnavailable,\n PasskeyAssertion,\n PasskeyAssertionVerified,\n PasskeyAttestation,\n PasskeyAuthenticationOptions,\n PasskeyCeremony,\n PasskeyChallenge,\n PasskeyCounter,\n PasskeyCredential,\n PasskeyDescriptor,\n PasskeyLabel,\n PasskeyProfile,\n PasskeyProtocolCredentialId,\n PasskeyRegistrationOptions,\n PasskeyRegistrationVerified,\n PasskeyUserHandle,\n PasskeyConfig,\n PasskeyProtocol,\n samePasskey,\n snapshotPasskey,\n} from \"@yielded/auth/Passkey\";\nimport { reportAuthFailure } from \"@yielded/auth/Persistence\";\nimport type { Context } from \"effect\";\nimport { Cause, DateTime, Effect, Layer, Redacted, Schema } from \"effect\";\nimport { Base64Url } from \"effect/encoding\";\n\nimport { captureSimpleWebAuthnProfiles } from \"./configuration\";\nimport type { SimpleWebAuthnPasskeyProtocolOptions } from \"./models\";\n\ntype Protocol = Context.Service.Shape<typeof PasskeyProtocol>;\ntype Input<K extends keyof Protocol> = Parameters<Protocol[K]>[0];\nconst rejected = () => PasskeyProtocolRejected.make({});\nconst unavailable = () => PasskeyUnavailable.make({});\n\nconst unexpected = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n effect.pipe(\n Effect.catchCause((cause): Effect.Effect<never, E | PasskeyUnavailable> =>\n Cause.hasDies(cause)\n ? reportAuthFailure(\"passkey-protocol\", cause).pipe(\n Effect.andThen(Effect.fail(unavailable())),\n )\n : Effect.failCause(cause),\n ),\n );\n\nconst maintained = <A>(call: () => Promise<A>) =>\n Effect.tryPromise(call).pipe(\n Effect.onError((cause) => reportAuthFailure(\"passkey-protocol\", cause)),\n Effect.mapError(unavailable),\n );\n\nconst parsed = <A>(call: () => A) => Effect.try({ try: call, catch: rejected });\n\nconst decode = <S extends Schema.Codec<unknown, unknown, never, never>>(\n schema: S,\n input: unknown,\n) =>\n // Maintained JSON/CBOR parsers and their map lookups return untyped wire data.\n // eslint-disable-next-line no-restricted-properties\n Schema.decodeUnknownEffect(schema)(input).pipe(Effect.mapError(rejected));\n\nconst capture = <S extends Schema.Codec<unknown, unknown, never, never>>(\n schema: S,\n input: S[\"Type\"],\n) => snapshotPasskey(schema, input).pipe(Effect.mapError(rejected));\n\nconst sameBytes = (left: Uint8Array, right: Uint8Array) =>\n left.length === right.length && left.every((byte, index) => byte === right[index]);\n\nconst binary = (minimum: number, maximum: number) =>\n Schema.String.check(\n Schema.isMaxLength(Math.ceil((maximum * 4) / 3)),\n Schema.makeFilter((value) => {\n const result = Base64Url.decode(value);\n\n return (\n result._tag === \"Success\" &&\n result.success.length >= minimum &&\n result.success.length <= maximum &&\n Base64Url.encode(result.success) === value\n );\n }),\n );\n\nconst bytes = Effect.fn(\"simpleWebAuthnBytes\")(function* (value: string) {\n const result = Base64Url.decode(value);\n\n if (result._tag === \"Failure\") return yield* rejected();\n\n return new Uint8Array(result.success);\n});\n\nconst duration = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 300000 }));\n\nconst prepareAuthenticationInput = Schema.Struct({\n profile: PasskeyProfile,\n challenge: PasskeyChallenge,\n timeoutMillis: duration,\n allowedCredentials: Schema.Array(PasskeyDescriptor).check(Schema.isMaxLength(64)),\n});\n\nconst prepareRegistrationInput = Schema.Struct({\n profile: PasskeyProfile,\n challenge: PasskeyChallenge,\n timeoutMillis: duration,\n userHandle: PasskeyUserHandle,\n name: PasskeyLabel,\n displayName: PasskeyLabel,\n excludedCredentials: Schema.Array(PasskeyDescriptor).check(Schema.isMaxLength(64)),\n});\n\nconst authenticationInput = Schema.Struct({\n ceremony: PasskeyCeremony,\n credential: PasskeyCredential,\n response: PasskeyAssertion,\n});\n\nconst registrationInput = Schema.Struct({\n ceremony: PasskeyCeremony,\n response: PasskeyAttestation,\n});\n\nconst envelope = {\n id: PasskeyProtocolCredentialId,\n rawId: PasskeyProtocolCredentialId,\n type: Schema.Literal(\"public-key\"),\n};\n\nconst authenticationResponse = Schema.Struct({\n ...envelope,\n response: Schema.Struct({\n clientDataJSON: binary(1, 8192),\n authenticatorData: binary(37, 16384),\n signature: binary(1, 1024),\n userHandle: Schema.optionalKey(Schema.NullOr(PasskeyUserHandle)),\n }),\n});\n\nconst registrationResponse = Schema.Struct({\n ...envelope,\n response: Schema.Struct({ clientDataJSON: binary(1, 8192), attestationObject: binary(1, 65536) }),\n});\n\nconst clientData = Schema.Struct({\n type: Schema.String,\n challenge: PasskeyChallenge,\n origin: Schema.String.check(Schema.isMaxLength(2048)),\n crossOrigin: Schema.optionalKey(Schema.Boolean),\n topOrigin: Schema.optionalKey(Schema.Unknown),\n});\n\ntype CborData =\n | string\n | number\n | boolean\n | null\n | Uint8Array\n | ReadonlyArray<CborData>\n | ReadonlyMap<string | number, CborData>;\n\nconst cborLeaf = Schema.Union([\n Schema.String.check(Schema.isMaxLength(8192)),\n Schema.Number.check(Schema.isFinite()),\n Schema.Boolean,\n Schema.Null,\n Schema.Uint8Array.check(Schema.makeFilter((value) => value.length <= 16384)),\n]);\n\nconst cborValue = (depth: number): Schema.Codec<CborData> => {\n if (depth === 0) return cborLeaf;\n const child = cborValue(depth - 1);\n\n return Schema.Union([\n cborLeaf,\n Schema.Array(child).check(Schema.isMaxLength(64)),\n Schema.ReadonlyMap(\n Schema.Union([Schema.String.check(Schema.isMaxLength(128)), Schema.Int]),\n child,\n ).check(Schema.makeFilter((value) => value.size <= 32)),\n ]);\n};\n\nconst cborMap = Schema.ReadonlyMap(\n Schema.Union([Schema.String.check(Schema.isMaxLength(128)), Schema.Int]),\n cborValue(4),\n).check(Schema.makeFilter((value) => value.size <= 32));\n\nconst encodeCbor = (value: CborData) => {\n // The maintained encoder reads these Schema-validated Maps/arrays; its type\n // requires mutable collections although no mutation is performed.\n return isoCBOR.encode(value as Parameters<typeof isoCBOR.encode>[0]);\n};\n\nconst exactMap = Effect.fn(\"simpleWebAuthnExactMap\")(function* (input: Uint8Array, value: unknown) {\n const result = yield* decode(cborMap, value);\n const encoded = yield* parsed(() => encodeCbor(result));\n\n if (!sameBytes(input, encoded)) return yield* rejected();\n\n return result;\n});\n\nconst byteValue = (minimum: number, maximum: number) =>\n Schema.Uint8Array.check(\n Schema.makeFilter((value) => value.length >= minimum && value.length <= maximum),\n );\n\nconst fresh = Effect.fn(\"simpleWebAuthnFresh\")(function* (ceremony: PasskeyCeremony) {\n const now = DateTime.toEpochMillis(yield* DateTime.now);\n\n if (\n ceremony.issuedAtMillis > now ||\n now >= ceremony.expiresAtMillis ||\n now >= ceremony.requestBindingExpiresAtMillis ||\n ceremony.expiresAtMillis <= ceremony.issuedAtMillis\n )\n return yield* rejected();\n});\n\nconst checkClient = Effect.fn(\"simpleWebAuthnClientData\")(function* (\n value: string,\n ceremony: PasskeyCeremony,\n type: \"webauthn.create\" | \"webauthn.get\",\n) {\n const client = yield* decode(clientData, yield* parsed(() => decodeClientDataJSON(value)));\n\n if (\n client.type !== type ||\n client.challenge !== ceremony.challenge ||\n !ceremony.profile.origins.includes(client.origin) ||\n client.crossOrigin === true ||\n \"topOrigin\" in client\n )\n return yield* rejected();\n\n return client;\n});\n\nconst checkAuthenticator = Effect.fn(\"simpleWebAuthnAuthenticatorData\")(function* (\n original: Uint8Array,\n registration: boolean,\n profile: PasskeyProfile,\n) {\n if (\n original.length < 37 ||\n original.length > 16384 ||\n Boolean(original[32]! & 64) !== registration\n )\n return yield* rejected();\n let prefix = 37;\n\n if (registration) {\n if (original.length < 55) return yield* rejected();\n\n const length = new DataView(\n original.buffer,\n original.byteOffset,\n original.byteLength,\n ).getUint16(53, false);\n\n if (length < 1 || length > 1023 || original.length < 55 + length) return yield* rejected();\n prefix = 55 + length;\n }\n const result = yield* parsed(() => parseAuthenticatorData(new Uint8Array(original)));\n\n if (\n !result.flags.up ||\n (profile.userVerification === \"required\" && !result.flags.uv) ||\n (result.flags.bs && !result.flags.be) ||\n result.flags.at !== registration ||\n result.flags.flagsInt !== original[32]\n )\n return yield* rejected();\n yield* decode(PasskeyCounter, result.counter);\n const chunks: Uint8Array[] = [original.slice(0, prefix)];\n\n if (registration) {\n const id = yield* decode(byteValue(1, 1023), result.credentialID);\n const key = yield* decode(byteValue(1, 8192), result.credentialPublicKey);\n\n if (!sameBytes(id, original.slice(55, prefix))) return yield* rejected();\n chunks.push(key);\n }\n if (result.flags.ed) {\n const extension = yield* decode(byteValue(1, 16384), result.extensionsDataBuffer);\n\n yield* exactMap(\n extension,\n yield* parsed(() => isoCBOR.decodeFirst<unknown>(new Uint8Array(extension))),\n );\n chunks.push(extension);\n } else if (result.extensionsDataBuffer !== undefined) return yield* rejected();\n const length = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n\n if (length !== original.length) return yield* rejected();\n let offset = 0;\n\n for (const chunk of chunks) {\n if (!sameBytes(chunk, original.slice(offset, offset + chunk.length))) return yield* rejected();\n offset += chunk.length;\n }\n\n const rpHash = new Uint8Array(\n yield* maintained(() =>\n globalThis.crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(profile.rpId)),\n ),\n );\n\n if (!sameBytes(rpHash, original.slice(0, 32))) return yield* rejected();\n\n return result;\n});\n\nconst checkKey = Effect.fn(\"simpleWebAuthnPublicKey\")(function* (\n input: Uint8Array,\n allowed: ReadonlyArray<-7 | -257>,\n expected?: -7 | -257,\n) {\n const map = yield* exactMap(\n input,\n yield* parsed(() => decodeCredentialPublicKey(new Uint8Array(input))),\n );\n\n const algorithmId = yield* decode(Schema.Literals([-7, -257]), map.get(3));\n\n if (!allowed.includes(algorithmId) || (expected !== undefined && algorithmId !== expected))\n return yield* rejected();\n let jwk: JsonWebKey;\n let algorithm: EcKeyImportParams | RsaHashedImportParams;\n\n if (algorithmId === -7) {\n if (\n map.size !== 5 ||\n ![1, 3, -1, -2, -3].every((key) => map.has(key)) ||\n map.get(1) !== 2 ||\n map.get(-1) !== 1\n )\n return yield* rejected();\n const x = yield* decode(byteValue(32, 32), map.get(-2));\n const y = yield* decode(byteValue(32, 32), map.get(-3));\n\n jwk = {\n kty: \"EC\",\n crv: \"P-256\",\n x: Base64Url.encode(x),\n y: Base64Url.encode(y),\n ext: false,\n };\n algorithm = { name: \"ECDSA\", namedCurve: \"P-256\" };\n } else {\n if (map.size !== 4 || ![1, 3, -1, -2].every((key) => map.has(key)) || map.get(1) !== 3)\n return yield* rejected();\n const n = yield* decode(byteValue(256, 512), map.get(-1));\n const e = yield* decode(byteValue(1, 4), map.get(-2));\n const exponent = e.reduce((value, byte) => value * 256 + byte, 0);\n\n if (\n n[0]! < 128 ||\n (n[n.length - 1]! & 1) === 0 ||\n e[0] === 0 ||\n exponent < 3 ||\n exponent % 2 !== 1\n )\n return yield* rejected();\n jwk = {\n kty: \"RSA\",\n alg: \"RS256\",\n n: Base64Url.encode(n),\n e: Base64Url.encode(e),\n ext: false,\n };\n algorithm = { name: \"RSASSA-PKCS1-v1_5\", hash: \"SHA-256\" };\n }\n yield* maintained(() =>\n globalThis.crypto.subtle.importKey(\"jwk\", jwk, algorithm, false, [\"verify\"]),\n );\n\n return algorithmId;\n});\n\nexport const makeSimpleWebAuthnPasskeyProtocol = Effect.fn(\"makeSimpleWebAuthnPasskeyProtocol\")(\n function* (\n options: SimpleWebAuthnPasskeyProtocolOptions,\n ): Effect.fn.Return<Protocol, PasskeyConfigurationError> {\n const select = yield* captureSimpleWebAuthnProfiles(options);\n\n const prepareAuthentication = Effect.fn(\"SimpleWebAuthnPasskeyProtocol.prepareAuthentication\")(\n function* (input: Input<\"prepareAuthentication\">) {\n const fixed = yield* capture(prepareAuthenticationInput, input);\n const profile = yield* select(fixed.profile);\n const challenge = yield* bytes(fixed.challenge);\n\n const result = yield* maintained(() =>\n generateAuthenticationOptions({\n rpID: profile.rpId,\n challenge,\n timeout: fixed.timeoutMillis,\n userVerification: profile.userVerification,\n allowCredentials: fixed.allowedCredentials.map((value) => ({ ...value })),\n }),\n );\n\n const value = yield* decode(PasskeyAuthenticationOptions, {\n challenge: result.challenge,\n rpId: result.rpId,\n timeout: result.timeout,\n userVerification: result.userVerification,\n allowCredentials: result.allowCredentials ?? [],\n });\n\n if (\n !(yield* samePasskey(PasskeyAuthenticationOptions, value, {\n challenge: fixed.challenge,\n rpId: profile.rpId,\n timeout: fixed.timeoutMillis,\n userVerification: profile.userVerification,\n allowCredentials: fixed.allowedCredentials,\n }))\n )\n return yield* unavailable();\n\n return yield* capture(PasskeyAuthenticationOptions, value);\n },\n unexpected,\n );\n\n const prepareRegistration = Effect.fn(\"SimpleWebAuthnPasskeyProtocol.prepareRegistration\")(\n function* (input: Input<\"prepareRegistration\">) {\n const fixed = yield* capture(prepareRegistrationInput, input);\n const profile = yield* select(fixed.profile);\n\n const challenge = yield* bytes(fixed.challenge),\n userID = yield* bytes(fixed.userHandle);\n\n const result = yield* maintained(() =>\n generateRegistrationOptions({\n rpName: profile.rpName,\n rpID: profile.rpId,\n userName: fixed.name,\n userDisplayName: fixed.displayName,\n userID,\n challenge,\n timeout: fixed.timeoutMillis,\n attestationType: \"none\",\n supportedAlgorithmIDs: [...profile.algorithms],\n authenticatorSelection: {\n residentKey: profile.residentKey,\n userVerification: profile.userVerification,\n },\n excludeCredentials: fixed.excludedCredentials.map((value) => ({ ...value })),\n }),\n );\n\n const value = yield* decode(PasskeyRegistrationOptions, {\n challenge: result.challenge,\n rp: result.rp,\n user: result.user,\n pubKeyCredParams: result.pubKeyCredParams,\n timeout: result.timeout,\n attestation: result.attestation,\n authenticatorSelection: result.authenticatorSelection,\n excludeCredentials: result.excludeCredentials ?? [],\n });\n\n const expected = {\n challenge: fixed.challenge,\n rp: { id: profile.rpId, name: profile.rpName },\n user: { id: fixed.userHandle, name: fixed.name, displayName: fixed.displayName },\n pubKeyCredParams: profile.algorithms.map((alg) => ({ type: \"public-key\", alg })),\n timeout: fixed.timeoutMillis,\n attestation: \"none\",\n authenticatorSelection: {\n residentKey: profile.residentKey,\n userVerification: profile.userVerification,\n },\n excludeCredentials: fixed.excludedCredentials,\n };\n\n if (\n !(yield* samePasskey(\n PasskeyRegistrationOptions,\n value,\n yield* decode(PasskeyRegistrationOptions, expected),\n ))\n )\n return yield* unavailable();\n\n return yield* capture(PasskeyRegistrationOptions, value);\n },\n unexpected,\n );\n\n const verifyRegistration = Effect.fn(\"SimpleWebAuthnPasskeyProtocol.verifyRegistration\")(\n function* (input: Input<\"verifyRegistration\">) {\n const fixed = yield* capture(registrationInput, input),\n ceremony = fixed.ceremony;\n\n const profile = yield* select(ceremony.profile);\n\n if (\n (ceremony.purpose !== \"registration\" || ceremony.context._tag !== \"Registration\") &&\n (ceremony.purpose !== \"enrollment\" || ceremony.context._tag !== \"Enrollment\")\n )\n return yield* rejected();\n yield* fresh(ceremony);\n\n const wire = yield* decode(\n Schema.fromJsonString(registrationResponse),\n Redacted.value(fixed.response),\n );\n\n if (wire.id !== wire.rawId) return yield* rejected();\n\n const client = yield* checkClient(\n wire.response.clientDataJSON,\n ceremony,\n \"webauthn.create\",\n );\n\n const attestationBytes = yield* bytes(wire.response.attestationObject);\n\n const attestation = yield* exactMap(\n attestationBytes,\n yield* parsed(() => decodeAttestationObject(new Uint8Array(attestationBytes))),\n );\n\n if (\n attestation.size !== 3 ||\n attestation.get(\"fmt\") !== \"none\" ||\n !attestation.has(\"attStmt\") ||\n !attestation.has(\"authData\")\n )\n return yield* rejected();\n const statement = yield* decode(cborMap, attestation.get(\"attStmt\"));\n\n if (statement.size !== 0) return yield* rejected();\n const authenticatorBytes = yield* decode(byteValue(37, 16384), attestation.get(\"authData\"));\n const auth = yield* checkAuthenticator(authenticatorBytes, true, profile);\n const id = yield* decode(byteValue(1, 1023), auth.credentialID);\n const key = yield* decode(byteValue(1, 8192), auth.credentialPublicKey);\n\n if (Base64Url.encode(id) !== wire.id) return yield* rejected();\n const algorithm = yield* checkKey(key, profile.algorithms);\n\n const result = yield* maintained(() =>\n verifyRegistrationResponse({\n response: { ...wire, clientExtensionResults: {} },\n expectedChallenge: ceremony.challenge,\n expectedOrigin: [...profile.origins],\n expectedRPID: profile.rpId,\n expectedType: \"webauthn.create\",\n requireUserPresence: true,\n requireUserVerification: profile.userVerification === \"required\",\n supportedAlgorithmIDs: [...profile.algorithms],\n }),\n );\n\n if (!result.verified || result.registrationInfo === undefined) return yield* rejected();\n const info = result.registrationInfo;\n\n if (\n info.fmt !== \"none\" ||\n info.origin !== client.origin ||\n info.rpID !== profile.rpId ||\n info.credential.id !== wire.id ||\n !sameBytes(info.credential.publicKey, key) ||\n info.credential.counter !== auth.counter ||\n info.userVerified !== auth.flags.uv ||\n (info.credentialDeviceType === \"multiDevice\") !== auth.flags.be ||\n info.credentialBackedUp !== auth.flags.bs\n )\n return yield* rejected();\n yield* fresh(ceremony);\n\n return yield* capture(\n PasskeyRegistrationVerified,\n yield* decode(PasskeyRegistrationVerified, {\n protocolCredentialId: info.credential.id,\n publicKey: Base64Url.encode(info.credential.publicKey),\n algorithm,\n counter: info.credential.counter,\n userVerified: info.userVerified,\n backupEligible: info.credentialDeviceType === \"multiDevice\",\n backupState: info.credentialBackedUp,\n }),\n );\n },\n unexpected,\n );\n\n const verifyAuthentication = Effect.fn(\"SimpleWebAuthnPasskeyProtocol.verifyAuthentication\")(\n function* (input: Input<\"verifyAuthentication\">) {\n const fixed = yield* capture(authenticationInput, input),\n ceremony = fixed.ceremony,\n credential = fixed.credential;\n\n const profile = yield* select(ceremony.profile),\n original = yield* select(credential.profile);\n\n const contexts = {\n \"sign-in\": \"SignIn\",\n pending: \"Pending\",\n \"step-up\": \"StepUp\",\n action: \"Action\",\n } as const;\n\n if (\n ceremony.purpose === \"registration\" ||\n ceremony.purpose === \"enrollment\" ||\n contexts[ceremony.purpose] !== ceremony.context._tag ||\n !credential.active ||\n credential.rpId !== profile.rpId ||\n original.rpId !== profile.rpId ||\n !original.algorithms.includes(credential.algorithm) ||\n !profile.algorithms.includes(credential.algorithm)\n )\n return yield* rejected();\n yield* fresh(ceremony);\n\n const wire = yield* decode(\n Schema.fromJsonString(authenticationResponse),\n Redacted.value(fixed.response),\n );\n\n const userHandle = wire.response.userHandle ?? undefined;\n\n if (\n wire.id !== wire.rawId ||\n wire.id !== credential.protocolCredentialId ||\n (userHandle !== undefined && userHandle !== credential.userHandle) ||\n (ceremony.context._tag === \"SignIn\" && userHandle === undefined) ||\n (ceremony.allowedCredentials.length > 0 &&\n !ceremony.allowedCredentials.some((value) => value.id === wire.id))\n )\n return yield* rejected();\n const client = yield* checkClient(wire.response.clientDataJSON, ceremony, \"webauthn.get\");\n\n const auth = yield* checkAuthenticator(\n yield* bytes(wire.response.authenticatorData),\n false,\n profile,\n );\n\n if (\n auth.flags.be !== credential.backupEligible ||\n (!credential.backupEligible &&\n (credential.counter > 0 || auth.counter > 0) &&\n auth.counter <= credential.counter)\n )\n return yield* rejected();\n const publicKey = yield* bytes(credential.publicKey);\n\n yield* checkKey(publicKey, profile.algorithms, credential.algorithm);\n\n const result = yield* maintained(() =>\n verifyAuthenticationResponse({\n response: {\n ...wire,\n response: { ...wire.response, userHandle },\n clientExtensionResults: {},\n },\n expectedChallenge: ceremony.challenge,\n expectedOrigin: [...profile.origins],\n expectedRPID: profile.rpId,\n expectedType: \"webauthn.get\",\n requireUserVerification: profile.userVerification === \"required\",\n credential: {\n id: credential.protocolCredentialId,\n publicKey,\n counter: credential.backupEligible ? 0 : credential.counter,\n },\n }),\n );\n\n if (!result.verified) return yield* rejected();\n const info = result.authenticationInfo;\n\n if (\n info.credentialID !== wire.id ||\n info.origin !== client.origin ||\n info.rpID !== profile.rpId ||\n info.newCounter !== auth.counter ||\n info.userVerified !== auth.flags.uv ||\n (info.credentialDeviceType === \"multiDevice\") !== credential.backupEligible ||\n info.credentialBackedUp !== auth.flags.bs\n )\n return yield* rejected();\n yield* fresh(ceremony);\n\n return yield* capture(\n PasskeyAssertionVerified,\n yield* decode(PasskeyAssertionVerified, {\n protocolCredentialId: info.credentialID,\n ...(userHandle === undefined ? {} : { userHandle }),\n counter: info.newCounter,\n userVerified: info.userVerified,\n backupEligible: info.credentialDeviceType === \"multiDevice\",\n backupState: info.credentialBackedUp,\n }),\n );\n },\n unexpected,\n );\n\n return PasskeyProtocol.of({\n prepareAuthentication,\n prepareRegistration,\n verifyRegistration,\n verifyAuthentication,\n });\n },\n);\n\n/** Requires the same host profiles as the strategy. */\nexport const layerSimpleWebAuthnPasskeyProtocol = Layer.effect(\n PasskeyProtocol,\n Effect.flatMap(PasskeyConfig, makeSimpleWebAuthnPasskeyProtocol),\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"protocol.mjs","names":[],"sources":["../../../src/internal/server/protocol.ts"],"sourcesContent":["import {\n generateAuthenticationOptions,\n generateRegistrationOptions,\n verifyAuthenticationResponse,\n verifyRegistrationResponse,\n} from \"@simplewebauthn/server\";\nimport {\n decodeAttestationObject,\n decodeClientDataJSON,\n decodeCredentialPublicKey,\n isoCBOR,\n parseAuthenticatorData,\n} from \"@simplewebauthn/server/helpers\";\nimport {\n type PasskeyConfigurationError,\n PasskeyProtocolRejected,\n PasskeyUnavailable,\n PasskeyAssertion,\n PasskeyAssertionVerified,\n PasskeyAttestation,\n PasskeyAuthenticationOptions,\n PasskeyCeremony,\n PasskeyChallenge,\n PasskeyCounter,\n PasskeyCredential,\n PasskeyDescriptor,\n PasskeyLabel,\n PasskeyProfile,\n PasskeyProtocolCredentialId,\n PasskeyRegistrationOptions,\n PasskeyRegistrationVerified,\n PasskeyUserHandle,\n PasskeyConfig,\n PasskeyProtocol,\n samePasskey,\n snapshotPasskey,\n} from \"@yielded/auth/Passkey\";\nimport { reportAuthFailure } from \"@yielded/auth/Persistence\";\nimport type { Context } from \"effect\";\nimport { Cause, DateTime, Effect, Layer, Redacted, Schema } from \"effect\";\nimport { Base64Url } from \"effect/encoding\";\n\nimport { captureSimpleWebAuthnProfiles } from \"./configuration\";\nimport type { SimpleWebAuthnPasskeyProtocolOptions } from \"./models\";\n\ntype Protocol = Context.Service.Shape<typeof PasskeyProtocol>;\ntype Input<K extends keyof Protocol> = Parameters<Protocol[K]>[0];\nconst rejected = () => PasskeyProtocolRejected.make({});\nconst unavailable = () => PasskeyUnavailable.make({});\n\nconst unexpected = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n effect.pipe(\n Effect.catchCause((cause): Effect.Effect<never, E | PasskeyUnavailable> =>\n Cause.hasDies(cause)\n ? reportAuthFailure(\"passkey-protocol\", cause).pipe(\n Effect.andThen(Effect.fail(unavailable())),\n )\n : Effect.failCause(cause),\n ),\n );\n\nconst maintained = <A>(call: () => Promise<A>) =>\n Effect.tryPromise(call).pipe(\n Effect.onError((cause) => reportAuthFailure(\"passkey-protocol\", cause)),\n Effect.mapError(unavailable),\n );\n\nconst parsed = <A>(call: () => A) => Effect.try({ try: call, catch: rejected });\n\nconst decode = <S extends Schema.Codec<unknown, unknown, never, never>>(\n schema: S,\n input: unknown,\n) =>\n // Maintained JSON/CBOR parsers and their map lookups return untyped wire data.\n // eslint-disable-next-line no-restricted-properties\n Schema.decodeUnknownEffect(schema)(input).pipe(Effect.mapError(rejected));\n\nconst capture = <S extends Schema.Codec<unknown, unknown, never, never>>(\n schema: S,\n input: S[\"Type\"],\n) => snapshotPasskey(schema, input).pipe(Effect.mapError(rejected));\n\nconst sameBytes = (left: Uint8Array, right: Uint8Array) =>\n left.length === right.length && left.every((byte, index) => byte === right[index]);\n\nconst binary = (minimum: number, maximum: number) =>\n Schema.String.check(\n Schema.isMaxLength(Math.ceil((maximum * 4) / 3)),\n Schema.makeFilter((value) => {\n const result = Base64Url.decode(value);\n\n return (\n result._tag === \"Success\" &&\n result.success.length >= minimum &&\n result.success.length <= maximum &&\n Base64Url.encode(result.success) === value\n );\n }),\n );\n\nconst bytes = Effect.fn(\"simpleWebAuthnBytes\")(function* (value: string) {\n const result = Base64Url.decode(value);\n\n if (result._tag === \"Failure\") return yield* rejected();\n\n return new Uint8Array(result.success);\n});\n\nconst duration = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 300000 }));\n\nconst prepareAuthenticationInput = Schema.Struct({\n profile: PasskeyProfile,\n challenge: PasskeyChallenge,\n timeoutMillis: duration,\n allowedCredentials: Schema.Array(PasskeyDescriptor).check(Schema.isMaxLength(64)),\n});\n\nconst prepareRegistrationInput = Schema.Struct({\n profile: PasskeyProfile,\n challenge: PasskeyChallenge,\n timeoutMillis: duration,\n userHandle: PasskeyUserHandle,\n name: PasskeyLabel,\n displayName: PasskeyLabel,\n excludedCredentials: Schema.Array(PasskeyDescriptor).check(Schema.isMaxLength(64)),\n});\n\nconst authenticationInput = Schema.Struct({\n ceremony: PasskeyCeremony,\n credential: PasskeyCredential,\n response: PasskeyAssertion,\n});\n\nconst registrationInput = Schema.Struct({\n ceremony: PasskeyCeremony,\n response: PasskeyAttestation,\n});\n\nconst envelope = {\n id: PasskeyProtocolCredentialId,\n rawId: PasskeyProtocolCredentialId,\n type: Schema.Literal(\"public-key\"),\n};\n\nconst authenticationResponse = Schema.Struct({\n ...envelope,\n response: Schema.Struct({\n clientDataJSON: binary(1, 8192),\n authenticatorData: binary(37, 16384),\n signature: binary(1, 1024),\n userHandle: Schema.optionalKey(Schema.NullOr(PasskeyUserHandle)),\n }),\n});\n\nconst registrationResponse = Schema.Struct({\n ...envelope,\n response: Schema.Struct({ clientDataJSON: binary(1, 8192), attestationObject: binary(1, 65536) }),\n});\n\nconst clientData = Schema.Struct({\n type: Schema.String,\n challenge: PasskeyChallenge,\n origin: Schema.String.check(Schema.isMaxLength(2048)),\n crossOrigin: Schema.optionalKey(Schema.Boolean),\n topOrigin: Schema.optionalKey(Schema.Unknown),\n});\n\ntype CborData =\n | string\n | number\n | boolean\n | null\n | Uint8Array\n | ReadonlyArray<CborData>\n | ReadonlyMap<string | number, CborData>;\n\nconst cborLeaf = Schema.Union([\n Schema.String.check(Schema.isMaxLength(8192)),\n Schema.Number.check(Schema.isFinite()),\n Schema.Boolean,\n Schema.Null,\n Schema.Uint8Array.check(Schema.makeFilter((value) => value.length <= 16384)),\n]);\n\nconst cborValue = (depth: number): Schema.Codec<CborData> => {\n if (depth === 0) return cborLeaf;\n const child = cborValue(depth - 1);\n\n return Schema.Union([\n cborLeaf,\n Schema.Array(child).check(Schema.isMaxLength(64)),\n Schema.ReadonlyMap(\n Schema.Union([Schema.String.check(Schema.isMaxLength(128)), Schema.Int]),\n child,\n ).check(Schema.makeFilter((value) => value.size <= 32)),\n ]);\n};\n\nconst cborMap = Schema.ReadonlyMap(\n Schema.Union([Schema.String.check(Schema.isMaxLength(128)), Schema.Int]),\n cborValue(4),\n).check(Schema.makeFilter((value) => value.size <= 32));\n\nconst encodeCbor = (value: CborData) => {\n // The maintained encoder reads these Schema-validated Maps/arrays; its type\n // requires mutable collections although no mutation is performed.\n return isoCBOR.encode(value as Parameters<typeof isoCBOR.encode>[0]);\n};\n\nconst exactMap = Effect.fn(\"simpleWebAuthnExactMap\")(function* (input: Uint8Array, value: unknown) {\n const result = yield* decode(cborMap, value);\n const encoded = yield* parsed(() => encodeCbor(result));\n\n if (!sameBytes(input, encoded)) return yield* rejected();\n\n return result;\n});\n\nconst byteValue = (minimum: number, maximum: number) =>\n Schema.Uint8Array.check(\n Schema.makeFilter((value) => value.length >= minimum && value.length <= maximum),\n );\n\nconst fresh = Effect.fn(\"simpleWebAuthnFresh\")(function* (ceremony: PasskeyCeremony) {\n const now = DateTime.toEpochMillis(yield* DateTime.now);\n\n if (\n ceremony.issuedAtMillis > now ||\n now >= ceremony.expiresAtMillis ||\n now >= ceremony.requestBindingExpiresAtMillis ||\n ceremony.expiresAtMillis <= ceremony.issuedAtMillis\n )\n return yield* rejected();\n});\n\nconst checkClient = Effect.fn(\"simpleWebAuthnClientData\")(function* (\n value: string,\n ceremony: PasskeyCeremony,\n type: \"webauthn.create\" | \"webauthn.get\",\n) {\n const client = yield* decode(clientData, yield* parsed(() => decodeClientDataJSON(value)));\n\n if (\n client.type !== type ||\n client.challenge !== ceremony.challenge ||\n !ceremony.profile.origins.includes(client.origin) ||\n client.crossOrigin === true ||\n \"topOrigin\" in client\n )\n return yield* rejected();\n\n return client;\n});\n\nconst checkAuthenticator = Effect.fn(\"simpleWebAuthnAuthenticatorData\")(function* (\n original: Uint8Array,\n registration: boolean,\n profile: PasskeyProfile,\n) {\n if (\n original.length < 37 ||\n original.length > 16384 ||\n Boolean(original[32]! & 64) !== registration\n )\n return yield* rejected();\n let prefix = 37;\n\n if (registration) {\n if (original.length < 55) return yield* rejected();\n\n const length = new DataView(\n original.buffer,\n original.byteOffset,\n original.byteLength,\n ).getUint16(53, false);\n\n if (length < 1 || length > 1023 || original.length < 55 + length) return yield* rejected();\n prefix = 55 + length;\n }\n const result = yield* parsed(() => parseAuthenticatorData(new Uint8Array(original)));\n\n if (\n !result.flags.up ||\n (profile.userVerification === \"required\" && !result.flags.uv) ||\n (result.flags.bs && !result.flags.be) ||\n result.flags.at !== registration ||\n result.flags.flagsInt !== original[32]\n )\n return yield* rejected();\n yield* decode(PasskeyCounter, result.counter);\n const chunks: Uint8Array[] = [original.slice(0, prefix)];\n\n if (registration) {\n const id = yield* decode(byteValue(1, 1023), result.credentialID);\n const key = yield* decode(byteValue(1, 8192), result.credentialPublicKey);\n\n if (!sameBytes(id, original.slice(55, prefix))) return yield* rejected();\n chunks.push(key);\n }\n if (result.flags.ed) {\n const extension = yield* decode(byteValue(1, 16384), result.extensionsDataBuffer);\n\n yield* exactMap(\n extension,\n yield* parsed(() => isoCBOR.decodeFirst<unknown>(new Uint8Array(extension))),\n );\n chunks.push(extension);\n } else if (result.extensionsDataBuffer !== undefined) return yield* rejected();\n const length = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n\n if (length !== original.length) return yield* rejected();\n let offset = 0;\n\n for (const chunk of chunks) {\n if (!sameBytes(chunk, original.slice(offset, offset + chunk.length))) return yield* rejected();\n offset += chunk.length;\n }\n\n const rpHash = new Uint8Array(\n yield* maintained(() =>\n globalThis.crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(profile.rpId)),\n ),\n );\n\n if (!sameBytes(rpHash, original.slice(0, 32))) return yield* rejected();\n\n return result;\n});\n\nconst checkKey = Effect.fn(\"simpleWebAuthnPublicKey\")(function* (\n input: Uint8Array,\n allowed: ReadonlyArray<-7 | -257>,\n expected?: -7 | -257,\n) {\n const map = yield* exactMap(\n input,\n yield* parsed(() => decodeCredentialPublicKey(new Uint8Array(input))),\n );\n\n const algorithmId = yield* decode(Schema.Literals([-7, -257]), map.get(3));\n\n if (!allowed.includes(algorithmId) || (expected !== undefined && algorithmId !== expected))\n return yield* rejected();\n let jwk: JsonWebKey;\n let algorithm: EcKeyImportParams | RsaHashedImportParams;\n\n if (algorithmId === -7) {\n if (\n map.size !== 5 ||\n ![1, 3, -1, -2, -3].every((key) => map.has(key)) ||\n map.get(1) !== 2 ||\n map.get(-1) !== 1\n )\n return yield* rejected();\n const x = yield* decode(byteValue(32, 32), map.get(-2));\n const y = yield* decode(byteValue(32, 32), map.get(-3));\n\n jwk = {\n kty: \"EC\",\n crv: \"P-256\",\n x: Base64Url.encode(x),\n y: Base64Url.encode(y),\n ext: false,\n };\n algorithm = { name: \"ECDSA\", namedCurve: \"P-256\" };\n } else {\n if (map.size !== 4 || ![1, 3, -1, -2].every((key) => map.has(key)) || map.get(1) !== 3)\n return yield* rejected();\n const n = yield* decode(byteValue(256, 512), map.get(-1));\n const e = yield* decode(byteValue(1, 4), map.get(-2));\n const exponent = e.reduce((value, byte) => value * 256 + byte, 0);\n\n if (\n n[0]! < 128 ||\n (n[n.length - 1]! & 1) === 0 ||\n e[0] === 0 ||\n exponent < 3 ||\n exponent % 2 !== 1\n )\n return yield* rejected();\n jwk = {\n kty: \"RSA\",\n alg: \"RS256\",\n n: Base64Url.encode(n),\n e: Base64Url.encode(e),\n ext: false,\n };\n algorithm = { name: \"RSASSA-PKCS1-v1_5\", hash: \"SHA-256\" };\n }\n yield* maintained(() =>\n globalThis.crypto.subtle.importKey(\"jwk\", jwk, algorithm, false, [\"verify\"]),\n );\n\n return algorithmId;\n});\n\nexport const makeSimpleWebAuthnPasskeyProtocol = Effect.fn(\"makeSimpleWebAuthnPasskeyProtocol\")(\n function* (\n options: SimpleWebAuthnPasskeyProtocolOptions,\n ): Effect.fn.Return<Protocol, PasskeyConfigurationError> {\n const select = yield* captureSimpleWebAuthnProfiles(options);\n\n const prepareAuthentication = Effect.fn(\"SimpleWebAuthnPasskeyProtocol.prepareAuthentication\")(\n function* (input: Input<\"prepareAuthentication\">) {\n const fixed = yield* capture(prepareAuthenticationInput, input);\n const profile = yield* select(fixed.profile);\n const challenge = yield* bytes(fixed.challenge);\n\n const result = yield* maintained(() =>\n generateAuthenticationOptions({\n rpID: profile.rpId,\n challenge,\n timeout: fixed.timeoutMillis,\n userVerification: profile.userVerification,\n allowCredentials: fixed.allowedCredentials.map((value) => ({ ...value })),\n }),\n );\n\n const value = yield* decode(PasskeyAuthenticationOptions, {\n challenge: result.challenge,\n rpId: result.rpId,\n timeout: result.timeout,\n userVerification: result.userVerification,\n allowCredentials: result.allowCredentials ?? [],\n });\n\n if (\n !(yield* samePasskey(PasskeyAuthenticationOptions, value, {\n challenge: fixed.challenge,\n rpId: profile.rpId,\n timeout: fixed.timeoutMillis,\n userVerification: profile.userVerification,\n allowCredentials: fixed.allowedCredentials,\n }))\n )\n return yield* unavailable();\n\n return yield* capture(PasskeyAuthenticationOptions, value);\n },\n unexpected,\n );\n\n const prepareRegistration = Effect.fn(\"SimpleWebAuthnPasskeyProtocol.prepareRegistration\")(\n function* (input: Input<\"prepareRegistration\">) {\n const fixed = yield* capture(prepareRegistrationInput, input);\n const profile = yield* select(fixed.profile);\n\n const challenge = yield* bytes(fixed.challenge),\n userID = yield* bytes(fixed.userHandle);\n\n const result = yield* maintained(() =>\n generateRegistrationOptions({\n rpName: profile.rpName,\n rpID: profile.rpId,\n userName: fixed.name,\n userDisplayName: fixed.displayName,\n userID,\n challenge,\n timeout: fixed.timeoutMillis,\n attestationType: \"none\",\n supportedAlgorithmIDs: [...profile.algorithms],\n authenticatorSelection: {\n residentKey: profile.residentKey,\n userVerification: profile.userVerification,\n },\n excludeCredentials: fixed.excludedCredentials.map((value) => ({ ...value })),\n }),\n );\n\n const value = yield* decode(PasskeyRegistrationOptions, {\n challenge: result.challenge,\n rp: result.rp,\n user: result.user,\n pubKeyCredParams: result.pubKeyCredParams,\n timeout: result.timeout,\n attestation: result.attestation,\n authenticatorSelection: result.authenticatorSelection,\n excludeCredentials: result.excludeCredentials ?? [],\n });\n\n const expected = {\n challenge: fixed.challenge,\n rp: { id: profile.rpId, name: profile.rpName },\n user: { id: fixed.userHandle, name: fixed.name, displayName: fixed.displayName },\n pubKeyCredParams: profile.algorithms.map((alg) => ({ type: \"public-key\", alg })),\n timeout: fixed.timeoutMillis,\n attestation: \"none\",\n authenticatorSelection: {\n residentKey: profile.residentKey,\n userVerification: profile.userVerification,\n },\n excludeCredentials: fixed.excludedCredentials,\n };\n\n if (\n !(yield* samePasskey(\n PasskeyRegistrationOptions,\n value,\n yield* decode(PasskeyRegistrationOptions, expected),\n ))\n )\n return yield* unavailable();\n\n return yield* capture(PasskeyRegistrationOptions, value);\n },\n unexpected,\n );\n\n const verifyRegistration = Effect.fn(\"SimpleWebAuthnPasskeyProtocol.verifyRegistration\")(\n function* (input: Input<\"verifyRegistration\">) {\n const fixed = yield* capture(registrationInput, input),\n ceremony = fixed.ceremony;\n\n const profile = yield* select(ceremony.profile);\n\n if (\n (ceremony.purpose !== \"registration\" || ceremony.context._tag !== \"Registration\") &&\n (ceremony.purpose !== \"enrollment\" || ceremony.context._tag !== \"Enrollment\")\n )\n return yield* rejected();\n yield* fresh(ceremony);\n\n const wire = yield* decode(\n Schema.fromJsonString(registrationResponse),\n Redacted.value(fixed.response),\n );\n\n if (wire.id !== wire.rawId) return yield* rejected();\n\n const client = yield* checkClient(\n wire.response.clientDataJSON,\n ceremony,\n \"webauthn.create\",\n );\n\n const attestationBytes = yield* bytes(wire.response.attestationObject);\n\n const attestation = yield* exactMap(\n attestationBytes,\n yield* parsed(() => decodeAttestationObject(new Uint8Array(attestationBytes))),\n );\n\n if (\n attestation.size !== 3 ||\n attestation.get(\"fmt\") !== \"none\" ||\n !attestation.has(\"attStmt\") ||\n !attestation.has(\"authData\")\n )\n return yield* rejected();\n const statement = yield* decode(cborMap, attestation.get(\"attStmt\"));\n\n if (statement.size !== 0) return yield* rejected();\n const authenticatorBytes = yield* decode(byteValue(37, 16384), attestation.get(\"authData\"));\n const auth = yield* checkAuthenticator(authenticatorBytes, true, profile);\n const id = yield* decode(byteValue(1, 1023), auth.credentialID);\n const key = yield* decode(byteValue(1, 8192), auth.credentialPublicKey);\n\n if (Base64Url.encode(id) !== wire.id) return yield* rejected();\n const algorithm = yield* checkKey(key, profile.algorithms);\n\n const result = yield* maintained(() =>\n verifyRegistrationResponse({\n response: { ...wire, clientExtensionResults: {} },\n expectedChallenge: ceremony.challenge,\n expectedOrigin: [...profile.origins],\n expectedRPID: profile.rpId,\n expectedType: \"webauthn.create\",\n requireUserPresence: true,\n requireUserVerification: profile.userVerification === \"required\",\n supportedAlgorithmIDs: [...profile.algorithms],\n }),\n );\n\n if (!result.verified || result.registrationInfo === undefined) return yield* rejected();\n const info = result.registrationInfo;\n\n if (\n info.fmt !== \"none\" ||\n info.origin !== client.origin ||\n info.rpID !== profile.rpId ||\n info.credential.id !== wire.id ||\n !sameBytes(info.credential.publicKey, key) ||\n info.credential.counter !== auth.counter ||\n info.userVerified !== auth.flags.uv ||\n (info.credentialDeviceType === \"multiDevice\") !== auth.flags.be ||\n info.credentialBackedUp !== auth.flags.bs\n )\n return yield* rejected();\n yield* fresh(ceremony);\n\n return yield* capture(\n PasskeyRegistrationVerified,\n yield* decode(PasskeyRegistrationVerified, {\n protocolCredentialId: info.credential.id,\n publicKey: Base64Url.encode(info.credential.publicKey),\n algorithm,\n counter: info.credential.counter,\n userVerified: info.userVerified,\n backupEligible: info.credentialDeviceType === \"multiDevice\",\n backupState: info.credentialBackedUp,\n }),\n );\n },\n unexpected,\n );\n\n const verifyAuthentication = Effect.fn(\"SimpleWebAuthnPasskeyProtocol.verifyAuthentication\")(\n function* (input: Input<\"verifyAuthentication\">) {\n const fixed = yield* capture(authenticationInput, input),\n ceremony = fixed.ceremony,\n credential = fixed.credential;\n\n const profile = yield* select(ceremony.profile),\n original = yield* select(credential.profile);\n\n const contexts = {\n \"sign-in\": \"SignIn\",\n pending: \"Pending\",\n \"step-up\": \"StepUp\",\n action: \"Action\",\n } as const;\n\n if (\n ceremony.purpose === \"registration\" ||\n ceremony.purpose === \"enrollment\" ||\n contexts[ceremony.purpose] !== ceremony.context._tag ||\n !credential.active ||\n credential.rpId !== profile.rpId ||\n original.rpId !== profile.rpId ||\n !original.algorithms.includes(credential.algorithm) ||\n !profile.algorithms.includes(credential.algorithm)\n )\n return yield* rejected();\n yield* fresh(ceremony);\n\n const wire = yield* decode(\n Schema.fromJsonString(authenticationResponse),\n Redacted.value(fixed.response),\n );\n\n const { userHandle: rawUserHandle, ...assertionResponse } = wire.response;\n const userHandle = rawUserHandle ?? undefined;\n\n if (\n wire.id !== wire.rawId ||\n wire.id !== credential.protocolCredentialId ||\n (userHandle !== undefined && userHandle !== credential.userHandle) ||\n (ceremony.context._tag === \"SignIn\" && userHandle === undefined) ||\n (ceremony.allowedCredentials.length > 0 &&\n !ceremony.allowedCredentials.some((value) => value.id === wire.id))\n )\n return yield* rejected();\n const client = yield* checkClient(wire.response.clientDataJSON, ceremony, \"webauthn.get\");\n\n const auth = yield* checkAuthenticator(\n yield* bytes(wire.response.authenticatorData),\n false,\n profile,\n );\n\n if (\n auth.flags.be !== credential.backupEligible ||\n (!credential.backupEligible &&\n (credential.counter > 0 || auth.counter > 0) &&\n auth.counter <= credential.counter)\n )\n return yield* rejected();\n const publicKey = yield* bytes(credential.publicKey);\n\n yield* checkKey(publicKey, profile.algorithms, credential.algorithm);\n\n const result = yield* maintained(() =>\n verifyAuthenticationResponse({\n response: {\n ...wire,\n response: {\n ...assertionResponse,\n ...(userHandle === undefined ? {} : { userHandle }),\n },\n clientExtensionResults: {},\n },\n expectedChallenge: ceremony.challenge,\n expectedOrigin: [...profile.origins],\n expectedRPID: profile.rpId,\n expectedType: \"webauthn.get\",\n requireUserVerification: profile.userVerification === \"required\",\n credential: {\n id: credential.protocolCredentialId,\n publicKey,\n counter: credential.backupEligible ? 0 : credential.counter,\n },\n }),\n );\n\n if (!result.verified) return yield* rejected();\n const info = result.authenticationInfo;\n\n if (\n info.credentialID !== wire.id ||\n info.origin !== client.origin ||\n info.rpID !== profile.rpId ||\n info.newCounter !== auth.counter ||\n info.userVerified !== auth.flags.uv ||\n (info.credentialDeviceType === \"multiDevice\") !== credential.backupEligible ||\n info.credentialBackedUp !== auth.flags.bs\n )\n return yield* rejected();\n yield* fresh(ceremony);\n\n return yield* capture(\n PasskeyAssertionVerified,\n yield* decode(PasskeyAssertionVerified, {\n protocolCredentialId: info.credentialID,\n ...(userHandle === undefined ? {} : { userHandle }),\n counter: info.newCounter,\n userVerified: info.userVerified,\n backupEligible: info.credentialDeviceType === \"multiDevice\",\n backupState: info.credentialBackedUp,\n }),\n );\n },\n unexpected,\n );\n\n return PasskeyProtocol.of({\n prepareAuthentication,\n prepareRegistration,\n verifyRegistration,\n verifyAuthentication,\n });\n },\n);\n\n/** Requires the same host profiles as the strategy. */\nexport const layerSimpleWebAuthnPasskeyProtocol = Layer.effect(\n PasskeyProtocol,\n Effect.flatMap(PasskeyConfig, makeSimpleWebAuthnPasskeyProtocol),\n);\n"],"mappings":";;;;;;;;AA+CA,MAAM,iBAAiB,wBAAwB,KAAK,CAAC,CAAC;AACtD,MAAM,oBAAoB,mBAAmB,KAAK,CAAC,CAAC;AAEpD,MAAM,cAAuB,WAC3B,OAAO,KACL,OAAO,YAAY,UACjB,MAAM,QAAQ,KAAK,IACf,kBAAkB,oBAAoB,KAAK,CAAC,CAAC,KAC3C,OAAO,QAAQ,OAAO,KAAK,YAAY,CAAC,CAAC,CAC3C,IACA,OAAO,UAAU,KAAK,CAC5B,CACF;AAEF,MAAM,cAAiB,SACrB,OAAO,WAAW,IAAI,CAAC,CAAC,KACtB,OAAO,SAAS,UAAU,kBAAkB,oBAAoB,KAAK,CAAC,GACtE,OAAO,SAAS,WAAW,CAC7B;AAEF,MAAM,UAAa,SAAkB,OAAO,IAAI;CAAE,KAAK;CAAM,OAAO;AAAS,CAAC;AAE9E,MAAM,UACJ,QACA,UAIA,OAAO,oBAAoB,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,OAAO,SAAS,QAAQ,CAAC;AAE1E,MAAM,WACJ,QACA,UACG,gBAAgB,QAAQ,KAAK,CAAC,CAAC,KAAK,OAAO,SAAS,QAAQ,CAAC;AAElE,MAAM,aAAa,MAAkB,UACnC,KAAK,WAAW,MAAM,UAAU,KAAK,OAAO,MAAM,UAAU,SAAS,MAAM,MAAM;AAEnF,MAAM,UAAU,SAAiB,YAC/B,OAAO,OAAO,MACZ,OAAO,YAAY,KAAK,KAAM,UAAU,IAAK,CAAC,CAAC,GAC/C,OAAO,YAAY,UAAU;CAC3B,MAAM,SAAS,UAAU,OAAO,KAAK;CAErC,OACE,OAAO,SAAS,aAChB,OAAO,QAAQ,UAAU,WACzB,OAAO,QAAQ,UAAU,WACzB,UAAU,OAAO,OAAO,OAAO,MAAM;AAEzC,CAAC,CACH;AAEF,MAAM,QAAQ,OAAO,GAAG,qBAAqB,CAAC,CAAC,WAAW,OAAe;CACvE,MAAM,SAAS,UAAU,OAAO,KAAK;CAErC,IAAI,OAAO,SAAS,WAAW,OAAO,OAAO,SAAS;CAEtD,OAAO,IAAI,WAAW,OAAO,OAAO;AACtC,CAAC;AAED,MAAM,WAAW,OAAO,IAAI,MAAM,OAAO,UAAU;CAAE,SAAS;CAAG,SAAS;AAAO,CAAC,CAAC;AAEnF,MAAM,6BAA6B,OAAO,OAAO;CAC/C,SAAS;CACT,WAAW;CACX,eAAe;CACf,oBAAoB,OAAO,MAAM,iBAAiB,CAAC,CAAC,MAAM,OAAO,YAAY,EAAE,CAAC;AAClF,CAAC;AAED,MAAM,2BAA2B,OAAO,OAAO;CAC7C,SAAS;CACT,WAAW;CACX,eAAe;CACf,YAAY;CACZ,MAAM;CACN,aAAa;CACb,qBAAqB,OAAO,MAAM,iBAAiB,CAAC,CAAC,MAAM,OAAO,YAAY,EAAE,CAAC;AACnF,CAAC;AAED,MAAM,sBAAsB,OAAO,OAAO;CACxC,UAAU;CACV,YAAY;CACZ,UAAU;AACZ,CAAC;AAED,MAAM,oBAAoB,OAAO,OAAO;CACtC,UAAU;CACV,UAAU;AACZ,CAAC;AAED,MAAM,WAAW;CACf,IAAI;CACJ,OAAO;CACP,MAAM,OAAO,QAAQ,YAAY;AACnC;AAEA,MAAM,yBAAyB,OAAO,OAAO;CAC3C,GAAG;CACH,UAAU,OAAO,OAAO;EACtB,gBAAgB,OAAO,GAAG,IAAI;EAC9B,mBAAmB,OAAO,IAAI,KAAK;EACnC,WAAW,OAAO,GAAG,IAAI;EACzB,YAAY,OAAO,YAAY,OAAO,OAAO,iBAAiB,CAAC;CACjE,CAAC;AACH,CAAC;AAED,MAAM,uBAAuB,OAAO,OAAO;CACzC,GAAG;CACH,UAAU,OAAO,OAAO;EAAE,gBAAgB,OAAO,GAAG,IAAI;EAAG,mBAAmB,OAAO,GAAG,KAAK;CAAE,CAAC;AAClG,CAAC;AAED,MAAM,aAAa,OAAO,OAAO;CAC/B,MAAM,OAAO;CACb,WAAW;CACX,QAAQ,OAAO,OAAO,MAAM,OAAO,YAAY,IAAI,CAAC;CACpD,aAAa,OAAO,YAAY,OAAO,OAAO;CAC9C,WAAW,OAAO,YAAY,OAAO,OAAO;AAC9C,CAAC;AAWD,MAAM,WAAW,OAAO,MAAM;CAC5B,OAAO,OAAO,MAAM,OAAO,YAAY,IAAI,CAAC;CAC5C,OAAO,OAAO,MAAM,OAAO,SAAS,CAAC;CACrC,OAAO;CACP,OAAO;CACP,OAAO,WAAW,MAAM,OAAO,YAAY,UAAU,MAAM,UAAU,KAAK,CAAC;AAC7E,CAAC;AAED,MAAM,aAAa,UAA0C;CAC3D,IAAI,UAAU,GAAG,OAAO;CACxB,MAAM,QAAQ,UAAU,QAAQ,CAAC;CAEjC,OAAO,OAAO,MAAM;EAClB;EACA,OAAO,MAAM,KAAK,CAAC,CAAC,MAAM,OAAO,YAAY,EAAE,CAAC;EAChD,OAAO,YACL,OAAO,MAAM,CAAC,OAAO,OAAO,MAAM,OAAO,YAAY,GAAG,CAAC,GAAG,OAAO,GAAG,CAAC,GACvE,KACF,CAAC,CAAC,MAAM,OAAO,YAAY,UAAU,MAAM,QAAQ,EAAE,CAAC;CACxD,CAAC;AACH;AAEA,MAAM,UAAU,OAAO,YACrB,OAAO,MAAM,CAAC,OAAO,OAAO,MAAM,OAAO,YAAY,GAAG,CAAC,GAAG,OAAO,GAAG,CAAC,GACvE,UAAU,CAAC,CACb,CAAC,CAAC,MAAM,OAAO,YAAY,UAAU,MAAM,QAAQ,EAAE,CAAC;AAEtD,MAAM,cAAc,UAAoB;CAGtC,OAAO,QAAQ,OAAO,KAA6C;AACrE;AAEA,MAAM,WAAW,OAAO,GAAG,wBAAwB,CAAC,CAAC,WAAW,OAAmB,OAAgB;CACjG,MAAM,SAAS,OAAO,OAAO,SAAS,KAAK;CAC3C,MAAM,UAAU,OAAO,aAAa,WAAW,MAAM,CAAC;CAEtD,IAAI,CAAC,UAAU,OAAO,OAAO,GAAG,OAAO,OAAO,SAAS;CAEvD,OAAO;AACT,CAAC;AAED,MAAM,aAAa,SAAiB,YAClC,OAAO,WAAW,MAChB,OAAO,YAAY,UAAU,MAAM,UAAU,WAAW,MAAM,UAAU,OAAO,CACjF;AAEF,MAAM,QAAQ,OAAO,GAAG,qBAAqB,CAAC,CAAC,WAAW,UAA2B;CACnF,MAAM,MAAM,SAAS,cAAc,OAAO,SAAS,GAAG;CAEtD,IACE,SAAS,iBAAiB,OAC1B,OAAO,SAAS,mBAChB,OAAO,SAAS,iCAChB,SAAS,mBAAmB,SAAS,gBAErC,OAAO,OAAO,SAAS;AAC3B,CAAC;AAED,MAAM,cAAc,OAAO,GAAG,0BAA0B,CAAC,CAAC,WACxD,OACA,UACA,MACA;CACA,MAAM,SAAS,OAAO,OAAO,YAAY,OAAO,aAAa,qBAAqB,KAAK,CAAC,CAAC;CAEzF,IACE,OAAO,SAAS,QAChB,OAAO,cAAc,SAAS,aAC9B,CAAC,SAAS,QAAQ,QAAQ,SAAS,OAAO,MAAM,KAChD,OAAO,gBAAgB,QACvB,eAAe,QAEf,OAAO,OAAO,SAAS;CAEzB,OAAO;AACT,CAAC;AAED,MAAM,qBAAqB,OAAO,GAAG,iCAAiC,CAAC,CAAC,WACtE,UACA,cACA,SACA;CACA,IACE,SAAS,SAAS,MAClB,SAAS,SAAS,SAClB,QAAQ,SAAS,MAAO,EAAE,MAAM,cAEhC,OAAO,OAAO,SAAS;CACzB,IAAI,SAAS;CAEb,IAAI,cAAc;EAChB,IAAI,SAAS,SAAS,IAAI,OAAO,OAAO,SAAS;EAEjD,MAAM,SAAS,IAAI,SACjB,SAAS,QACT,SAAS,YACT,SAAS,UACX,CAAC,CAAC,UAAU,IAAI,KAAK;EAErB,IAAI,SAAS,KAAK,SAAS,QAAQ,SAAS,SAAS,KAAK,QAAQ,OAAO,OAAO,SAAS;EACzF,SAAS,KAAK;CAChB;CACA,MAAM,SAAS,OAAO,aAAa,uBAAuB,IAAI,WAAW,QAAQ,CAAC,CAAC;CAEnF,IACE,CAAC,OAAO,MAAM,MACb,QAAQ,qBAAqB,cAAc,CAAC,OAAO,MAAM,MACzD,OAAO,MAAM,MAAM,CAAC,OAAO,MAAM,MAClC,OAAO,MAAM,OAAO,gBACpB,OAAO,MAAM,aAAa,SAAS,KAEnC,OAAO,OAAO,SAAS;CACzB,OAAO,OAAO,gBAAgB,OAAO,OAAO;CAC5C,MAAM,SAAuB,CAAC,SAAS,MAAM,GAAG,MAAM,CAAC;CAEvD,IAAI,cAAc;EAChB,MAAM,KAAK,OAAO,OAAO,UAAU,GAAG,IAAI,GAAG,OAAO,YAAY;EAChE,MAAM,MAAM,OAAO,OAAO,UAAU,GAAG,IAAI,GAAG,OAAO,mBAAmB;EAExE,IAAI,CAAC,UAAU,IAAI,SAAS,MAAM,IAAI,MAAM,CAAC,GAAG,OAAO,OAAO,SAAS;EACvE,OAAO,KAAK,GAAG;CACjB;CACA,IAAI,OAAO,MAAM,IAAI;EACnB,MAAM,YAAY,OAAO,OAAO,UAAU,GAAG,KAAK,GAAG,OAAO,oBAAoB;EAEhF,OAAO,SACL,WACA,OAAO,aAAa,QAAQ,YAAqB,IAAI,WAAW,SAAS,CAAC,CAAC,CAC7E;EACA,OAAO,KAAK,SAAS;CACvB,OAAO,IAAI,OAAO,yBAAyB,KAAA,GAAW,OAAO,OAAO,SAAS;CAG7E,IAFe,OAAO,QAAQ,KAAK,UAAU,MAAM,MAAM,QAAQ,CAExD,MAAM,SAAS,QAAQ,OAAO,OAAO,SAAS;CACvD,IAAI,SAAS;CAEb,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,CAAC,UAAU,OAAO,SAAS,MAAM,QAAQ,SAAS,MAAM,MAAM,CAAC,GAAG,OAAO,OAAO,SAAS;EAC7F,UAAU,MAAM;CAClB;CAEA,MAAM,SAAS,IAAI,WACjB,OAAO,iBACL,WAAW,OAAO,OAAO,OAAO,WAAW,IAAI,YAAY,CAAC,CAAC,OAAO,QAAQ,IAAI,CAAC,CACnF,CACF;CAEA,IAAI,CAAC,UAAU,QAAQ,SAAS,MAAM,GAAG,EAAE,CAAC,GAAG,OAAO,OAAO,SAAS;CAEtE,OAAO;AACT,CAAC;AAED,MAAM,WAAW,OAAO,GAAG,yBAAyB,CAAC,CAAC,WACpD,OACA,SACA,UACA;CACA,MAAM,MAAM,OAAO,SACjB,OACA,OAAO,aAAa,0BAA0B,IAAI,WAAW,KAAK,CAAC,CAAC,CACtE;CAEA,MAAM,cAAc,OAAO,OAAO,OAAO,SAAS,CAAC,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;CAEzE,IAAI,CAAC,QAAQ,SAAS,WAAW,KAAM,aAAa,KAAA,KAAa,gBAAgB,UAC/E,OAAO,OAAO,SAAS;CACzB,IAAI;CACJ,IAAI;CAEJ,IAAI,gBAAgB,IAAI;EACtB,IACE,IAAI,SAAS,KACb,CAAC;GAAC;GAAG;GAAG;GAAI;GAAI;EAAE,CAAC,CAAC,OAAO,QAAQ,IAAI,IAAI,GAAG,CAAC,KAC/C,IAAI,IAAI,CAAC,MAAM,KACf,IAAI,IAAI,EAAE,MAAM,GAEhB,OAAO,OAAO,SAAS;EACzB,MAAM,IAAI,OAAO,OAAO,UAAU,IAAI,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC;EACtD,MAAM,IAAI,OAAO,OAAO,UAAU,IAAI,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC;EAEtD,MAAM;GACJ,KAAK;GACL,KAAK;GACL,GAAG,UAAU,OAAO,CAAC;GACrB,GAAG,UAAU,OAAO,CAAC;GACrB,KAAK;EACP;EACA,YAAY;GAAE,MAAM;GAAS,YAAY;EAAQ;CACnD,OAAO;EACL,IAAI,IAAI,SAAS,KAAK,CAAC;GAAC;GAAG;GAAG;GAAI;EAAE,CAAC,CAAC,OAAO,QAAQ,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,GACnF,OAAO,OAAO,SAAS;EACzB,MAAM,IAAI,OAAO,OAAO,UAAU,KAAK,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;EACxD,MAAM,IAAI,OAAO,OAAO,UAAU,GAAG,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;EACpD,MAAM,WAAW,EAAE,QAAQ,OAAO,SAAS,QAAQ,MAAM,MAAM,CAAC;EAEhE,IACE,EAAE,KAAM,QACP,EAAE,EAAE,SAAS,KAAM,OAAO,KAC3B,EAAE,OAAO,KACT,WAAW,KACX,WAAW,MAAM,GAEjB,OAAO,OAAO,SAAS;EACzB,MAAM;GACJ,KAAK;GACL,KAAK;GACL,GAAG,UAAU,OAAO,CAAC;GACrB,GAAG,UAAU,OAAO,CAAC;GACrB,KAAK;EACP;EACA,YAAY;GAAE,MAAM;GAAqB,MAAM;EAAU;CAC3D;CACA,OAAO,iBACL,WAAW,OAAO,OAAO,UAAU,OAAO,KAAK,WAAW,OAAO,CAAC,QAAQ,CAAC,CAC7E;CAEA,OAAO;AACT,CAAC;AAED,MAAa,oCAAoC,OAAO,GAAG,mCAAmC,CAAC,CAC7F,WACE,SACuD;CACvD,MAAM,SAAS,OAAO,8BAA8B,OAAO;CAE3D,MAAM,wBAAwB,OAAO,GAAG,qDAAqD,CAAC,CAC5F,WAAW,OAAuC;EAChD,MAAM,QAAQ,OAAO,QAAQ,4BAA4B,KAAK;EAC9D,MAAM,UAAU,OAAO,OAAO,MAAM,OAAO;EAC3C,MAAM,YAAY,OAAO,MAAM,MAAM,SAAS;EAE9C,MAAM,SAAS,OAAO,iBACpB,8BAA8B;GAC5B,MAAM,QAAQ;GACd;GACA,SAAS,MAAM;GACf,kBAAkB,QAAQ;GAC1B,kBAAkB,MAAM,mBAAmB,KAAK,WAAW,EAAE,GAAG,MAAM,EAAE;EAC1E,CAAC,CACH;EAEA,MAAM,QAAQ,OAAO,OAAO,8BAA8B;GACxD,WAAW,OAAO;GAClB,MAAM,OAAO;GACb,SAAS,OAAO;GAChB,kBAAkB,OAAO;GACzB,kBAAkB,OAAO,oBAAoB,CAAC;EAChD,CAAC;EAED,IACE,EAAE,OAAO,YAAY,8BAA8B,OAAO;GACxD,WAAW,MAAM;GACjB,MAAM,QAAQ;GACd,SAAS,MAAM;GACf,kBAAkB,QAAQ;GAC1B,kBAAkB,MAAM;EAC1B,CAAC,IAED,OAAO,OAAO,YAAY;EAE5B,OAAO,OAAO,QAAQ,8BAA8B,KAAK;CAC3D,GACA,UACF;CAEA,MAAM,sBAAsB,OAAO,GAAG,mDAAmD,CAAC,CACxF,WAAW,OAAqC;EAC9C,MAAM,QAAQ,OAAO,QAAQ,0BAA0B,KAAK;EAC5D,MAAM,UAAU,OAAO,OAAO,MAAM,OAAO;EAE3C,MAAM,YAAY,OAAO,MAAM,MAAM,SAAS,GAC5C,SAAS,OAAO,MAAM,MAAM,UAAU;EAExC,MAAM,SAAS,OAAO,iBACpB,4BAA4B;GAC1B,QAAQ,QAAQ;GAChB,MAAM,QAAQ;GACd,UAAU,MAAM;GAChB,iBAAiB,MAAM;GACvB;GACA;GACA,SAAS,MAAM;GACf,iBAAiB;GACjB,uBAAuB,CAAC,GAAG,QAAQ,UAAU;GAC7C,wBAAwB;IACtB,aAAa,QAAQ;IACrB,kBAAkB,QAAQ;GAC5B;GACA,oBAAoB,MAAM,oBAAoB,KAAK,WAAW,EAAE,GAAG,MAAM,EAAE;EAC7E,CAAC,CACH;EAEA,MAAM,QAAQ,OAAO,OAAO,4BAA4B;GACtD,WAAW,OAAO;GAClB,IAAI,OAAO;GACX,MAAM,OAAO;GACb,kBAAkB,OAAO;GACzB,SAAS,OAAO;GAChB,aAAa,OAAO;GACpB,wBAAwB,OAAO;GAC/B,oBAAoB,OAAO,sBAAsB,CAAC;EACpD,CAAC;EAED,MAAM,WAAW;GACf,WAAW,MAAM;GACjB,IAAI;IAAE,IAAI,QAAQ;IAAM,MAAM,QAAQ;GAAO;GAC7C,MAAM;IAAE,IAAI,MAAM;IAAY,MAAM,MAAM;IAAM,aAAa,MAAM;GAAY;GAC/E,kBAAkB,QAAQ,WAAW,KAAK,SAAS;IAAE,MAAM;IAAc;GAAI,EAAE;GAC/E,SAAS,MAAM;GACf,aAAa;GACb,wBAAwB;IACtB,aAAa,QAAQ;IACrB,kBAAkB,QAAQ;GAC5B;GACA,oBAAoB,MAAM;EAC5B;EAEA,IACE,EAAE,OAAO,YACP,4BACA,OACA,OAAO,OAAO,4BAA4B,QAAQ,CACpD,IAEA,OAAO,OAAO,YAAY;EAE5B,OAAO,OAAO,QAAQ,4BAA4B,KAAK;CACzD,GACA,UACF;CAEA,MAAM,qBAAqB,OAAO,GAAG,kDAAkD,CAAC,CACtF,WAAW,OAAoC;EAC7C,MAAM,QAAQ,OAAO,QAAQ,mBAAmB,KAAK,GACnD,WAAW,MAAM;EAEnB,MAAM,UAAU,OAAO,OAAO,SAAS,OAAO;EAE9C,KACG,SAAS,YAAY,kBAAkB,SAAS,QAAQ,SAAS,oBACjE,SAAS,YAAY,gBAAgB,SAAS,QAAQ,SAAS,eAEhE,OAAO,OAAO,SAAS;EACzB,OAAO,MAAM,QAAQ;EAErB,MAAM,OAAO,OAAO,OAClB,OAAO,eAAe,oBAAoB,GAC1C,SAAS,MAAM,MAAM,QAAQ,CAC/B;EAEA,IAAI,KAAK,OAAO,KAAK,OAAO,OAAO,OAAO,SAAS;EAEnD,MAAM,SAAS,OAAO,YACpB,KAAK,SAAS,gBACd,UACA,iBACF;EAEA,MAAM,mBAAmB,OAAO,MAAM,KAAK,SAAS,iBAAiB;EAErE,MAAM,cAAc,OAAO,SACzB,kBACA,OAAO,aAAa,wBAAwB,IAAI,WAAW,gBAAgB,CAAC,CAAC,CAC/E;EAEA,IACE,YAAY,SAAS,KACrB,YAAY,IAAI,KAAK,MAAM,UAC3B,CAAC,YAAY,IAAI,SAAS,KAC1B,CAAC,YAAY,IAAI,UAAU,GAE3B,OAAO,OAAO,SAAS;EAGzB,KAAI,OAFqB,OAAO,SAAS,YAAY,IAAI,SAAS,CAAC,EAAA,CAErD,SAAS,GAAG,OAAO,OAAO,SAAS;EACjD,MAAM,qBAAqB,OAAO,OAAO,UAAU,IAAI,KAAK,GAAG,YAAY,IAAI,UAAU,CAAC;EAC1F,MAAM,OAAO,OAAO,mBAAmB,oBAAoB,MAAM,OAAO;EACxE,MAAM,KAAK,OAAO,OAAO,UAAU,GAAG,IAAI,GAAG,KAAK,YAAY;EAC9D,MAAM,MAAM,OAAO,OAAO,UAAU,GAAG,IAAI,GAAG,KAAK,mBAAmB;EAEtE,IAAI,UAAU,OAAO,EAAE,MAAM,KAAK,IAAI,OAAO,OAAO,SAAS;EAC7D,MAAM,YAAY,OAAO,SAAS,KAAK,QAAQ,UAAU;EAEzD,MAAM,SAAS,OAAO,iBACpB,2BAA2B;GACzB,UAAU;IAAE,GAAG;IAAM,wBAAwB,CAAC;GAAE;GAChD,mBAAmB,SAAS;GAC5B,gBAAgB,CAAC,GAAG,QAAQ,OAAO;GACnC,cAAc,QAAQ;GACtB,cAAc;GACd,qBAAqB;GACrB,yBAAyB,QAAQ,qBAAqB;GACtD,uBAAuB,CAAC,GAAG,QAAQ,UAAU;EAC/C,CAAC,CACH;EAEA,IAAI,CAAC,OAAO,YAAY,OAAO,qBAAqB,KAAA,GAAW,OAAO,OAAO,SAAS;EACtF,MAAM,OAAO,OAAO;EAEpB,IACE,KAAK,QAAQ,UACb,KAAK,WAAW,OAAO,UACvB,KAAK,SAAS,QAAQ,QACtB,KAAK,WAAW,OAAO,KAAK,MAC5B,CAAC,UAAU,KAAK,WAAW,WAAW,GAAG,KACzC,KAAK,WAAW,YAAY,KAAK,WACjC,KAAK,iBAAiB,KAAK,MAAM,MAChC,KAAK,yBAAyB,kBAAmB,KAAK,MAAM,MAC7D,KAAK,uBAAuB,KAAK,MAAM,IAEvC,OAAO,OAAO,SAAS;EACzB,OAAO,MAAM,QAAQ;EAErB,OAAO,OAAO,QACZ,6BACA,OAAO,OAAO,6BAA6B;GACzC,sBAAsB,KAAK,WAAW;GACtC,WAAW,UAAU,OAAO,KAAK,WAAW,SAAS;GACrD;GACA,SAAS,KAAK,WAAW;GACzB,cAAc,KAAK;GACnB,gBAAgB,KAAK,yBAAyB;GAC9C,aAAa,KAAK;EACpB,CAAC,CACH;CACF,GACA,UACF;CAEA,MAAM,uBAAuB,OAAO,GAAG,oDAAoD,CAAC,CAC1F,WAAW,OAAsC;EAC/C,MAAM,QAAQ,OAAO,QAAQ,qBAAqB,KAAK,GACrD,WAAW,MAAM,UACjB,aAAa,MAAM;EAErB,MAAM,UAAU,OAAO,OAAO,SAAS,OAAO,GAC5C,WAAW,OAAO,OAAO,WAAW,OAAO;EAS7C,IACE,SAAS,YAAY,kBACrB,SAAS,YAAY,gBACrB;GATA,WAAW;GACX,SAAS;GACT,WAAW;GACX,QAAQ;EAMD,EAAE,SAAS,aAAa,SAAS,QAAQ,QAChD,CAAC,WAAW,UACZ,WAAW,SAAS,QAAQ,QAC5B,SAAS,SAAS,QAAQ,QAC1B,CAAC,SAAS,WAAW,SAAS,WAAW,SAAS,KAClD,CAAC,QAAQ,WAAW,SAAS,WAAW,SAAS,GAEjD,OAAO,OAAO,SAAS;EACzB,OAAO,MAAM,QAAQ;EAErB,MAAM,OAAO,OAAO,OAClB,OAAO,eAAe,sBAAsB,GAC5C,SAAS,MAAM,MAAM,QAAQ,CAC/B;EAEA,MAAM,EAAE,YAAY,eAAe,GAAG,sBAAsB,KAAK;EACjE,MAAM,aAAa,iBAAiB,KAAA;EAEpC,IACE,KAAK,OAAO,KAAK,SACjB,KAAK,OAAO,WAAW,wBACtB,eAAe,KAAA,KAAa,eAAe,WAAW,cACtD,SAAS,QAAQ,SAAS,YAAY,eAAe,KAAA,KACrD,SAAS,mBAAmB,SAAS,KACpC,CAAC,SAAS,mBAAmB,MAAM,UAAU,MAAM,OAAO,KAAK,EAAE,GAEnE,OAAO,OAAO,SAAS;EACzB,MAAM,SAAS,OAAO,YAAY,KAAK,SAAS,gBAAgB,UAAU,cAAc;EAExF,MAAM,OAAO,OAAO,mBAClB,OAAO,MAAM,KAAK,SAAS,iBAAiB,GAC5C,OACA,OACF;EAEA,IACE,KAAK,MAAM,OAAO,WAAW,kBAC5B,CAAC,WAAW,mBACV,WAAW,UAAU,KAAK,KAAK,UAAU,MAC1C,KAAK,WAAW,WAAW,SAE7B,OAAO,OAAO,SAAS;EACzB,MAAM,YAAY,OAAO,MAAM,WAAW,SAAS;EAEnD,OAAO,SAAS,WAAW,QAAQ,YAAY,WAAW,SAAS;EAEnE,MAAM,SAAS,OAAO,iBACpB,6BAA6B;GAC3B,UAAU;IACR,GAAG;IACH,UAAU;KACR,GAAG;KACH,GAAI,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW;IACnD;IACA,wBAAwB,CAAC;GAC3B;GACA,mBAAmB,SAAS;GAC5B,gBAAgB,CAAC,GAAG,QAAQ,OAAO;GACnC,cAAc,QAAQ;GACtB,cAAc;GACd,yBAAyB,QAAQ,qBAAqB;GACtD,YAAY;IACV,IAAI,WAAW;IACf;IACA,SAAS,WAAW,iBAAiB,IAAI,WAAW;GACtD;EACF,CAAC,CACH;EAEA,IAAI,CAAC,OAAO,UAAU,OAAO,OAAO,SAAS;EAC7C,MAAM,OAAO,OAAO;EAEpB,IACE,KAAK,iBAAiB,KAAK,MAC3B,KAAK,WAAW,OAAO,UACvB,KAAK,SAAS,QAAQ,QACtB,KAAK,eAAe,KAAK,WACzB,KAAK,iBAAiB,KAAK,MAAM,MAChC,KAAK,yBAAyB,kBAAmB,WAAW,kBAC7D,KAAK,uBAAuB,KAAK,MAAM,IAEvC,OAAO,OAAO,SAAS;EACzB,OAAO,MAAM,QAAQ;EAErB,OAAO,OAAO,QACZ,0BACA,OAAO,OAAO,0BAA0B;GACtC,sBAAsB,KAAK;GAC3B,GAAI,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW;GACjD,SAAS,KAAK;GACd,cAAc,KAAK;GACnB,gBAAgB,KAAK,yBAAyB;GAC9C,aAAa,KAAK;EACpB,CAAC,CACH;CACF,GACA,UACF;CAEA,OAAO,gBAAgB,GAAG;EACxB;EACA;EACA;EACA;CACF,CAAC;AACH,CACF;;AAGA,MAAa,qCAAqC,MAAM,OACtD,iBACA,OAAO,QAAQ,eAAe,iCAAiC,CACjE"}
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@yielded/auth-simplewebauthn","version":"0.1.0-beta.16","dependencies":{"@yielded/auth":"0.1.0-beta.16","tldts":"7.4.11"},"devDependencies":{"@simplewebauthn/browser":"14.0.0","@simplewebauthn/server":"14.0.1","effect":"4.0.0","typescript":"7.0.2","vite-plus":"0.3.3"},"peerDependencies":{"@simplewebauthn/browser":">=14.0.0 <15","@simplewebauthn/server":">=14.0.1 <15","effect":"^4.0.0"},"exports":{"./Browser":{"types":"./dist/Browser.d.mts","default":"./dist/Browser.mjs"},"./Server":{"types":"./dist/Server.d.mts","default":"./dist/Server.mjs"}},"description":"SimpleWebAuthn browser ceremonies and server verification for Yielded Auth.","homepage":"https://yielded.dev/auth/","bugs":{"url":"https://github.com/yielded-dev/auth/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/yielded-dev/auth.git","directory":"packages/auth-simplewebauthn"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests"},"peerDependenciesMeta":{"@simplewebauthn/browser":{"optional":true},"@simplewebauthn/server":{"optional":true}}}
1
+ {"name":"@yielded/auth-simplewebauthn","version":"0.1.0-beta.18","dependencies":{"@yielded/auth":"0.1.0-beta.18","tldts":"7.4.11"},"devDependencies":{"@simplewebauthn/browser":"14.0.0","@simplewebauthn/server":"14.0.1","effect":"4.0.0","typescript":"7.0.2","vite-plus":"0.3.3"},"peerDependencies":{"@simplewebauthn/browser":">=14.0.0 <15","@simplewebauthn/server":">=14.0.1 <15","effect":"^4.0.0"},"exports":{"./Browser":{"types":"./dist/Browser.d.mts","default":"./dist/Browser.mjs"},"./Server":{"types":"./dist/Server.d.mts","default":"./dist/Server.mjs"}},"description":"SimpleWebAuthn browser ceremonies and server verification for Yielded Auth.","homepage":"https://yielded.dev/auth/","bugs":{"url":"https://github.com/yielded-dev/auth/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/yielded-dev/auth.git","directory":"packages/auth-simplewebauthn"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests"},"peerDependenciesMeta":{"@simplewebauthn/browser":{"optional":true},"@simplewebauthn/server":{"optional":true}}}
@@ -638,7 +638,8 @@ export const makeSimpleWebAuthnPasskeyProtocol = Effect.fn("makeSimpleWebAuthnPa
638
638
  Redacted.value(fixed.response),
639
639
  );
640
640
 
641
- const userHandle = wire.response.userHandle ?? undefined;
641
+ const { userHandle: rawUserHandle, ...assertionResponse } = wire.response;
642
+ const userHandle = rawUserHandle ?? undefined;
642
643
 
643
644
  if (
644
645
  wire.id !== wire.rawId ||
@@ -672,7 +673,10 @@ export const makeSimpleWebAuthnPasskeyProtocol = Effect.fn("makeSimpleWebAuthnPa
672
673
  verifyAuthenticationResponse({
673
674
  response: {
674
675
  ...wire,
675
- response: { ...wire.response, userHandle },
676
+ response: {
677
+ ...assertionResponse,
678
+ ...(userHandle === undefined ? {} : { userHandle }),
679
+ },
676
680
  clientExtensionResults: {},
677
681
  },
678
682
  expectedChallenge: ceremony.challenge,