{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://docs.qauth.dev/interaction/v1-rc.0/steps/webauthn_get.json",
  "title": "urn:qauth:ia:webauthn_get:v1-rc.0",
  "description": "Passkey sign-in: the WebAuthn Level 3 request options as JSON, for `PublicKeyCredential.parseRequestOptionsFromJSON()`. Discoverable credentials only: the options never carry `allowCredentials`, so the step read reveals no account’s passkeys (ADR-017 Decision 4, ADR-019 Decision 6). The engine checks that the passkey belongs to the transaction’s account. The RP ID is the realm’s host (ADR-019 Decision 2). Needs JavaScript.",
  "x-qauth-transports": [
    "interaction",
    "fipa"
  ],
  "type": "object",
  "properties": {
    "type": {
      "const": "urn:qauth:ia:webauthn_get:v1-rc.0",
      "description": "The step name."
    },
    "params": {
      "$ref": "#/$defs/params"
    },
    "answer": {
      "$ref": "#/$defs/answer"
    },
    "personal": {
      "$ref": "#/$defs/personal"
    },
    "error": {
      "$ref": "#/$defs/error"
    },
    "amr": {
      "$ref": "#/$defs/amr"
    }
  },
  "required": [
    "type",
    "params",
    "answer",
    "personal",
    "amr"
  ],
  "examples": [
    {
      "type": "urn:qauth:ia:webauthn_get:v1-rc.0",
      "params": {
        "challenge": "Qm9vbGVhbi1ub3QtYS1yZWFsLWNoYWxsZW5nZS0zMmI",
        "rpId": "auth.example.com",
        "timeout": 300000,
        "userVerification": "required"
      },
      "answer": {
        "webauthn_response": "{\"id\":\"mC1lKXgSi0S3vW2mU1Nwhg\",\"rawId\":\"mC1lKXgSi0S3vW2mU1Nwhg\",\"type\":\"public-key\",\"response\":{\"clientDataJSON\":\"eyJ0eXBlIjoid2ViYXV0aG4uZ2V0In0\",\"authenticatorData\":\"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAAAQ\",\"signature\":\"MEUCIQDzVOkaFj9Kf2m9VE3e3Jx1yX2w\",\"userHandle\":\"b2Zmc2V0LXVzZXItaGFuZGxl\"},\"authenticatorAttachment\":\"platform\",\"clientExtensionResults\":{}}"
      },
      "personal": {
        "identifier": "alice@example.com"
      },
      "amr": [
        "pop",
        "mfa"
      ]
    }
  ],
  "$defs": {
    "params": {
      "type": "object",
      "properties": {
        "challenge": {
          "type": "string",
          "minLength": 43,
          "maxLength": 128,
          "pattern": "^[A-Za-z0-9_-]{43,128}$",
          "description": "The challenge, at least 32 random bytes."
        },
        "rpId": {
          "type": "string",
          "minLength": 1,
          "maxLength": 253,
          "pattern": "^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$",
          "description": "The relying party ID: the realm’s host."
        },
        "timeout": {
          "type": "integer",
          "minimum": 1000,
          "maximum": 600000,
          "description": "How long the ceremony may take, in milliseconds."
        },
        "userVerification": {
          "const": "required",
          "description": "The server refuses an assertion without user verification."
        }
      },
      "required": [
        "challenge",
        "rpId",
        "userVerification"
      ],
      "additionalProperties": false,
      "examples": [
        {
          "challenge": "Qm9vbGVhbi1ub3QtYS1yZWFsLWNoYWxsZW5nZS0zMmI",
          "rpId": "auth.example.com",
          "timeout": 300000,
          "userVerification": "required"
        }
      ]
    },
    "answer": {
      "type": "object",
      "properties": {
        "webauthn_response": {
          "type": "string",
          "minLength": 2,
          "maxLength": 8192,
          "contentMediaType": "application/json",
          "contentSchema": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "rawId": {
                "type": "string"
              },
              "type": {
                "const": "public-key"
              },
              "response": {
                "type": "object",
                "properties": {
                  "clientDataJSON": {
                    "type": "string"
                  },
                  "authenticatorData": {
                    "type": "string"
                  },
                  "signature": {
                    "type": "string"
                  },
                  "userHandle": {
                    "type": "string"
                  }
                },
                "required": [
                  "clientDataJSON",
                  "authenticatorData",
                  "signature"
                ]
              },
              "authenticatorAttachment": {
                "type": "string"
              },
              "clientExtensionResults": {
                "type": "object"
              }
            },
            "required": [
              "id",
              "rawId",
              "type",
              "response",
              "clientExtensionResults"
            ]
          },
          "description": "The authentication response, `PublicKeyCredential.toJSON()` (WebAuthn Level 3), as a JSON string. It is a string on both transports, so a form post carries it in one field (ADR-017 Decision 3)."
        }
      },
      "required": [
        "webauthn_response"
      ],
      "additionalProperties": false,
      "examples": [
        {
          "webauthn_response": "{\"id\":\"mC1lKXgSi0S3vW2mU1Nwhg\",\"rawId\":\"mC1lKXgSi0S3vW2mU1Nwhg\",\"type\":\"public-key\",\"response\":{\"clientDataJSON\":\"eyJ0eXBlIjoid2ViYXV0aG4uZ2V0In0\",\"authenticatorData\":\"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAAAQ\",\"signature\":\"MEUCIQDzVOkaFj9Kf2m9VE3e3Jx1yX2w\",\"userHandle\":\"b2Zmc2V0LXVzZXItaGFuZGxl\"},\"authenticatorAttachment\":\"platform\",\"clientExtensionResults\":{}}"
        }
      ]
    },
    "personal": {
      "type": "object",
      "description": "Who the transaction is for, so the screen can show it with a way to switch accounts. Absent until the transaction has an identifier.",
      "properties": {
        "identifier": {
          "type": "string",
          "minLength": 1,
          "maxLength": 254,
          "pattern": "^[^<>\\p{C}\\p{Z}\\u115F\\u1160\\u3164\\uFFA0](?:[^<>\\p{C}\\p{Zl}\\p{Zp}\\u115F\\u1160\\u3164\\uFFA0]*[^<>\\p{C}\\p{Z}\\u115F\\u1160\\u3164\\uFFA0])?$",
          "x-qauth-display": "account",
          "description": "The identifier of the account this transaction is for. Before a first factor succeeds it is the identifier exactly as the person gave it, after the one normalisation every input gets, whether or not an account holds it, so it tells nothing about which accounts exist; the form the account holds appears only after authentication. Personal data: only the personal-data read returns it."
        }
      },
      "additionalProperties": false,
      "examples": [
        {
          "identifier": "alice@example.com"
        }
      ]
    },
    "error": {
      "type": "string",
      "enum": [
        "invalid_credentials"
      ],
      "description": "Why the last answer was refused. A closed set."
    },
    "amr": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "const": [
        "pop",
        "mfa"
      ],
      "description": "The RFC 8176 `amr` values a successful answer adds to the transaction."
    }
  }
}
