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

# JWKS-Signaturschlüssel abrufen | Didit Authentication API

> GET /.well-known/jwks.json liefert die öffentlichen ES256-Schlüssel von Didit. Nach kid cachen; Rotation alle 30 Tage, Überlappung ein Tag.

> [!WARNING]
>
> Die Authentifizierung ist neu. Diese Endpoints werden vom Issuer Ihrer Anwendung bereitgestellt, etwa `https://<name>.auth.didit.me`, und verwenden niemals Ihren Didit-API-Schlüssel.

Schlüssel werden alle 30 Tage rotiert, wobei auf beiden Seiten ein Tag Überlappung besteht. Ein für 5 Minuten zwischengespeichertes JWKS ermöglicht daher auch während einer Rotation weiterhin eine korrekte Verifizierung. Rufen Sie es erneut ab, wenn ein Token eine `kid` angibt, die Ihnen nicht vorliegt, höchstens einmal pro Minute. Siehe [Caching und Rotation](https://docs.didit.me/de/authentication/tokens-and-jwks.md#caching-und-rotation).


## OpenAPI

````yaml de/openapi-authentication.json GET /.well-known/jwks.json
openapi: 3.0.3
info:
  title: Didit Authentication API
  version: 1.0.0
  description: >-
    Die serverseitigen Endpoints von Didit Authentication, dem Anmeldeprodukt
    für die Endbenutzer Ihrer Anwendung. Authentication ist **neu** und geht mit
    dem Release 2026-11-01 in Produktion.


    ## Basis-URL


    Jede Anwendung ist ihr eigener OpenID Connect Issuer, und jeder unten
    aufgeführte Endpoint wird unter dem Stamm dieses Issuers bereitgestellt:


    - `https://<name>.auth.didit.me` für eine Live-Anwendung oder
    `https://<name>.sandbox.auth.didit.me` für eine Sandbox-Anwendung.

    - Ihre eigene benutzerdefinierte Domain, sobald sie aktiv ist. Sie ersetzt
    dann den Standard-Host als Issuer: Neue Token geben sie in `iss` an,
    Discovery verweist auf sie und der veröffentlichbare Schlüssel ändert sich.
    Zugriffstoken, die unter dem Standard-Host ausgestellt wurden, schlagen bei
    `/session/`, `/step-up/` und `/monitoring-token/` fehl, bis sie aktualisiert
    werden.


    Live und Sandbox sind separate Anwendungen, also separate Issuer mit
    separaten Schlüsseln. Der veröffentlichbare Schlüssel lautet `pk_live_`
    (Live) oder `pk_test_` (Sandbox), gefolgt von der Base64url-Codierung ohne
    Padding des Issuers ohne abschließenden Schrägstrich: Decodieren Sie ihn, um
    den Issuer zu ermitteln. Es handelt sich um eine öffentliche Kennung, nicht
    um Anmeldedaten.


    Dieselben JSON-Endpoints werden auch unter
    `https://apx.didit.me/auth/v2/authentication/{application_id}/`
    bereitgestellt. Token geben immer den obigen Issuer an, unabhängig davon,
    welche Adresse sie ausgestellt hat.


    ## Anmeldedaten


    Diese Endpoints akzeptieren niemals Ihren Didit-API-Schlüssel oder ein
    Konsolen-Token.


    - Discovery, das JWKS und `POST /token/` erfordern keine Anmeldedaten.
    Clients sind öffentlich: Es gibt kein Client-Secret, und ein
    Autorisierungscode ist an seinen PKCE-Verifier (`S256`) gebunden.
    `client_id` ist Ihre Anwendungs-ID.

    - `/session/`, `/step-up/` und `/monitoring-token/` erfordern das
    Zugriffstoken der Person: `Authorization: Bearer <access_token>`. Jeder
    erfolgreiche Aufruf zählt als Aktivität in der Sitzung und setzt daher den
    Inaktivitäts-Timeout der Sitzung zurück.


    ## Request-Bodys


    Jeder Endpoint, der einen Body akzeptiert, unterstützt JSON-, form-codierte
    und multipart-Bodys. Dieses Dokument führt JSON sowie form-codierte Anfragen
    für `POST /token/` auf, wie es von OAuth-Clients gesendet wird. Ein Feld,
    das der Endpoint nicht akzeptiert, führt zu `400 {"<field>":
    "unknown_field"}`.


    ## Token


    - **Access-Token**: ein ES256-JWT mit dem Header `typ: at+jwt`, maximal 5
    Minuten gültig und niemals länger als seine Sitzung. Claims:
    `AccessTokenClaims`.

    - **ID-Token**: ein ES256-JWT mit dem Header `typ: JWT`. Claims:
    `IDTokenClaims`. Es wird niemals als Zugriffstoken akzeptiert.

    - **Refresh-Token**: eine zufällige Zeichenfolge, die bei jeder Verwendung
    rotiert. Das erneute Senden eines bereits verwendeten Refresh-Tokens
    widerruft die Sitzung.


    Verifizieren Sie ein Token mit den Schlüsseln aus `GET
    /.well-known/jwks.json`: Der Algorithmus muss `ES256` sein, `typ` muss mit
    dem Token-Typ übereinstimmen, `iss` muss dem von Ihnen konfigurierten Issuer
    entsprechen und `aud` Ihrer Anwendungs-ID. Eine Offline-Verifizierung
    erkennt eine widerrufene Sitzung erst nach Ablauf ihres Zugriffstokens; `GET
    /session/` ist die sofortige Prüfung.


    ## Fehler


    | Body | Wann |

    | --- | --- |

    | `{"error": "<code>"}` | Fehler von `POST /token/`, alle mit Status `400`,
    im Body-Format von [RFC 6749 Abschnitt
    5.2](https://www.rfc-editor.org/rfc/rfc6749#section-5.2): `invalid_grant`,
    `invalid_client` und Didits `mfa_required`. Dienstfehler:
    `temporarily_unavailable`, `monitoring_unavailable`, `monitoring_disabled`.
    |

    | `{"<field>": ["<message>"]}` oder `{"<field>": "<code>"}` | Ein
    Anfragefeld hat die Validierung nicht bestanden. `non_field_errors` benennt
    eine feldübergreifende Regel und `unknown_field` ein Feld, das der Endpoint
    nicht akzeptiert. |

    | `{"detail": "<message>"}` | `401` (`invalid_token`), `403`
    (`origin_not_allowed`), `404` (unbekannte Anwendung oder Step-Up) und `429`
    (Rate-Limit). Außerdem `400` für einen Body, der nicht geparst werden kann
    (`JSON parse error - ...`), `405` für eine Methode, die der Endpoint nicht
    bedient, und `415` für einen nicht unterstützten `Content-Type`. |


    Ein `401` enthält außerdem `WWW-Authenticate: Bearer`, und ein `429` enthält
    `Retry-After` in Sekunden.


    Zwei Ablehnungen erfolgen nicht als JSON. Eine Adresse, die kein Issuer ist,
    wird abgelehnt, bevor sie diese Endpoints erreicht, beispielsweise mit einer
    leeren `404`-Antwort für einen ungenutzten `*.auth.didit.me`-Namen. Eine
    `step_up_id`, die keine UUID ist, erhält eine `404`-Seite.


    ## Rate-Limits


    Eine Anfrage muss zwei Ebenen durchlaufen.


    **Endpoint-Limits**, gezählt pro Client-IP-Adresse, pro Anwendung und pro
    Endpoint:


    - Discovery und das JWKS: 1.200 Anfragen pro Minute und 12.000 pro Stunde.

    - Jeder andere Endpoint: 30 Anfragen pro Minute und 300 pro Stunde. `GET`
    und `DELETE /session/` teilen sich eine Zählung.


    Bei Überschreitung eines Limits: `429 {"detail": "Too many requests from
    this IP address. Please wait before trying again. Expected available in 60
    seconds."}`, oder `3600 seconds` für das stündliche Limit.


    **Bot-Schutz**, bei jedem `POST` und `DELETE`. Seine Buckets werden von
    allen `POST`- und `DELETE`-Anfragen der Anwendung geteilt, einschließlich
    der gehosteten Anmeldeschritte, und füllen sich kontinuierlich wieder auf:


    - 60 Anfragen pro Minute pro Client-IP-Adresse.

    - 30 Anfragen pro Minute pro Gerät für Anfragen, die ihr Gerät
    identifizieren, wie dies bei Browsern und nativen SDKs der Fall ist.

    - 3.000 Anfragen pro Minute für die gesamte Anwendung über alle IP-Adressen
    hinweg. Token-Aktualisierungen (`POST /token/` mit
    `grant_type=refresh_token`) greifen stattdessen auf einen eigenen Bucket zu:
    6.000 pro Minute für die gesamte Anwendung.


    Bei Überschreitung eines Buckets: `429 {"detail": "rate_limited Expected
    available in N seconds."}` (`1 second.` wenn N gleich 1 ist). Der Bucket pro
    IP erstreckt sich über alle Endpoints, sodass eine einzelne Adresse, die
    Token-, Step-Up- und Abmeldeaufrufe mischt, ihn leeren kann, bevor sie ein
    Endpoint-Limit erreicht. Der Anwendungs-Bucket zählt jeden Client der
    Anwendung, einschließlich Browsern.


    Beide Ebenen antworten, bevor der Endpoint ausgeführt wird. Eine Anfrage,
    die `429` erhalten hat, wurde also nicht ausgeführt: Wiederholen Sie sie
    nach `Retry-After`, einschließlich einer Token-Aktualisierung.


    ## Browser-Anfragen


    Eine Anfrage, die einen `Origin`-Header enthält, muss von einem der
    anwendungseigenen Origins oder ihren erlaubten Origins stammen, andernfalls
    erhält sie `403 origin_not_allowed`. Server-zu-Server-Anfragen senden keinen
    `Origin`-Header.


    ## Hier nicht behandelt


    Diese Routen bedienen die gehosteten Seiten, die Browser- und nativen SDKs
    sowie KI-Agenten. Sie sind nicht Teil des Serververtrags und werden von
    Server-SDKs nicht aufgerufen:


    - Anmeldeschritte: `POST /authorize/`, `POST /password/`, `/email/*`,
    `/phone/*`, `/password-reset/*`, `/passkeys/*`, `/mfa/*`, `/social/*` und
    `/protection/complete/`.

    - Gehostete Seiten und Callbacks: `/sign-in`, `/magic`, `/invite`, `/reset`,
    `/verify/`, `/sso/*`, `/wallet/callback/`, `/logo/` und die nativen
    App-Zuordnungsdateien unter `/.well-known/`.

    - Agentenzugriff: `/agents/*` und `/grants/`, einschließlich `GET
    /agents/session/`, der Live-Prüfung für das Zugriffstoken eines KI-Agenten.
    Agentenzugriff ist nicht Teil dieser Version des Vertrags.

    - Die Konsolen-Verwaltungs-API für Authentication, die Konsolensitzungen
    verwendet.


    Authentication-Ereignisse werden derzeit noch nicht als Webhooks zugestellt,
    daher definiert dieses Dokument keinen Webhook.
servers:
  - url: https://{issuer}
    description: 'Der Aussteller Ihrer Anwendung: ihr Anmeldeursprung.'
    variables:
      issuer:
        default: your-app.auth.didit.me
        description: >-
          Der Host des Ausstellers: `<name>.auth.didit.me` (Produktion),
          `<name>.sandbox.auth.didit.me` (Sandbox) oder Ihre aktive
          benutzerdefinierte Domain.
security: []
tags:
  - name: Issuer
    description: Discovery- und Signaturschlüssel zur Überprüfung von Tokens.
  - name: Tokens
    description: Der Autorisierungscode und Refresh-Grants.
  - name: Sessions
    description: Die Sitzung hinter einem Zugriffstoken prüfen und beenden.
  - name: Step-ups
    description: Verifizierung vor einer sensiblen Aktion.
  - name: Monitoring
    description: Geräte-Anmeldedaten für Transaktionsüberwachungs-Ereignisse.
paths:
  /.well-known/jwks.json:
    get:
      tags:
        - Issuer
      summary: Signaturschlüssel abrufen
      description: >-
        Die öffentlichen ES256-Schlüssel der Anwendung. Jedes Token benennt
        seinen Schlüssel im `kid`-Header.


        Schlüssel rotieren alle 30 Tage. Der nächste Schlüssel wird einen Tag
        vor Beginn des Signierens veröffentlicht, und der vorherige Schlüssel
        bleibt noch einen Tag nach Beendigung veröffentlicht. So verifiziert ein
        bis zu 5 Minuten zwischengespeichertes JWKS auch über eine Rotation
        hinweg weiter. Speichern Sie Schlüssel nach `kid` zwischen und rufen Sie
        das JWKS erneut ab, wenn ein Token eine `kid` nennt, die Sie nicht haben
        – höchstens einmal pro Minute. Wenn Didit einen kompromittierten
        Schlüssel widerruft, wird der Schlüssel sofort aus diesem Dokument
        entfernt und `GET /session/` lehnt jedes von ihm signierte Token ab. Ein
        Ersatzschlüssel beginnt sofort zu signieren, ohne die eintägige
        Vorabveröffentlichung; ein bis zu 5 Minuten zuvor zwischengespeichertes
        JWKS akzeptiert den widerrufenen Schlüssel daher weiterhin und kennt den
        Ersatzschlüssel noch nicht.
      operationId: authentication_get_jwks
      responses:
        '200':
          description: Die veröffentlichten Schlüssel.
          headers:
            Cache-Control:
              description: >-
                `public, max-age=300`: Sie und gemeinsame Caches dürfen eine
                erfolgreiche Antwort 5 Minuten lang aufbewahren, die Lebensdauer
                eines Zugriffstokens.
              schema:
                type: string
                example: public, max-age=300
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JSONWebKeySet'
              examples:
                Keys:
                  summary: Ein Signaturschlüssel
                  value:
                    keys:
                      - kty: EC
                        crv: P-256
                        x: ZDN2unLMultuZwNY_ZKMvsKLRrlC_usPFZyK77cnDO8
                        'y': CfLKoaJNvhFpDWqG56H8dD_j0f1c93RdR63bhIdTh3I
                        kid: k_8sJ2dQvX0nLr5TfYb3HkPw
                        use: sig
                        alg: ES256
        '403':
          $ref: '#/components/responses/OriginNotAllowed'
        '404':
          $ref: '#/components/responses/ApplicationNotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/TemporarilyUnavailable'
      security:
        - {}
components:
  schemas:
    JSONWebKeySet:
      type: object
      description: >-
        Die veröffentlichten öffentlichen Signaturschlüssel der Anwendung.
        Normalerweise ein Schlüssel; zwei während einer Rotation, wenn der
        nächste Schlüssel einen Tag vor dem Signieren veröffentlicht wird und
        der vorherige Schlüssel noch einen Tag nach dem Beenden verbleibt.
      required:
        - keys
      properties:
        keys:
          type: array
          items:
            $ref: '#/components/schemas/JSONWebKey'
    JSONWebKey:
      type: object
      description: Ein öffentlicher P-256-Schlüssel im JWK-Format (RFC 7517).
      required:
        - kty
        - crv
        - x
        - 'y'
        - kid
        - use
        - alg
      properties:
        kty:
          type: string
          enum:
            - EC
        crv:
          type: string
          enum:
            - P-256
        x:
          type: string
          description: Die x-Koordinate des öffentlichen Punkts, base64url.
          example: ZDN2unLMultuZwNY_ZKMvsKLRrlC_usPFZyK77cnDO8
        'y':
          type: string
          description: Die y-Koordinate des öffentlichen Punkts, base64url.
          example: CfLKoaJNvhFpDWqG56H8dD_j0f1c93RdR63bhIdTh3I
        kid:
          type: string
          description: >-
            Schlüssel-ID, die `kid` im Header jedes Tokens, das mit diesem
            Schlüssel signiert wird. Neue Schlüssel-IDs beginnen mit `k_`.
          example: k_8sJ2dQvX0nLr5TfYb3HkPw
        use:
          type: string
          enum:
            - sig
        alg:
          type: string
          enum:
            - ES256
    Detail:
      type: object
      required:
        - detail
      properties:
        detail:
          type: string
          example: invalid_token
    OAuthError:
      title: OAuth error
      type: object
      description: Ein OAuth-Fehler (RFC 6749 Abschnitt 5.2) oder ein Dienstfehler.
      required:
        - error
      properties:
        error:
          type: string
          example: invalid_grant
  responses:
    OriginNotAllowed:
      description: >-
        Die Anfrage enthielt einen `Origin`, der weder der anwendungseigene ist
        noch zu den zulässigen Origins gehört. Server-Anfragen senden keinen
        `Origin`.
      headers:
        Cache-Control:
          description: 'Immer `no-store`: Diese Antwort niemals zwischenspeichern.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Immer `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            OriginNotAllowed:
              summary: Origin nicht zulässig
              value:
                detail: origin_not_allowed
    ApplicationNotFound:
      description: >-
        Die Adresse gehört zu einer Anwendung, aber Authentication ist für sie
        nicht aktiv; bei der Adresse `apx.didit.me` ist die Anwendungs-ID
        unbekannt. Eine Adresse, die zu keiner Anwendung gehört, wird
        abgewiesen, bevor sie den Endpoint erreicht, und diese Antwort ist kein
        JSON.
      headers:
        Cache-Control:
          description: 'Immer `no-store`: Diese Antwort niemals zwischenspeichern.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Immer `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            ApplicationNotFound:
              summary: Unbekannte Anwendung
              value:
                detail: No Configuration matches the given query.
    RateLimited:
      description: >-
        Zu viele Anfragen von dieser IP-Adresse für diesen Endpoint, oder bei
        einem `POST` oder `DELETE` ist ein Bot-Schutz-Bucket leer. Es wurde
        nichts ausgeführt: Warten Sie `Retry-After` Sekunden und versuchen Sie
        es dann erneut.
      headers:
        Retry-After:
          description: Sekunden, die vor einem Wiederholungsversuch gewartet werden müssen.
          schema:
            type: integer
            example: 60
        Cache-Control:
          description: 'Immer `no-store`: Diese Antwort niemals zwischenspeichern.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Immer `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            RateLimited:
              summary: Endpoint-Limit
              value:
                detail: >-
                  Too many requests from this IP address. Please wait before
                  trying again. Expected available in 60 seconds.
            BotProtection:
              summary: Bot-Schutz-Limit (POST und DELETE)
              value:
                detail: rate_limited Expected available in 2 seconds.
    TemporarilyUnavailable:
      description: >-
        Ein Dienst, von dem die Anfrage abhängt, ist vorübergehend nicht
        verfügbar. Versuchen Sie es mit Backoff erneut.
      headers:
        Cache-Control:
          description: 'Immer `no-store`: Diese Antwort niemals zwischenspeichern.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Immer `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/OAuthError'
          examples:
            TemporarilyUnavailable:
              summary: Später erneut versuchen
              value:
                error: temporarily_unavailable

````

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