@yielded/auth-simplewebauthn 0.1.0-beta.0
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/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/Browser.d.mts +4 -0
- package/dist/Browser.mjs +4 -0
- package/dist/Server.d.mts +3 -0
- package/dist/Server.mjs +3 -0
- package/dist/internal/browser/PasskeyBrowser.d.mts +17 -0
- package/dist/internal/browser/PasskeyBrowser.mjs +10 -0
- package/dist/internal/browser/PasskeyBrowser.mjs.map +1 -0
- package/dist/internal/browser/models.d.mts +37 -0
- package/dist/internal/browser/models.mjs +41 -0
- package/dist/internal/browser/models.mjs.map +1 -0
- package/dist/internal/browser/simplewebauthn.d.mts +16 -0
- package/dist/internal/browser/simplewebauthn.mjs +410 -0
- package/dist/internal/browser/simplewebauthn.mjs.map +1 -0
- package/dist/internal/server/configuration.mjs +43 -0
- package/dist/internal/server/configuration.mjs.map +1 -0
- package/dist/internal/server/models.d.mts +20 -0
- package/dist/internal/server/models.mjs +8 -0
- package/dist/internal/server/models.mjs.map +1 -0
- package/dist/internal/server/protocol.d.mts +59 -0
- package/dist/internal/server/protocol.mjs +400 -0
- package/dist/internal/server/protocol.mjs.map +1 -0
- package/package.json +1 -0
- package/src/Browser.ts +19 -0
- package/src/Server.ts +6 -0
- package/src/internal/browser/PasskeyBrowser.ts +29 -0
- package/src/internal/browser/models.ts +66 -0
- package/src/internal/browser/simplewebauthn.ts +621 -0
- package/src/internal/server/configuration.ts +101 -0
- package/src/internal/server/models.ts +8 -0
- package/src/internal/server/protocol.ts +733 -0
|
@@ -0,0 +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, Encoding, Layer, Redacted, Schema } from \"effect\";\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 = Encoding.decodeBase64Url(value);\n\n return (\n result._tag === \"Success\" &&\n result.success.length >= minimum &&\n result.success.length <= maximum &&\n Encoding.encodeBase64Url(result.success) === value\n );\n }),\n );\n\nconst bytes = Effect.fn(\"simpleWebAuthnBytes\")(function* (value: string) {\n const result = Encoding.decodeBase64Url(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: Encoding.encodeBase64Url(x),\n y: Encoding.encodeBase64Url(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: Encoding.encodeBase64Url(n),\n e: Encoding.encodeBase64Url(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 (Encoding.encodeBase64Url(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: Encoding.encodeBase64Url(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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"}
|
package/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"name":"@yielded/auth-simplewebauthn","version":"0.1.0-beta.0","dependencies":{"@yielded/auth":"0.1.0-beta.10","tldts":"7.4.11"},"devDependencies":{"@simplewebauthn/browser":"14.0.0","@simplewebauthn/server":"14.0.1","effect":"4.0.0-rc.117","typescript":"7.0.2","vite-plus":"1.0.0-rc.0"},"peerDependencies":{"@simplewebauthn/browser":">=14.0.0 <15","@simplewebauthn/server":">=14.0.1 <15","effect":"^4.0.0-rc.117"},"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}}}
|
package/src/Browser.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { PasskeyBrowser } from "./internal/browser/PasskeyBrowser";
|
|
2
|
+
|
|
3
|
+
export {
|
|
4
|
+
PasskeyBrowserAuthentication,
|
|
5
|
+
PasskeyBrowserBusy,
|
|
6
|
+
PasskeyBrowserCapabilities,
|
|
7
|
+
PasskeyBrowserCapability,
|
|
8
|
+
PasskeyBrowserFailure,
|
|
9
|
+
PasskeyBrowserInputRejected,
|
|
10
|
+
PasskeyBrowserNotCompleted,
|
|
11
|
+
PasskeyBrowserRegistration,
|
|
12
|
+
PasskeyBrowserUnavailable,
|
|
13
|
+
PasskeyBrowserUnsupported,
|
|
14
|
+
} from "./internal/browser/models";
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
layerSimpleWebAuthnPasskeyBrowser as layer,
|
|
18
|
+
makeSimpleWebAuthnPasskeyBrowser as make,
|
|
19
|
+
} from "./internal/browser/simplewebauthn";
|
package/src/Server.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type PasskeyAuthenticationStarted,
|
|
3
|
+
type PasskeyRegistrationStarted,
|
|
4
|
+
} from "@yielded/auth/Passkey";
|
|
5
|
+
import { Context, type Effect } from "effect";
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
PasskeyBrowserAuthentication,
|
|
9
|
+
PasskeyBrowserCapabilities,
|
|
10
|
+
PasskeyBrowserFailure,
|
|
11
|
+
PasskeyBrowserRegistration,
|
|
12
|
+
PasskeyBrowserUnavailable,
|
|
13
|
+
} from "./models";
|
|
14
|
+
|
|
15
|
+
/** Client-local ceremony capability. The caller owns Begin/Complete RPCs and
|
|
16
|
+
* request binding. Interrupt its Effect to request cancellation; no global cancel. */
|
|
17
|
+
export class PasskeyBrowser extends Context.Service<
|
|
18
|
+
PasskeyBrowser,
|
|
19
|
+
{
|
|
20
|
+
readonly capabilities: Effect.Effect<PasskeyBrowserCapabilities, PasskeyBrowserUnavailable>;
|
|
21
|
+
readonly register: (
|
|
22
|
+
started: typeof PasskeyRegistrationStarted.Type,
|
|
23
|
+
) => Effect.Effect<PasskeyBrowserRegistration, PasskeyBrowserFailure>;
|
|
24
|
+
readonly authenticate: (input: {
|
|
25
|
+
readonly started: typeof PasskeyAuthenticationStarted.Type;
|
|
26
|
+
readonly mediation: "required" | "conditional";
|
|
27
|
+
}) => Effect.Effect<PasskeyBrowserAuthentication, PasskeyBrowserFailure>;
|
|
28
|
+
}
|
|
29
|
+
>()("effect-auth/PasskeyBrowser") {}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { RequestBindingFlowId } from "@yielded/auth/Operations";
|
|
2
|
+
import { PasskeyAssertion, PasskeyAttestation } from "@yielded/auth/Passkey";
|
|
3
|
+
import { Schema } from "effect";
|
|
4
|
+
|
|
5
|
+
export const PasskeyBrowserCapability = Schema.Literals(["supported", "unsupported", "unknown"]);
|
|
6
|
+
export type PasskeyBrowserCapability = typeof PasskeyBrowserCapability.Type;
|
|
7
|
+
|
|
8
|
+
export const PasskeyBrowserCapabilities = Schema.Struct({
|
|
9
|
+
secureContext: Schema.Boolean,
|
|
10
|
+
webAuthn: Schema.Boolean,
|
|
11
|
+
conditionalGet: PasskeyBrowserCapability,
|
|
12
|
+
userVerifyingPlatformAuthenticator: PasskeyBrowserCapability,
|
|
13
|
+
hybridTransport: PasskeyBrowserCapability,
|
|
14
|
+
passkeyPlatformAuthenticator: PasskeyBrowserCapability,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export type PasskeyBrowserCapabilities = typeof PasskeyBrowserCapabilities.Type;
|
|
18
|
+
|
|
19
|
+
export const PasskeyBrowserRegistration = Schema.Struct({
|
|
20
|
+
flowId: RequestBindingFlowId,
|
|
21
|
+
response: PasskeyAttestation,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export type PasskeyBrowserRegistration = typeof PasskeyBrowserRegistration.Type;
|
|
25
|
+
|
|
26
|
+
export const PasskeyBrowserAuthentication = Schema.Struct({
|
|
27
|
+
flowId: RequestBindingFlowId,
|
|
28
|
+
response: PasskeyAssertion,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export type PasskeyBrowserAuthentication = typeof PasskeyBrowserAuthentication.Type;
|
|
32
|
+
|
|
33
|
+
export class PasskeyBrowserInputRejected extends Schema.TaggedError<PasskeyBrowserInputRejected>()(
|
|
34
|
+
"PasskeyBrowserInputRejected",
|
|
35
|
+
{},
|
|
36
|
+
) {}
|
|
37
|
+
|
|
38
|
+
export class PasskeyBrowserUnsupported extends Schema.TaggedError<PasskeyBrowserUnsupported>()(
|
|
39
|
+
"PasskeyBrowserUnsupported",
|
|
40
|
+
{},
|
|
41
|
+
) {}
|
|
42
|
+
|
|
43
|
+
export class PasskeyBrowserBusy extends Schema.TaggedError<PasskeyBrowserBusy>()(
|
|
44
|
+
"PasskeyBrowserBusy",
|
|
45
|
+
{},
|
|
46
|
+
) {}
|
|
47
|
+
|
|
48
|
+
export class PasskeyBrowserNotCompleted extends Schema.TaggedError<PasskeyBrowserNotCompleted>()(
|
|
49
|
+
"PasskeyBrowserNotCompleted",
|
|
50
|
+
{},
|
|
51
|
+
) {}
|
|
52
|
+
|
|
53
|
+
export class PasskeyBrowserUnavailable extends Schema.TaggedError<PasskeyBrowserUnavailable>()(
|
|
54
|
+
"PasskeyBrowserUnavailable",
|
|
55
|
+
{},
|
|
56
|
+
) {}
|
|
57
|
+
|
|
58
|
+
export const PasskeyBrowserFailure = Schema.Union([
|
|
59
|
+
PasskeyBrowserInputRejected,
|
|
60
|
+
PasskeyBrowserUnsupported,
|
|
61
|
+
PasskeyBrowserBusy,
|
|
62
|
+
PasskeyBrowserNotCompleted,
|
|
63
|
+
PasskeyBrowserUnavailable,
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
export type PasskeyBrowserFailure = typeof PasskeyBrowserFailure.Type;
|