Fahrtenbuch

Linked Accounts

GET
/auth/oauth/providers

Ein Anbieter ist aktiv, wenn auf dem Server Client-ID und Secret gesetzt sind.

Response Body

Anbieterliste

application/json
  1. response
[index: integer]?
Example Request
curl -X GET 'https://example.com/api/v1/auth/oauth/providers'
Example Response200
[  {    "id": "google",    "name": "string",    "enabled": true  }]
POST
/auth/oauth/{provider}/login

Liefert die Autorisierungs-URL des Anbieters.

Web: ohne Request-Body. Der Server setzt einen kurzlebigen HttpOnly-Cookie, der den Callback an diesen Browser bindet; der Client leitet im selben Browser auf authorizationUrl weiter.

Mobile App: mit appRedirectUri und appCodeChallenge. Die App erzeugt einen zufälligen Verifier (43–128 Zeichen, PKCE nach RFC 7636), sendet appCodeChallenge = BASE64URL(SHA256(verifier)) und öffnet authorizationUrl in einem Custom Tab. Nach der Anmeldung leitet der Server auf appRedirectUri?ticket=… weiter (bei Fehlern appRedirectUri?error=<CODE>). Die App löst das Ticket zusammen mit dem Verifier über POST /auth/oauth/exchange ein. Die Serveradresse muss die App vorher kennen.

appRedirectUri muss auf dem Server freigegeben sein (OAUTH_APP_REDIRECT_URIS, Standard fahrtenbuch://oauth/callback).

Path Parameters

provider*string
Value in"google""microsoft"

Request Body

application/json
  1. body
appRedirectUri?string
Lengthlength <= 300
appCodeChallenge?string

S256-Challenge des App-Verifiers (Base64url ohne Padding).

Match^[A-Za-z0-9_-]{43}$

Response Body

Autorisierungs-URL

application/json
  1. response
authorizationUrl*string
Formaturi
Example Request
curl -X POST 'https://example.com/api/v1/auth/oauth/google/login' \  -H 'Content-Type: application/json' \  -d '{}'
Example Response
{  "authorizationUrl": "http://example.com"}
POST
/auth/oauth/{provider}/link

Authorization

bearerAuth
headerAuthorizationBearer <JWT>

Path Parameters

provider*string
Value in"google""microsoft"

Response Body

Autorisierungs-URL

application/json
  1. response
authorizationUrl*string
Formaturi
Example Request
curl -X POST 'https://example.com/api/v1/auth/oauth/google/link'
Example Response
{  "authorizationUrl": "http://example.com"}
GET
/auth/oauth/{provider}/callback

Wird vom Browser nach der Anmeldung beim Anbieter aufgerufen und leitet zurück zur Web-App: Anmeldung nach /login#oauthTicket=…, Verknüpfung nach /profilesettings?oauthLinked=<provider>, Fehler mit ?oauthError=<CODE> (z. B. OAUTH_NOT_LINKED, OAUTH_CANCELLED, OAUTH_STATE_INVALID, OAUTH_IDENTITY_IN_USE, OAUTH_PROVIDER_ALREADY_LINKED). Wurde die Anmeldung aus der App gestartet, geht die Weiterleitung an appRedirectUri?ticket=… bzw. appRedirectUri?error=<CODE>.

Path Parameters

provider*string
Value in"google""microsoft"

Query Parameters

code?string
state?string
error?string

Response Body

Weiterleitung zur Web-App

Example Request
curl -X GET 'https://example.com/api/v1/auth/oauth/google/callback'
Example Response303
Empty
POST
/auth/oauth/exchange

Tauscht das Einmal-Ticket aus dem Callback gegen Tokens. Ist TOTP aktiv, antwortet der Server zuerst mit MFA_REQUIRED; das Ticket bleibt dann bis zu seinem Ablauf (5 Minuten) gültig. Tickets aus einer App-Anmeldung lassen sich nur mit dem passenden appCodeVerifier einlösen (sonst OAUTH_APP_VERIFIER_INVALID); das Gerät wird dann als mobile registriert.

Request Body

application/json
  1. body
ticket*string
Length20 <= length <= 200
totpCode?|
Match^\\d{6}$
appCodeVerifier?|

Pflicht für Tickets aus einer App-Anmeldung.

Match^[A-Za-z0-9._~-]{43,128}$
deviceId?|
Lengthlength <= 200
deviceName?|
Lengthlength <= 120
platform?|
Lengthlength <= 64
appVersion?|
Lengthlength <= 64

Response Body

Erfolgreich angemeldet

application/json
  1. response
accessToken*string
refreshToken*string
expiresIn*integer
tokenType?string
user*
Example Request
curl -X POST 'https://example.com/api/v1/auth/oauth/exchange' \  -H 'Content-Type: application/json' \  -d '{  "ticket": "stringstringstringst"}'
Example Response
{  "accessToken": "string",  "refreshToken": "string",  "expiresIn": 0,  "tokenType": "Bearer",  "user": {    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",    "email": "user@example.com",    "loginName": "string",    "displayName": "string",    "firstName": "string",    "lastName": "string",    "role": "user",    "status": "active",    "locale": "de",    "timezone": "Europe/Berlin",    "themeMode": "light",    "totpEnabled": true,    "totpRequired": true,    "passkeyEnabled": true,    "hasPassword": true,    "forcePasswordChange": true,    "onboardingCompleted": true,    "lastLoginAt": "2019-08-24T14:15:22Z",    "createdAt": "2019-08-24T14:15:22Z",    "updatedAt": "2019-08-24T14:15:22Z"  }}

List own linked accounts

GET
/auth/oauth/identities

Authorization

bearerAuth
headerAuthorizationBearer <JWT>

Response Body

Verknüpfte Konten

application/json
  1. response
[index: integer]?
Example Request
curl -X GET 'https://example.com/api/v1/auth/oauth/identities'
Example Response
[  {    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",    "provider": "google",    "email": "string",    "displayName": "string",    "lastUsedAt": "2019-08-24T14:15:22Z",    "createdAt": "2019-08-24T14:15:22Z"  }]
DELETE
/auth/oauth/identities/{id}

Schlägt mit LAST_LOGIN_METHOD (409) fehl, wenn das Konto weder ein Passwort noch einen Passkey oder ein weiteres verknüpftes Konto hat.

Authorization

bearerAuth
headerAuthorizationBearer <JWT>

Path Parameters

id*string
Formatuuid

Response Body

Verknüpfung getrennt

Example Request
curl -X DELETE 'https://example.com/api/v1/auth/oauth/identities/497f6eca-6276-4993-bfeb-53cbbbba6f08'
Example Response
Empty