> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# 撤销会话（退出登录）| Didit 认证 API

> DELETE /session/ 可结束访问令牌对应的会话并返回 204。Didit 会使其刷新令牌失效，会话检查立即失败。

> [!WARNING]
>
> 认证功能是新增功能。这些端点由您应用的签发方提供，例如 `https://<name>.auth.didit.me`，且绝不接受您的 Didit API 密钥。

请发送用户当前的访问令牌：该令牌尚未过期，也未因刷新而被替换。返回 `401` 表示会话未能结束，请先刷新令牌，然后使用新的访问令牌再次退出登录。

您离线验证的访问令牌在过期前（最长 5 分钟内）仍然有效。退出登录后，如果您设置了 `post_logout_redirect_uri`，请将用户重定向至该地址。参见 [退出登录](https://docs.didit.me/zh/authentication/tokens-and-jwks.md#退出登录)。


## OpenAPI

````yaml zh/openapi-authentication.json DELETE /session/
openapi: 3.0.3
info:
  title: Didit Authentication API
  version: 1.0.0
  description: >-
    Didit Authentication 面向服务器的 endpoint，该产品是为您应用的终端用户提供的登录产品。Authentication
    为**新功能**，将于 2026-11-01 版本在生产环境中正式推出。


    ## 基础 URL


    每个应用都是其独立的 OpenID Connect 签发方（issuer），以下所有 endpoint 均在该签发方的根路径下提供服务：


    - 生产环境应用为 `https://<name>.auth.didit.me`，沙盒应用为
    `https://<name>.sandbox.auth.didit.me`。

    - 您的自定义域名（一旦激活）。激活后，它将取代默认主机作为签发方：新 token 会在 `iss`
    中标明该域名，发现文档（discovery）会指向它，并且可发布密钥也会改变。在默认主机下签发的 access token 将无法用于调用
    `/session/`、`/step-up/` 和 `/monitoring-token/`，直至完成刷新。


    生产环境与沙盒是独立的应用，因此它们是拥有独立密钥的不同签发方。可发布密钥为 `pk_live_`（生产环境）或
    `pk_test_`（沙盒），后接签发方去除末尾斜杠后的无填充 base64url 编码：对其解码即可找到签发方。它是一个公开标识符，并非凭据。


    相同的 JSON endpoint 也在
    `https://apx.didit.me/auth/v2/authentication/{application_id}/`
    下提供。无论由哪个地址签发，token 始终会将上述签发方声明在内。


    ## 凭据


    这些 endpoint 绝不接受您的 Didit API 密钥或控制台 token。


    - 发现文档（Discovery）、JWKS 以及 `POST /token/` 不需要任何凭据。客户端为公开客户端：不存在 client
    secret，且授权码（authorization code）与其 PKCE 验证器（`S256`）绑定。`client_id` 即为您的应用 ID。

    - `/session/`、`/step-up/` 和 `/monitoring-token/` 接收用户的 access
    token：`Authorization: Bearer
    <access_token>`。每次成功的调用均计为该会话的活动，因此会重置会话的空闲超时时间。


    ## 请求体


    所有接收请求体的 endpoint 均支持 JSON、表单编码（form-encoded）和 multipart 请求体。本文档列出了 JSON，以及
    OAuth 客户端发送 `POST /token/` 时使用的表单编码。如果 endpoint 收到不支持的字段，将返回 `400
    {"<field>": "unknown_field"}`。


    ## Token


    - **Access token**：请求头为 `typ: at+jwt` 的 ES256 JWT，有效期最多 5
    分钟，且绝不超过其会话时长。Claims 为 `AccessTokenClaims`。

    - **ID token**：请求头为 `typ: JWT` 的 ES256 JWT。Claims 为 `IDTokenClaims`。绝不能作为
    access token 使用。

    - **Refresh token**：随机字符串，每次使用时均会轮换。再次发送已使用的 refresh token 将会撤销该会话。


    使用来自 `GET /.well-known/jwks.json` 的密钥验证 token：算法必须为 `ES256`，`typ` 必须匹配 token
    类型，`iss` 必须等于您配置的签发方，且 `aud` 必须为您的应用 ID。离线验证仅在 access token
    过期后才能察觉已撤销的会话；`GET /session/` 则是即时检查手段。


    ## 错误


    | 响应体 | 适用情况 |

    | --- | --- |

    | `{"error": "<code>"}` | 来自 `POST /token/` 的错误，状态码均为 `400`，响应体格式符合 [RFC
    6749 第 5.2
    节](https://www.rfc-editor.org/rfc/rfc6749#section-5.2)：`invalid_grant`、`invalid_client`
    以及 Didit 的
    `mfa_required`。服务错误：`temporarily_unavailable`、`monitoring_unavailable`、`monitoring_disabled`。
    |

    | `{"<field>": ["<message>"]}` 或 `{"<field>": "<code>"}` |
    请求字段未通过验证。`non_field_errors` 表示跨字段规则校验失败，`unknown_field` 表示 endpoint 不接受的字段。
    |

    | `{"detail": "<message>"}` |
    `401`（`invalid_token`）、`403`（`origin_not_allowed`）、`404`（未知应用或 step-up）以及
    `429`（速率限制）。此外还包括无法解析请求体的 `400`（`JSON parse error - ...`）、endpoint 不支持该方法的
    `405` 以及不支持的 `Content-Type` 对应的 `415`。 |


    `401` 响应还会携带 `WWW-Authenticate: Bearer`，而 `429` 响应会携带以秒为单位的 `Retry-After`。


    有两种拒绝响应不是 JSON 格式。非签发方地址在到达这些 endpoint 之前就会被拒绝，例如未使用的 `*.auth.didit.me`
    名称会返回空白的 `404`。若 `step_up_id` 不是 UUID，则会返回 `404` 页面。


    ## 速率限制


    请求必须通过两层限制。


    **Endpoint 限制**，按客户端 IP 地址、应用及 endpoint 分别计数：


    - 发现文档（Discovery）与 JWKS：每分钟 1,200 次请求，每小时 12,000 次请求。

    - 其他所有 endpoint：每分钟 30 次请求，每小时 300 次请求。`GET` 和 `DELETE /session/` 共享同一个计数。


    超出限制时返回：`429 {"detail": "Too many requests from this IP address. Please wait
    before trying again. Expected available in 60 seconds."}`，小时限制则为 `3600
    seconds`。


    **Bot 防护**，适用于所有 `POST` 和 `DELETE` 请求。其桶由该应用的所有 `POST` 和 `DELETE`
    请求共享（包括托管登录步骤），并持续补充：


    - 每个客户端 IP 地址每分钟 60 次请求。

    - 每个设备每分钟 30 次请求（适用于像浏览器和原生 SDK 那样标识自身设备的请求）。

    - 整个应用（涵盖所有 IP 地址）每分钟 3,000 次请求。Token 刷新（带有 `grant_type=refresh_token` 的
    `POST /token/`）则使用独立的桶：整个应用每分钟 6,000 次。


    超出桶容量时返回：`429 {"detail": "rate_limited Expected available in N seconds."}`（当
    N 为 1 时为 `1 second.`）。基于 IP 的桶跨 endpoint 共享，因此混合调用 token、step-up
    和退出登录调用的单一地址可能会在触及任何 endpoint 限制之前就耗尽其额度。应用级别的桶会统计该应用的所有客户端，包括浏览器。


    两层限制均在 endpoint 执行前进行拦截并返回响应，因此收到 `429` 的请求并未实际执行：请在 `Retry-After`
    指定的时间之后重试（包括刷新请求）。


    ## 浏览器请求


    携带 `Origin` 请求头的请求必须来自应用自身的源或其允许的源，否则将收到 `403
    origin_not_allowed`。服务器到服务器的请求不发送 `Origin`。


    ## 此处未涵盖的内容


    以下路由用于托管页面、浏览器和原生 SDK 以及 AI agent。它们不属于服务器约定的一部分，服务器 SDK 也不会调用它们：


    - 登录步骤：`POST /authorize/`、`POST
    /password/`、`/email/*`、`/phone/*`、`/password-reset/*`、`/passkeys/*`、`/mfa/*`、`/social/*`
    和 `/protection/complete/`。

    -
    托管页面和回调：`/sign-in`、`/magic`、`/invite`、`/reset`、`/verify/`、`/sso/*`、`/wallet/callback/`、`/logo/`
    以及 `/.well-known/` 下的原生应用关联文件。

    - Agent 访问：`/agents/*` 和 `/grants/`，包括用于实时检查 AI agent 的 access token 的 `GET
    /agents/session/`。Agent 访问不属于当前版本的约定范围。

    - Authentication 的控制台管理 API（该 API 接收控制台会话）。


    Authentication 事件目前尚未作为 Webhook 投递，因此本文档未定义任何 Webhook。
servers:
  - url: https://{issuer}
    description: 您的应用的签发方：其登录来源。
    variables:
      issuer:
        default: your-app.auth.didit.me
        description: >-
          签发方主机：`<name>.auth.didit.me`（生产环境）、`<name>.sandbox.auth.didit.me`（沙盒）或您当前生效的自定义网域。
security: []
tags:
  - name: Issuer
    description: 发现和签名密钥，用于核验 token。
  - name: Tokens
    description: 授权码授予和刷新授予。
  - name: Sessions
    description: 检查并结束访问 token 背后的会话。
  - name: Step-ups
    description: 敏感操作前的验证。
  - name: Monitoring
    description: 用于交易监控事件的设备凭据。
paths:
  /session/:
    delete:
      tags:
        - Sessions
      summary: 撤销会话
      description: >-
        将该用户登出：结束访问 token 背后的会话。使用其访问 token 调用 `GET /session/` 会立即失败，且其刷新 token
        将停止工作。


        请发送当前的访问 token：即尚未过期且未被刷新操作替换的 token。任何其他 token 都会收到 `401` 且会话不会结束，因此请刷新
        token，并使用新的访问 token 重新登出。之前签发的监控 token 不与该会话绑定，在其过期前（15
        分钟内）仍可使用。您在离线状态下验证的 token 在过期前（5 分钟内）保持有效。然后将该用户重定向至您的
        `post_logout_redirect_uri`（如果您设置了该地址）。
      operationId: authentication_revoke_session
      responses:
        '204':
          description: 会话已结束。
          headers:
            Cache-Control:
              description: 始终为 `no-store`：切勿缓存此响应。
              schema:
                type: string
                example: no-store
            Pragma:
              description: 始终为 `no-cache`。
              schema:
                type: string
                example: no-cache
        '401':
          $ref: '#/components/responses/InvalidToken'
        '403':
          $ref: '#/components/responses/OriginNotAllowed'
        '404':
          $ref: '#/components/responses/ApplicationNotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/TemporarilyUnavailable'
      security:
        - AccessToken: []
components:
  responses:
    InvalidToken:
      description: >-
        访问 token 缺失、格式错误、已过期、由其他签发方或密钥签名、为 ID token、为代理
        token，或已被刷新替换；或者其会话已被撤销、因闲置超时、已超过生命周期或不再符合您的 MFA
        策略，抑或是对应人员已被屏蔽或其邮箱不再处于已验证状态。请让该人员重新登录。
      headers:
        WWW-Authenticate:
          description: '`Bearer`。'
          schema:
            type: string
            example: Bearer
        Cache-Control:
          description: 始终为 `no-store`：切勿缓存此响应。
          schema:
            type: string
            example: no-store
        Pragma:
          description: 始终为 `no-cache`。
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            InvalidToken:
              summary: 已拒绝的访问令牌
              value:
                detail: invalid_token
    OriginNotAllowed:
      description: 请求携带的 `Origin` 既不是该应用自身的源，也不在其允许的源列表中。服务端请求不发送 `Origin`。
      headers:
        Cache-Control:
          description: 始终为 `no-store`：切勿缓存此响应。
          schema:
            type: string
            example: no-store
        Pragma:
          description: 始终为 `no-cache`。
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            OriginNotAllowed:
              summary: 来源（Origin）不允许
              value:
                detail: origin_not_allowed
    ApplicationNotFound:
      description: >-
        该地址属于某个应用，但该应用尚未启用 Authentication 功能；在 `apx.didit.me` 地址上，应用 ID
        未知。不属于任何应用的地址在到达 endpoint 之前即被拒绝，且该响应不是 JSON 格式。
      headers:
        Cache-Control:
          description: 始终为 `no-store`：切勿缓存此响应。
          schema:
            type: string
            example: no-store
        Pragma:
          description: 始终为 `no-cache`。
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            ApplicationNotFound:
              summary: 未知应用
              value:
                detail: No Configuration matches the given query.
    RateLimited:
      description: >-
        此地址针对该 endpoint 的请求过多，或者在 `POST` 或 `DELETE` 上机器人防护令牌桶已耗尽。未执行任何操作：请等待
        `Retry-After` 秒后重试。
      headers:
        Retry-After:
          description: 重试前需要等待的秒数。
          schema:
            type: integer
            example: 60
        Cache-Control:
          description: 始终为 `no-store`：切勿缓存此响应。
          schema:
            type: string
            example: no-store
        Pragma:
          description: 始终为 `no-cache`。
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            RateLimited:
              summary: endpoint 限制
              value:
                detail: >-
                  Too many requests from this IP address. Please wait before
                  trying again. Expected available in 60 seconds.
            BotProtection:
              summary: 机器人防护限制（POST 和 DELETE）
              value:
                detail: rate_limited Expected available in 2 seconds.
    TemporarilyUnavailable:
      description: 请求所依赖的服务暂时不可用。请采用退避策略重试。
      headers:
        Cache-Control:
          description: 始终为 `no-store`：切勿缓存此响应。
          schema:
            type: string
            example: no-store
        Pragma:
          description: 始终为 `no-cache`。
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/OAuthError'
          examples:
            TemporarilyUnavailable:
              summary: 稍后重试
              value:
                error: temporarily_unavailable
  schemas:
    Detail:
      type: object
      required:
        - detail
      properties:
        detail:
          type: string
          example: invalid_token
    OAuthError:
      title: OAuth error
      type: object
      description: OAuth 错误（RFC 6749 第 5.2 节）或服务错误。
      required:
        - error
      properties:
        error:
          type: string
          example: invalid_grant
  securitySchemes:
    AccessToken:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        来自 `POST /token/` 的该人员访问 token：请求头带有 `typ: at+jwt` 的 ES256 JWT，有效期最多 5
        分钟。并非您的 Didit API 密钥。

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.