{
  "product": "Specification (reference)",
  "title": "OAuth 2.1 Authorization Code + PKCE",
  "summary": "Delegated authorisation done the way current guidance requires.",
  "category": "protocols",
  "entries": [
    {
      "path": [
        "Flow",
        "Client redirects to the authorization endpoint"
      ],
      "value": "",
      "status": "yes",
      "note": "response_type=code"
    },
    {
      "path": [
        "Flow",
        "User authenticates and consents at the provider"
      ],
      "value": "",
      "status": "yes",
      "note": "never at the client"
    },
    {
      "path": [
        "Flow",
        "Provider redirects back with a code"
      ],
      "value": "",
      "status": "yes",
      "note": "short-lived, single use"
    },
    {
      "path": [
        "Flow",
        "Client exchanges the code at the token endpoint"
      ],
      "value": "",
      "status": "yes",
      "note": "server-to-server"
    },
    {
      "path": [
        "PKCE",
        "code_verifier generated per request"
      ],
      "value": "",
      "status": "yes",
      "note": "high entropy"
    },
    {
      "path": [
        "PKCE",
        "code_challenge sent with S256"
      ],
      "value": "",
      "status": "yes",
      "note": "plain is not acceptable"
    },
    {
      "path": [
        "PKCE",
        "Token exchange rejects a mismatched verifier"
      ],
      "value": "",
      "status": "yes",
      "note": ""
    },
    {
      "path": [
        "State",
        "state parameter bound to the user session"
      ],
      "value": "",
      "status": "yes",
      "note": "CSRF defence"
    },
    {
      "path": [
        "State",
        "Redirect URI matched exactly against registration"
      ],
      "value": "",
      "status": "yes",
      "note": "no wildcards"
    },
    {
      "path": [
        "Scopes",
        "Requested, granted and enforced scopes are distinct"
      ],
      "value": "",
      "status": "yes",
      "note": "granted may be narrower"
    },
    {
      "path": [
        "Tokens",
        "Access token short-lived"
      ],
      "value": "",
      "status": "yes",
      "note": "minutes, not days"
    },
    {
      "path": [
        "Tokens",
        "Refresh token rotation with reuse detection"
      ],
      "value": "",
      "status": "yes",
      "note": "reuse revokes the family"
    },
    {
      "path": [
        "Tokens",
        "Tokens never placed in URLs or logs"
      ],
      "value": "",
      "status": "yes",
      "note": ""
    },
    {
      "path": [
        "Endpoints",
        "Token revocation"
      ],
      "value": "",
      "status": "yes",
      "note": "RFC 7009"
    },
    {
      "path": [
        "Endpoints",
        "Discovery document"
      ],
      "value": "/.well-known/openid-configuration",
      "status": "yes",
      "note": ""
    },
    {
      "path": [
        "Security",
        "Implicit flow not offered"
      ],
      "value": "",
      "status": "yes",
      "note": "removed in OAuth 2.1"
    },
    {
      "path": [
        "Security",
        "Clients that cannot keep a secret are treated as public"
      ],
      "value": "",
      "status": "yes",
      "note": ""
    }
  ]
}
