> ## 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

> GET /session/ 用于对照实时会话校验访问令牌：令牌被撤销、空闲超时、被封禁或刷新后，校验会立即失败。Didit 认证 API。

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

这是即时撤销检查。每个 IP 地址每分钟允许 30 次请求，每小时允许 300 次，因此请在每次请求时离线验证 token，并在执行敏感操作前调用此接口。参阅 [检查会话](https://docs.didit.me/zh/authentication/tokens-and-jwks.md#检查会话)。


## OpenAPI

````yaml zh/openapi-authentication.json GET /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/:
    get:
      tags:
        - Sessions
      summary: 获取会话
      description: >-
        根据实时会话核验访问令牌并将其返回。比自行验证 JWT
        更加严格：在以下情况下也会立即失败：会话已被撤销、处于空闲状态或已超过生命周期；用户已被拦截或其邮箱不再处于已验证状态；会话不再满足您的 MFA
        策略（例如用户添加了身份验证器应用或成为组织管理员后）；或者令牌已被刷新替换。建议在执行敏感操作（例如付款）之前使用它。成功的检查计为活动，因此会重置会话的空闲超时时间。
      operationId: authentication_get_session
      responses:
        '200':
          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/Session'
              examples:
                Session:
                  summary: 密码会话
                  value:
                    sub: 1c9d8b88-1bff-43d1-ad7a-88b2bc0024e9
                    sid: c9abf6cc-2d64-4bf2-b31e-a4d09a070ab1
                    application_id: 7b0a6c2e-3f41-4c9a-8d55-1e2f3a4b5c6d
                    vendor_data: user-42
                    amr:
                      - password
                    mfa_verified: false
                    email: person@example.com
                    email_verified: true
                    phone: null
                    verified_identity: null
                    verified: null
                    expires_at: '2026-11-16T10:41:14.347557Z'
                    post_logout_redirect_uri: ''
                    organizations: []
                VerifiedMember:
                  summary: 已验证的组织成员
                  value:
                    sub: 1c9d8b88-1bff-43d1-ad7a-88b2bc0024e9
                    sid: c9abf6cc-2d64-4bf2-b31e-a4d09a070ab1
                    application_id: 7b0a6c2e-3f41-4c9a-8d55-1e2f3a4b5c6d
                    vendor_data: user-42
                    amr:
                      - passkey
                    mfa_verified: true
                    email: person@example.com
                    email_verified: true
                    phone: '+34600000000'
                    verified_identity: null
                    verified:
                      level: full_id
                      over_18: true
                      given_name: Alex
                      country: ES
                    expires_at: '2026-11-16T10:41:14.347557Z'
                    post_logout_redirect_uri: https://app.example.com/
                    organizations:
                      - organization_id: 3e9a1f0b-5c2d-4e7f-8a6b-9c0d1e2f3a4b
                        organization__name: Northwind
                        role: admin
                        custom_role: null
        '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:
  schemas:
    Session:
      type: object
      description: 访问 token 背后的活跃会话。
      required:
        - sub
        - sid
        - application_id
        - vendor_data
        - amr
        - mfa_verified
        - email
        - email_verified
        - phone
        - verified_identity
        - verified
        - expires_at
        - post_logout_redirect_uri
        - organizations
      properties:
        sub:
          type: string
          format: uuid
          description: 身份 ID。
          example: 1c9d8b88-1bff-43d1-ad7a-88b2bc0024e9
        sid:
          type: string
          format: uuid
          description: 会话 ID。
          example: c9abf6cc-2d64-4bf2-b31e-a4d09a070ab1
        application_id:
          type: string
          format: uuid
          example: 7b0a6c2e-3f41-4c9a-8d55-1e2f3a4b5c6d
        vendor_data:
          type: string
          description: 该人员在 Didit 各产品中的标识，与 token 中的一致。
          example: user-42
        amr:
          $ref: '#/components/schemas/AuthenticationMethods'
        mfa_verified:
          type: boolean
          description: 会话是否通过了第二重验证。对于 passkey 登录始终为 `true`。
          example: false
        email:
          type: string
          format: email
          nullable: true
          example: person@example.com
        email_verified:
          type: boolean
          example: true
        phone:
          type: string
          nullable: true
          description: E.164 格式的电话号码，或 `null`。
          example: null
        verified_identity:
          $ref: '#/components/schemas/WalletVerification'
        verified:
          type: object
          nullable: true
          description: >-
            验证等级和所选声明，与 token 中作为 `verified` 携带的对象相同，若无则为 `null`。请读取此字段，而不是
            `email_verified`，以了解该人员是否已验证其身份。
          properties:
            level:
              type: string
              enum:
                - liveness
                - liveness_face_match
                - full_id
              description: 通过的最高等级。由弱到强依次为：`liveness`、`liveness_face_match`、`full_id`。
              example: full_id
            over_18:
              type: boolean
              example: true
            over_21:
              type: boolean
              example: true
            given_name:
              type: string
              example: Alex
            family_name:
              type: string
              example: Doe
            birthdate:
              type: string
              description: 来自证件的出生日期，`YYYY-MM-DD`。
              example: '1990-04-12'
            nationality:
              type: string
              description: ISO 3166-1 alpha-2 国家/地区代码。
              example: ES
            country:
              type: string
              description: 证件所属国家/地区的 ISO 3166-1 alpha-2 代码。
              example: ES
            document_verified:
              type: boolean
              example: true
            liveness:
              type: boolean
              example: true
        expires_at:
          type: string
          format: date-time
          description: 会话最晚结束时间。空闲超时可能会使其提前结束。
          example: '2026-11-16T10:41:14.347557Z'
        post_logout_redirect_uri:
          type: string
          description: 在用户退出登录后，您的应用将其重定向到的位置。未设置时为空字符串。
          example: https://app.example.com/
        organizations:
          type: array
          description: 该人员所属的每个客户组织（当组织功能启用时）。否则为空。
          items:
            $ref: '#/components/schemas/SessionOrganization'
    AuthenticationMethods:
      type: array
      description: >-
        会话的登录方式，为一个单值：例如
        `password`、`code`（邮箱验证码）、`magic`（魔法链接）、`passkey`、`phone`、`sso`、`wallet`（Didit
        ID Wallet）或社交登录方式的名称。对于代理 token 则为空。
      items:
        type: string
      example:
        - password
    WalletVerification:
      type: object
      description: 登录时 Didit ID Wallet 共享的内容。当用户通过其他方式登录时为 `null`。
      nullable: true
      required:
        - issuer
        - subject
      properties:
        issuer:
          type: string
          description: 钱包的签发方。
          example: https://apx.didit.me/auth/idv
        subject:
          type: string
          description: 该人员在钱包中的 ID。
          example: 8b7f5c1e-2d3a-4b5c-9e8f-7a6b5c4d3e2f
        shared_session:
          type: object
          description: 该人员选择共享的验证，您可使用自己的 API 密钥进行兑换。
          properties:
            share_token:
              type: string
            session_id:
              type: string
            from_application_id:
              type: string
        claims:
          type: object
          description: 该人员同意共享的已验证事实，仅限于您的应用所请求的内容。
          additionalProperties:
            oneOf:
              - type: boolean
              - type: string
          example:
            over_18: true
            given_name: Alex
    SessionOrganization:
      type: object
      required:
        - organization_id
        - organization__name
        - role
        - custom_role
      properties:
        organization_id:
          type: string
          format: uuid
          example: 3e9a1f0b-5c2d-4e7f-8a6b-9c0d1e2f3a4b
        organization__name:
          type: string
          description: 组织名称。
          example: Northwind
        role:
          type: string
          enum:
            - admin
            - member
            - billing
          example: admin
        custom_role:
          type: object
          nullable: true
          description: 分配给成员的自定义角色，或为 `null`。
          required:
            - key
            - permissions
          properties:
            key:
              type: string
              example: approver
            permissions:
              type: array
              items:
                type: string
              example:
                - payouts.approve
    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
  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
  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.