{
  "openapi": "3.1.1",
  "info": {
    "title": "Passkey & WebAuthn Tester API",
    "version": "1.0.0",
    "summary": "Test passkeys in your browser and decode WebAuthn responses: flags, AAGUID, signatures.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://passkeywebauthntester.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Test passkeys in your browser and decode WebAuthn responses: flags, AAGUID, signatures.",
        "description": "Checks which passkey features your browser offers, runs a real passkey registration and sign-in against this site, and decodes the result: authenticator flags (user present/verified, backup), AAGUID, key algorithm and transports. Paste clientDataJSON, attestationObject or authenticatorData to decode and verify them on the server.\n\nMethodology:\n- In the browser (JavaScript on): feature detection of PublicKeyCredential, isUserVerifyingPlatformAuthenticatorAvailable(), isConditionalMediationAvailable() and getClientCapabilities(); then navigator.credentials.create() and get() with this site as relying party (rp.id = the current host) and random challenges generated in the browser. Nothing is sent to or stored on the server; the browser verifies the sign-in signature with WebCrypto.\n- clientDataJSON is decoded and checked: type (webauthn.create / webauthn.get), challenge, origin and crossOrigin. The RP ID hash in the authenticator data is compared with SHA-256 of the expected RP ID (or of the origin host).\n- Authenticator data (WebAuthn §6.1): RP ID hash, flags UP/UV/BE/BS/AT/ED, signature counter, and, at registration, the AAGUID, credential ID and COSE public key (decoded with a strict CBOR decoder). Well-known AAGUIDs are named from a small bundled list.\n- Attestation: \"none\" carries no statement. \"packed\" self-attestation (no certificate) is verified with the credential key; \"packed\" with an x5c certificate is verified with the certificate key, but the certificate chain is NOT validated against FIDO Metadata Service roots, so it proves nothing about the authenticator model. Other formats (tpm, android-key, apple, fido-u2f, …) are decoded but not verified.\n- Sign-in: the signature over authenticatorData ‖ SHA-256(clientDataJSON) is verified when you also paste the credential public key (COSE, base64url).\n\nThe browser test creates a real passkey for this site on your device or password manager; delete it there afterwards (\"usefulweb.site passkey test\"). This tool does not validate attestation certificate chains.",
        "tags": [
          "security"
        ],
        "x-mcp-tool": "passkey_webauthn_tester",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasskeyWebauthnTesterInput"
              },
              "examples": {
                "example1": {
                  "summary": "Registration with packed self-attestation (synthetic software key)",
                  "value": {
                    "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiZTR0TnZzM0NtWk1SWlpqWVlwZjBSUFlGVjhETUJ6Ym0tTmRncXpuNktYVSIsIm9yaWdpbiI6Imh0dHBzOi8vdXNlZnVsd2ViLnNpdGUiLCJjcm9zc09yaWdpbiI6ZmFsc2V9",
                    "attestationObject": "o2NmbXRmcGFja2VkZ2F0dFN0bXSiY2FsZyZjc2lnWEgwRgIhAMY6wBkBpgg_WmvsahWqQpBuowRNNK9tLL6JjpdeWSFdAiEAye9k55Dyc3DyQQbcPVymc9KVP2ZvwaMcJjzzkIQ7CINoYXV0aERhdGFYlOx_npoPyQloSAHCywQcKoGnucq5KZN6JMYsOWZ9pvo0XQAAAAAAAAAAAAAAAAAAAAAAAAAAABC5eSMrhmCORJPJXUoBgVhOpQECAyYgASFYIObX00WVuw2Lu-D-Hln9Y2VEHPDKJQ4oXDXweSHYAgjjIlggyHkfre47j_wYetb2RK4y5fmMS0F-tNhrrrGPBjexWKg",
                    "expectedChallenge": "e4tNvs3CmZMRZZjYYpf0RPYFV8DMBzbm-Ndgqzn6KXU",
                    "expectedOrigin": "https://usefulweb.site",
                    "expectedRpId": "usefulweb.site"
                  }
                },
                "example2": {
                  "summary": "Sign-in (assertion) with signature check",
                  "value": {
                    "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZmg4RC1DV2k0V2RqeEJsUzAwSEg5NVNCd0dYeXM4LWN0UDVfV1AyOTE5ZyIsIm9yaWdpbiI6Imh0dHBzOi8vdXNlZnVsd2ViLnNpdGUiLCJjcm9zc09yaWdpbiI6ZmFsc2V9",
                    "authenticatorData": "7H-emg_JCWhIAcLLBBwqgae5yrkpk3okxiw5Zn2m-jQdAAAAAA",
                    "signature": "MEUCIE1YxT6aNlpXBvrL_b-bQrAYIcoVRt7zxR-ppbCEaBHNAiEAoxx0AH7AwSXhWhlobPkKmOtcnaQ8l2bbKaRAcicCycA",
                    "publicKey": "pQECAyYgASFYIObX00WVuw2Lu-D-Hln9Y2VEHPDKJQ4oXDXweSHYAgjjIlggyHkfre47j_wYetb2RK4y5fmMS0F-tNhrrrGPBjexWKg",
                    "expectedChallenge": "fh8D-CWi4WdjxBlS00HH95SBwGXys8-ctP5_WP2919g",
                    "expectedOrigin": "https://usefulweb.site"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PasskeyWebauthnTesterResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "PasskeyWebauthnTesterInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "clientDataJSON": {
            "title": "clientDataJSON (base64url)",
            "type": "string",
            "maxLength": 20000
          },
          "attestationObject": {
            "title": "attestationObject (base64url, registration)",
            "type": "string",
            "maxLength": 100000
          },
          "authenticatorData": {
            "title": "authenticatorData (base64url, sign-in)",
            "description": "From navigator.credentials.get(). Ignored when an attestationObject is given.",
            "type": "string",
            "maxLength": 20000
          },
          "signature": {
            "title": "signature (base64url, sign-in)",
            "type": "string",
            "maxLength": 4000
          },
          "publicKey": {
            "title": "Credential public key (COSE, base64url, to verify a sign-in signature)",
            "type": "string",
            "maxLength": 4000
          },
          "expectedChallenge": {
            "title": "Expected challenge (base64url, optional)",
            "type": "string",
            "maxLength": 1000
          },
          "expectedOrigin": {
            "title": "Expected origin (optional)",
            "type": "string",
            "maxLength": 300
          },
          "expectedRpId": {
            "title": "Expected RP ID (optional)",
            "type": "string",
            "maxLength": 253
          }
        },
        "required": []
      },
      "PasskeyWebauthnTesterResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "ceremony",
              "clientData",
              "authenticatorData",
              "attestation",
              "signatureValid",
              "checks"
            ],
            "properties": {
              "ceremony": {
                "type": "string",
                "enum": [
                  "registration",
                  "authentication",
                  "client-data-only"
                ]
              },
              "clientData": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": true
              },
              "authenticatorData": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": true
              },
              "attestation": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": true
              },
              "signatureValid": {
                "type": [
                  "boolean",
                  "null"
                ],
                "description": "Attestation signature (registration) or assertion signature (sign-in); null if not checkable."
              },
              "checks": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "check",
                    "status",
                    "detail"
                  ],
                  "properties": {
                    "check": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pass",
                        "fail",
                        "info"
                      ]
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}