# OAuth 2.0 API-Dokumentation

<span class="custom-button red-button">Gen. 24 Enterprise</span>

Ab **Build 7076** ist der schreibende und lesende Zugriff über die GraphQL-Schnittstelle in microtech büro+ möglich. Voraussetzung ist eine Gen. 24 Enterprise.

**Notwendigkeit der GraphQL-Authentifizierung für Benutzer**

Im Bereich Automatisierungs-Dienste ist unter Registerkarte: INFORMATIONEN - BENUTZER - BENUTZER VERWALTEN in den jeweiligen Benutzer-Datensätzen auf dem Register: FIRMENVORGABEN das Kennzeichen: "Zugriff über GraphQL erlaubt" verfügbar. Nur wenn dieses Kennzeichen aktiviert ist, ist der Benutzer berechtigt, über die Schnittstelle auf Daten zuzugreifen.

![](https://assets.hilfe.microtech.de/bilder/18_graphql/oauthapidoku_1.png)

!!! info "Info"

    Wird das Kennzeichen: "Zugriff über GraphQL erlaubt gesetzt", wird auch automatisch das Kennzeichen: "Benutzer kann sich immer anmelden" gesetzt, da dies eine Voraussetzung für den Zugriff per GraphQL ist.

## 1. Einführung

### 1.1. Was ist OAuth 2.0?

OAuth 2.0 ist ein branchenübliches Autorisierungsprotokoll, das es Anwendungen ermöglicht, sicheren und eingeschränkten Zugriff auf Benutzerkonten zu erhalten, ohne dass Passwörter direkt geteilt werden müssen.

Der wesentliche Vorteil liegt in der Trennung von Authentifizierung und Autorisierung: Benutzer authentifizieren sich direkt bei der microtech Software und erteilen dann gezielt Berechtigungen an Drittanwendungen.

### 1.2. OAuth 2.0 in der microtech Software

Die OAuth 2.0-Implementation in der microtech Software bietet:

- **Sichere API-Zugriffe**: Externe Anwendungen können sicher auf die GraphQL-API zugreifen
- **Token-Verwaltung**: Automatische Token-Rotation und Erneuerungsmechanismen
- **PKCE-Pflicht**: Maximale Sicherheit durch obligatorisches PKCE (Proof Key for Code Exchange) für alle Clients
- **Duale Authentifizierung**: Session-basiert für Browser, Token-basiert für APIs

Die Implementation folgt den Standards RFC 6749, RFC 7636, RFC 7009, RFC 6750 und RFC 9700 (OAuth 2.0 Security Best Current Practice).

### 1.3. Authentifizierung vs. Autorisierung

Die OAuth 2.0-Implementation in der microtech Software dient primär der **Authentifizierung** (Wer ist der Benutzer?). Die **Autorisierung** (Was darf der Benutzer?) erfolgt durch die gewohnte Berechtigungsstruktur in der microtech Software.

Diese Architektur bedeutet:
- OAuth identifiziert den Benutzer
- Die microtech Software prüft die tatsächlichen Berechtigungen bei jeder Operation
- Änderungen an Benutzerrechten werden sofort wirksam
- Der OAuth-Scope `graphql` gewährt nur API-Zugang, nicht die Berechtigungen selbst

### 1.4. Voraussetzungen

- microtech Software mit aktivierter GraphQL-Schnittstelle
- HTTPS-fähiger Server (SSL-Zertifikat erforderlich)
- Administrative Rechte zur Einrichtung von Anwendungen
- Grundkenntnisse in OAuth 2.0 und REST-APIs

### 1.5. HTTPS und Domain-Anforderungen

#### Warum HTTPS und Domain-Namen zwingend erforderlich sind


!!! warning "Beachten Sie"

    OAuth 2.0 in der microtech Software funktioniert ausschließlich mit:

    *    **HTTPS-Protokoll** (verschlüsselte Verbindung)

    *    **Gültigen Domain-Namen** (keine IP-Adressen!)

#### Was funktioniert NICHT:

| ❌ Falsch | Problem |
|-----------|---------|
| `http://server.domain.de/...` | Unverschlüsselt - nicht erlaubt |
| `https://192.168.1.100/...` | IP-Adresse - technisch nicht möglich |
| `https://localhost/...` | Localhost - nicht im Zertifikat enthalten |

#### Was funktioniert:

| ✅ Richtig | Beschreibung |
|------------|--------------|
| `https://erp.firma.de/...` | Öffentliche Domain mit HTTPS |
| `https://test.firma.internal/...` | Interne Domain mit HTTPS (empfohlen) |
| `https://dev.firma.lan/...` | Netzwerk-Domain mit HTTPS |

#### Warum IP-Adressen nicht funktionieren:

1. **Windows HTTP-Server akzeptiert keine HTTPS-Verbindungen auf IP-Adressen**
   - SSL-Zertifikate sind an Domain-Namen gebunden
   - Verbindungsaufbau schlägt bereits auf System-Ebene fehl

2. **OAuth 2.0 Standards verbieten IP-Adressen**
   - Redirect URIs mit IP-Adressen werden abgelehnt
   - Sicherheitsstandard ohne Ausnahmen

3. **Fehlerhafte Redirect URI**
   - OAuth prüft auf exakte Übereinstimmung
   - Domain in der Anwendung ≠ IP im Aufruf = Fehler

#### Lösung für Testumgebungen:

Falls kein DNS verfügbar ist, kann die lokale Hosts-Datei verwendet werden:
```
# Windows: C:\Windows\System32\drivers\etc\hosts (als Administrator bearbeiten)
192.168.1.100  test.internal
```
Danach funktioniert: `https://test.internal/...`

**Empfehlung für interne Domains:**
- **Verwenden Sie `.internal`** - seit Juli 2024 von ICANN offiziell für private Netzwerke reserviert
- **Vermeiden Sie `.local`** - reserviert für mDNS (RFC 6762)
- **Alternativen:** `.lan`, `.home`, `.corp`, `.private` (nicht offiziell reserviert, könnten zukünftig Konflikte verursachen)

**Hinweis:** Die Zertifikatsverwaltung erfolgt über BpConfig. Dort können Sie Zertifikate registrieren oder selbstsignierte erstellen.

**Zusammenfassung:** IP-basierter Zugriff ist technisch nicht möglich. Verwenden Sie immer Domain-Namen mit HTTPS.

### 1.6. Authentifizierungsmethoden

| Methode | Verwendung | Gültigkeit | Transport |
|---------|------------|------------|-----------|
| **Session** | Browser, Entwickler-Werkzeuge | 600 s (= 10 Min, auto-verlängernd) | HttpOnly Cookie |
| **Bearer Token** | Externe Anwendungen, APIs | 3600 s (= 1 Std, konfigurierbar) | Authorization Header |

Sessions haben Vollzugriff inklusive GraphQL (wenn Benutzer berechtigt), OAuth-Tokens nur explizit gewährte Scopes.

!!! tip "Tipp"

    Wir stellen Ihnen den **microtech Bearer Token Generator** unter folgender Seite zur Verfügung: 
  
    [OAuth 2.0 Bearer Token Generator für microtech büro+](../18_graphql/graphqlbearertokengenerator.md)

### 1.7. Anmeldemethoden

Die microtech Software unterstützt mehrere Anmeldemethoden:

| Methode | Beschreibung | Voraussetzung |
|---------|--------------|---------------|
| **Benutzername/Passwort** | Klassische Anmeldung mit microtech-Zugangsdaten | Benutzer in microtech angelegt |
| **Mit Windows anmelden (SSO)** | Automatische Anmeldung mit Windows-Domänenkonto | Windows-Auth für Benutzer aktiviert |

#### Benutzername/Passwort

Die klassische Anmeldung mit Benutzername und Passwort folgt denselben Regeln wie beim Öffnen eines Mandanten in der microtech Software:

- **microtech büro+ Passwort hinterlegt**: Anmeldedaten müssen mit denen in der Software hinterlegten Anmeldedaten übereinstimmen.
- **Windows-Authentifizierung aktiviert**: Benutzername muss mit dem bei in microtech büro+ hinterlegtem Benutzernamen sowie mit dem Windows-Benutzernamen (ohne Domänen-Präfix) übereinstimmen, Passwort muss mit dem Windows-Domänenpasswort übereinstimmen. Die Validierung erfolgt gegen die Domäne des BpServer-Rechners.
- **Beide Optionen aktiv**: Prüfung gegen microtech büro+ Passwort. Wenn nicht erfolgreich, Prüfung gegen Windows-Domänenpasswort.

#### Mit Windows anmelden (SSO)

Die Option "Mit Windows anmelden (SSO)" startet eine Anmeldung mit dem aktuellen Windows-Domänenkonto. Diese Option muss im Anmeldeformular explizit ausgewählt werden.

!!! warning "Beachten Sie"

    Die SSO-Option wird im Anmeldeformular immer angezeigt, da zu diesem Zeitpunkt noch nicht bekannt ist, welcher Benutzer sich anmelden möchte. Ob die Anmeldung erfolgreich ist, hängt von der Benutzerkonfiguration ab.

**Funktionsweise:**

*    Verwendet das NTLM/Negotiate-Protokoll (Kerberos mit NTLM-Fallback)

*    Der Browser wird aufgefordert, die Windows-Anmeldedaten zu senden

*    Der Benutzername wird in der microtech Software gesucht (ohne Domänen-Präfix)

**Browser-Konfiguration:**

Ob die Anmeldedaten automatisch gesendet werden, hängt von der Browser-Konfiguration ab:

*    Der Browser muss der Domain vertrauen (Intranet-Zone oder explizit konfiguriert)

*    Bei nicht vertrauenswürdigen Domains zeigt der Browser möglicherweise einen Anmeldedialog

**Voraussetzungen für erfolgreiche SSO-Anmeldung:**

*    Der Benutzer muss in der microtech Software angelegt sein

*    Die Option "Windows-Authentifizierung" muss für den Benutzer aktiviert sein

*    Der Windows-Benutzername muss mit dem Anmeldenamen in microtech übereinstimmen

*    Client und BpServer sollten sich in derselben oder in vertrauenswürdigen Domänen befinden

!!! warning "Beachten Sie"

    "Mit Windows anmelden (SSO)" ist **nicht** identisch mit der Option "Mit Microsoft-Konto anmelden". Die SSO-Funktion nutzt die lokale Windows-Domäne (Active Directory), nicht Microsoft-Cloud-Dienste wie Azure AD oder Microsoft 365.

### 1.8. Basis-URLs und Endpunkte

**Basis-URL:**
```
https://<server.domain>/microtech/erp/<graphql-server-pfad>/
```

**OAuth-Endpunkte:**

| Endpunkt | Beschreibung |
|----------|--------------|
| `/authorize` | Startet OAuth-Flow, zeigt Login und Consent |
| `/token` | Tauscht Codes gegen Tokens, erneuert Tokens |
| `/revoke` | Widerruft Tokens explizit |
| `/login` | Browser-Login (Benutzername/Passwort oder Windows SSO) |
| `/logout` | Beendet Browser-Session |

**API-Endpunkt:**

| Endpunkt | Beschreibung |
|----------|--------------|
| `/graphql/v1` | GraphQL-API für Datenzugriff |

**HTTP-Methoden & Content Types:**

| Endpunkt | Methode | Content-Type / Beschreibung |
|----------|---------|------------------------------|
| `/authorize` | GET | Parameter in Query-String |
| | POST | `application/x-www-form-urlencoded` |
| `/token` | POST | `application/x-www-form-urlencoded` |
| `/revoke` | POST | `application/x-www-form-urlencoded` |
| `/login` | GET | HTML-Formular (Anmeldeseite) |
| `/logout` | GET | HTML-Seite (Logout-Bestätigung) |
| `/graphql/v1` | GET | HTML (interaktive Oberfläche, nur mit Session) |
| | POST | `application/json` (API-Zugriff) |

### 1.9. Endpunkt-Authentifizierung

| Endpunkt | Authentifizierungsmethode | Verhalten ohne Authentifizierung |
|----------|---------------------------|-----------------------------------|
| `/authorize` | Session oder Basic Auth | Anmeldeformular, Parameter erhalten |
| `/token` | Client-Anmeldedaten | 401 Unauthorized (JSON) |
| `/revoke` | Client-Anmeldedaten | 401 Unauthorized (JSON) |
| `/login` | Formular oder Windows SSO | Anmeldeformular |
| `/logout` | Optional: Session-Cookie | Logout-Bestätigung |
| `/graphql/v1` | Bearer oder Session | 401 (Bearer) oder Anmeldeformular |

!!! warning "Beachten Sie"

    *    Bei `/graphql/v1` hat Bearer Token Vorrang - kein Rückfall auf Session bei ungültigem Bearer.

    *    **Hinweis zu `/authorize`:** Falls Basic-Authentifizierung verwendet wird, erfolgt diese über `Authorization: Basic <base64(username:password)>` für die Benutzer-Authentifizierung.

## 2. Anwendung einrichten (OAuth-Client)

### 2.1. Navigation zur Anwendungsverwaltung

**Pfad:** Meine Firma → Überblick → Systemeinstellungen → Anwendungen verwalten

Die Anwendungsverwaltung öffnet sich in einem neuen Tab und zeigt alle registrierten Anwendungen.

### 2.2. Neue Anwendung erstellen

#### Schritt 1: Übersicht
Die Tabellenansicht zeigt:
- **Bezeichnung**: Name der Anwendung
- **Client ID**: Eindeutige Kennung (automatisch generiert)
- **Benutzernummer**: Verknüpfter microtech-Benutzer (bei vertraulichen Anwendungen)
- **Client-Typ**: Öffentlich oder Vertraulich
- **Redirect URI**: Erste konfigurierte Rückruf-URL

#### Schritt 2: Neue Anwendung anlegen
Klicken Sie auf **Neu** im Menüband.

#### Schritt 3: Anwendung konfigurieren

**Grundeinstellungen:**

| Feld | Beschreibung | Erforderlich |
|------|--------------|--------------|
| **Bezeichnung** | Name der Anwendung (wird im Zustimmungsdialog angezeigt) | Ja |
| **Client-Typ** | Öffentlich (Public) oder Vertraulich (Confidential) | Ja |
| **Benutzer** | microtech-Benutzer für Client Credentials Grant | Nur bei Vertraulich |

**Client-Typen im Detail:**

- **Öffentlicher Client (Public Client)**: 
  - Für Browser-Anwendungen, Mobile Apps, Desktop-Anwendungen
  - Kein Secret erforderlich
  - Automatische Token-Rotation bei Erneuerung
  
- **Vertraulicher Client (Confidential Client)**:
  - Für Server-Anwendungen und Backend-Services
  - Secret erforderlich und muss sicher gespeichert werden
  - Optionale Token-Rotation
  - Unterstützt Client Credentials Grant (nur mit verknüpftem microtech-Benutzer)

**Technische Einstellungen:**

| Feld | Beschreibung | Standard | Konfigurierbar |
|------|--------------|----------|----------------|
| **Client-ID** | 512-Bit Zufallswert, Base64URL | Auto-generiert | Nein |
| **Client-Secret** | 512-Bit Zufallswert, Base64URL | Auto-generiert | Nein |
| **Redirect URIs** | Eine pro Zeile, exakte Übereinstimmung | - | Ja |
| **Code-Gültigkeit** | Authorization Code Lebensdauer (Minuten) | 5 Min (= 300 s) | Ja |
| **Access-Token** | API-Zugriffsdauer (Minuten) | 60 Min (= 3600 s) | Ja |
| **Refresh-Token** | Gültigkeit für Token-Erneuerung (Minuten) | 43200 Min (= 30 Tage = 2592000 s) | Ja |

**Scopes (Checkboxen):**

| Scope | Bedeutung | Wenn deaktiviert |
|-------|-----------|------------------|
| **Autorisierungscodes anfordern** | Ermöglicht Authorization Code Flow | Nur Client Credentials Grant möglich |
| **Zugriffstokens anfordern** | Kann Access Tokens erhalten | Anwendung funktioniert nicht |
| **Aktualisierungstokens anfordern** | Erhält Refresh Tokens | Keine Refresh Token-Erneuerung möglich |
| **GraphQL-API Zugriff** | Tokens können API nutzen | API-Zugriff verweigert (401) |

#### Schritt 4: Anmeldedaten sichern

!!! danger "Beachten Sie"

    Client-ID und Secret sind bereits ausgefüllt. Kopieren Sie beide Werte mit den Kopier-Buttons **vor** dem Speichern! Das Secret wird danach nur als Hash gespeichert und kann nicht wiederhergestellt werden.

#### Schritt 5: Speichern
Nach dem Sichern der Anmeldedaten: **Speichern & schließen**

### 2.3. Anwendungen verwalten

#### Anwendung bearbeiten
- Doppelklick oder Auswahl + **Ändern**
- Client-ID und Secret sind nicht änderbar
- Alle anderen Einstellungen können angepasst werden

#### Secret erneuern
1. Anwendung zur Bearbeitung öffnen
2. Im Menüband: Bereich **Secret** → **Neu**
3. Neues Secret sofort kopieren
4. Speichern und schließen
5. Alle externen Systeme mit neuem Secret aktualisieren

**Hinweis:** Bestehende Tokens bleiben bis zu ihrem normalen Ablauf gültig.

#### Anwendung löschen
- Auswahl + **Löschen** im Menüband
- **Warnung:** Alle aktiven Tokens werden sofort ungültig!
- Gelöschte Anwendungen können nicht wiederhergestellt werden
- Client-ID kann nicht wiederverwendet werden

#### Anwendung sperren
- Auswahl + **Sperren** im Menüband
- **Wirkung:** Alle bestehenden Tokens dieser Anwendung werden temporär ungültig
- Token werden **nicht gelöscht**, sondern nur blockiert
- Nach Entsperren sind die Tokens wieder gültig (sofern nicht abgelaufen)
- Neue Token-Anfragen werden während der Sperrung abgelehnt

**Unterschied zwischen Sperren und Scope-Entfernung:**
- **Anwendung sperren**: Temporäre Blockade aller Token-Operationen
- **Scope "Autorisierungscodes anfordern" entfernen**: Verhindert nur neue Authorization Codes, bestehende Tokens bleiben gültig

### 2.4. Beispielkonfigurationen

**Öffentliche Anwendung (Mobile App):**
```
Bezeichnung: Mobile Verkaufs-App
Typ: Öffentlich
Redirect URI: com.microtech.sales://callback
Scopes: Alle aktiviert
Token-Gültigkeit: Standard
```

**Vertrauliche Anwendung (Server-Integration):**
```
Bezeichnung: E-Commerce Backend
Typ: Vertraulich
Benutzer: api-benutzer (microtech-Benutzer)
Redirect URI: https://shop.example.com/oauth/callback
Scopes: Alle aktiviert
Access-Token: 30 Min (= 1800 s)
Refresh-Token: 10080 Min (= 7 Tage = 604800 s)
```

## 3. OAuth 2.0 Flows

**Welchen Flow wann verwenden?**

| Flow | Client-Typ | Verwendungszweck |
|------|------------|------------------|
| **Authorization Code mit PKCE** | Öffentlich & Vertraulich | Anwendung agiert im Namen eines Endbenutzers |
| **Client Credentials** | Nur Vertraulich | Anwendung agiert eigenständig (Machine-to-Machine) |
| **Refresh Token** | Öffentlich & Vertraulich | Token-Erneuerung ohne Benutzer-Interaktion |

### 3.1. Authorization Code Flow mit PKCE

PKCE (Proof Key for Code Exchange) ist verpflichtend für alle Anwendungen, sowohl öffentliche als auch vertrauliche. Die `redirect_uri` muss exakt (bitgenau) mit einer der registrierten URIs übereinstimmen.

#### Schritt 1: PKCE-Werte generieren

- **Code Verifier**: Zufälliger String mit 43-128 Zeichen
  - Erlaubte Zeichen: `[A-Z] [a-z] [0-9] - . _ ~`
  - Beispiel: `dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk`
  
- **Code Challenge**: SHA256-Hash des Verifiers
  - Formel: `BASE64URL(SHA256(code_verifier))`
  - Ohne Padding (= Zeichen entfernen)

#### Schritt 2: Autorisierungsanfrage

**GET-Variante:**
```
GET https://<server>/microtech/erp/<graphql-server-pfad>/authorize?
  response_type=code&
  client_id=<CLIENT_ID>&
  redirect_uri=<REDIRECT_URI>&
  code_challenge=<CHALLENGE>&
  code_challenge_method=S256&
  scope=graphql&
  state=<RANDOM_STATE>
```

**POST-Variante (identische Parameter im Body):**
```http
POST /microtech/erp/<graphql-server-pfad>/authorize HTTP/1.1
Host: <server>
Content-Type: application/x-www-form-urlencoded

response_type=code&
client_id=<CLIENT_ID>&
redirect_uri=<REDIRECT_URI>&
code_challenge=<CHALLENGE>&
code_challenge_method=S256&
scope=graphql&
state=<RANDOM_STATE>
```

**Parameter:**
| Parameter | Pflicht | Beschreibung |
|-----------|---------|--------------|
| `response_type` | Ja | Muss `code` sein |
| `client_id` | Ja | Ihre Client-ID |
| `redirect_uri` | Ja | Muss exakt mit einer registrierten URI übereinstimmen |
| `code_challenge` | Ja | PKCE Challenge |
| `code_challenge_method` | Ja | Muss `S256` sein |
| `scope` | Nein | Angeforderte Scopes (z.B. `graphql`) |
| `state` | Empfohlen | CSRF-Schutz |

!!! warning "Beachten Sie"

    **Exact Match**

    Die `redirect_uri` muss **bitgenau** mit einer der registrierten URIs übereinstimmen (exakte Zeichenketten-Übereinstimmung, inklusive Schema, Host, Port, Pfad und Query-Parameter).

#### Schritt 3: Benutzer-Interaktion

1. **Anmeldung** (falls nicht angemeldet)
   - OAuth-Parameter werden automatisch gespeichert und nach Anmeldung wiederhergestellt
   - Anmeldung möglich via Benutzername/Passwort oder "Mit Windows anmelden (SSO)"
   
2. **Zustimmungsdialog** zeigt:
   - Name der anfragenden Anwendung
   - Angeforderte Scopes
   - Aktuell angemeldeter Benutzer
   - "Nicht Sie?" Link für Benutzerwechsel
   
3. **Benutzerentscheidung**: Zustimmung oder Ablehnung

**Antworten:**
- Erfolg: `redirect_uri?code=<CODE>&state=<STATE>`
- Ablehnung: `redirect_uri?error=access_denied&state=<STATE>`
- Fehler: `redirect_uri?error=<ERROR>&error_description=<DESC>&state=<STATE>`

#### Schritt 4: Token-Austausch

**Vertrauliche Anwendung:**
```http
POST /token HTTP/1.1
Authorization: Basic <BASE64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=<AUTHORIZATION_CODE>&
redirect_uri=<REDIRECT_URI>&
code_verifier=<VERIFIER>
```

!!! warning "Beachten Sie"

    Die `redirect_uri` muss exakt mit der URI übereinstimmen, die in der Autorisierungsanfrage verwendet wurde.

**Öffentliche Anwendung:**
```http
POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=<AUTHORIZATION_CODE>&
redirect_uri=<REDIRECT_URI>&
code_verifier=<VERIFIER>&
client_id=<CLIENT_ID>
```

!!! warning "Beachten Sie"

    Die `redirect_uri` muss exakt mit der URI übereinstimmen, die in der Autorisierungsanfrage verwendet wurde.

**Erfolgsantwort:**
```json
{
  "access_token": "vEQzaMu0i-E-7QbDSdeI...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "rW31CSnakl9kwuUB2XLC...",
  "refresh_expires_in": 2592000,
  "scope": "graphql",
  "refresh_scope": "request_access_token request_refresh_token graphql"
}
```

**OAuth Scope-Namen:**

| Scope-Name | Typ | Bedeutung |
|------------|-----|-----------|
| `request_code` | Intern | Kann Authorization Codes anfordern (nur Session-Tokens) |
| `request_access_token` | Intern | Kann Access Tokens anfordern |
| `request_refresh_token` | Intern | Kann Refresh Tokens anfordern |
| `graphql` | Client | Zugriff auf GraphQL-API |

**Scope-Verhalten in Responses:**
- `scope`: Enthält nur **Client-Scopes** des Access Tokens (z.B. `"graphql"`)
- `refresh_scope`: Enthält **Client-Scopes + interne Scopes** des Refresh Tokens (z.B. `"request_access_token request_refresh_token graphql"`)
- Mehrere Scopes werden **space-getrennt** zurückgegeben
- Interne Scopes steuern, welche Token-Operationen möglich sind

**Hinweise zu nicht-standard Feldern:**
- `refresh_expires_in`: Gültigkeit des Refresh Tokens in Sekunden (Standard-OAuth spezifiziert keine Refresh Token Lebensdauer-Sichtbarkeit)
- `scope`: Tatsächliche Berechtigungen des Access Tokens
- `refresh_scope`: Maximale Scopes für zukünftige Token-Erneuerungen

!!! danger "Beachten Sie"

    Authorization Codes sind nur **einmal verwendbar**. Wiederverwendung führt zur sofortigen Sperrung aller abgeleiteten Tokens (Security Breach).

### 3.2. Client Credentials Grant

Nur für vertrauliche Anwendungen mit verknüpftem microtech-Benutzer. Dieser Benutzer bestimmt die Berechtigungen in der microtech Software.

**Wann welchen Flow verwenden (Vertrauliche Clients)?**
- **Authorization Code Flow**: Wenn die Anwendung im Namen eines **Endbenutzers** agiert (z.B. Web-Portal wo sich verschiedene Benutzer anmelden)
- **Client Credentials Grant**: Wenn die Anwendung **eigenständig** agiert (z.B. nächtliche Synchronisation, automatisierte Prozesse)

**Anfrage:**
```http
POST /token HTTP/1.1
Authorization: Basic <BASE64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&
scope=graphql
```

**Antwort:**
```json
{
  "access_token": "kU9QpgL6stOLX9RNBkLA...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "graphql"
}
```

!!! warning "Beachten Sie"

    Client Credentials Grant gibt **niemals** ein Refresh Token zurück (RFC 6749 Section 4.4.3). Die Anwendung kann sich jederzeit mit Client-ID und Secret neu authentifizieren.

### 3.3. Token-Erneuerung (Refresh Token Grant)

**Laufzeit bei Rotation:** Neu ausgegebene Refresh Tokens erhalten die volle im Anwendungsdatensatz konfigurierte Laufzeit (Sliding TTL).

**Fehlerbehandlung:** Bei Fehlverwendung (z.B. Wiederverwendung eines bereits rotierten Refresh Tokens) erfolgt sofortige Invalidierung der gesamten Token-Kette. Recovery erfordert vollständige Neuauthentifizierung.

**Vertrauliche Anwendung:**
```http
POST /token HTTP/1.1
Authorization: Basic <BASE64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&
refresh_token=<REFRESH_TOKEN>&
scope=<OPTIONAL_RESTRICTED_SCOPE>
```

**Öffentliche Anwendung:**
```http
POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&
refresh_token=<REFRESH_TOKEN>&
client_id=<CLIENT_ID>&
scope=<OPTIONAL_RESTRICTED_SCOPE>
```

**Scope-Verhalten bei Erneuerung:**
- Ohne `scope` Parameter: Access Token erhält alle Scopes des Refresh Tokens
- Mit `scope` Parameter: Access Token erhält nur die angeforderten Scopes (muss Teilmenge der Refresh Token Scopes sein)
- **Refresh Token behält immer seine ursprünglichen Scopes** (vom Authorization Code)

**Token-Rotation:**
- **Öffentliche Anwendungen**: Refresh Token rotiert automatisch - das alte wird ungültig
- **Vertrauliche Anwendungen**: Optional via `rotate_refresh_token=true`

**Antwort mit Rotation:**
```json
{
  "access_token": "neues_access_token...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "neues_refresh_token...",
  "scope": "graphql",
  "refresh_scope": "request_access_token request_refresh_token graphql"
}
```

**Bedeutung der Scope-Felder:**
- `scope`: Tatsächliche Scopes des Access Tokens (kann eingeschränkt sein wenn bei Anfrage angegeben)
- `refresh_scope`: Maximale Scopes des Refresh Tokens für zukünftige Erneuerungen (unverändert vom Original)

!!! warning "Beachten Sie"

    **Wichtig bei Token-Rotation:** 

    *    Das neue Refresh Token muss sofort gespeichert werden

    *    Das alte Refresh Token wird ungültig

    *    Wiederverwendung eines rotierten Tokens führt zur Sperrung der gesamten Token-Kette

### 3.4. Token-Widerruf

Der `/revoke` Endpunkt implementiert RFC 7009 mit zusätzlichen optionalen Erweiterungen.

#### 3.4.1. Standard-Widerruf (RFC 7009)

**Vertrauliche Anwendung:**
```http
POST /revoke HTTP/1.1
Authorization: Basic <BASE64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

token=<TOKEN_TO_REVOKE>
```

**Öffentliche Anwendung:**
```http
POST /revoke HTTP/1.1
Content-Type: application/x-www-form-urlencoded

token=<TOKEN_TO_REVOKE>&
client_id=<CLIENT_ID>
```

**Antwort:** Immer HTTP 200 OK (auch wenn Token nicht existiert oder bereits ungültig)

**Widerruf-Auswirkungen nach Token-Typ:**

*    **Session Token**: Beendet die Browser-Session und alle abgeleiteten Tokens

*    **Authorization Code**: Alle abgeleiteten Access/Refresh Tokens werden ungültig

*    **Access Token**: Nur dieses Token wird ungültig

*    **Refresh Token**: Token und alle damit erneuerten Tokens werden ungültig

#### 3.4.2. Erweiterte Parameter (Optional)

**Graceful-Parameter:**

Der `graceful` Parameter ist eine optionale Erweiterung (RFC 7009 erlaubt zusätzliche Parameter):

```http
POST /revoke HTTP/1.1
Content-Type: application/x-www-form-urlencoded

token=<TOKEN_TO_REVOKE>&
client_id=<CLIENT_ID>&
graceful=true
```

| Parameter-Wert | Verhalten |
|----------------|-----------|
| `graceful=true` | Token läuft sofort ab, **ohne** andere Tokens zu beeinflussen |
| `graceful=false` oder weggelassen | Token wird widerrufen, abgeleitete Tokens werden ungültig (Standard) |

**Anwendungsfälle für graceful=true:**

*    Ein Gerät ausloggen ohne andere Geräte zu beeinflussen

*    Kontrollierte Token-Rotation ohne Unterbrechung anderer Sessions

*    Refresh Token beenden ohne aktive Access Tokens zu invalidieren

#### 3.4.3. Alternative Authentifizierung

Zusätzlich zur Client-Authentifizierung kann der Endpunkt auch mit einer aktiven Session verwendet werden:

```http
POST /revoke HTTP/1.1
Cookie: microtech_session=<SESSION_TOKEN>
Content-Type: application/x-www-form-urlencoded

token=<TOKEN_TO_REVOKE>
```

Dies ermöglicht Benutzern, ihre eigenen Tokens über die Web-Oberfläche zu verwalten. Das Token muss dem authentifizierten Benutzer oder Client gehören.

### 3.5. Logout

Beendet die aktuelle Browser-Session.

```http
GET /logout HTTP/1.1
Cookie: microtech_session=<SESSION_TOKEN>
```

**Antwort:** HTML-Seite mit Logout-Bestätigung.

**Logout-Verhalten:**

*    **Client-seitig:** Session-Cookie wird gelöscht

*    **Server-seitig:** Session wird als abgelaufen markiert und kann nicht mehr verwendet werden

*    **OAuth-Tokens:** Bereits ausgestellte Access und Refresh Tokens bleiben gültig und funktionsfähig

**Sicherheitshinweis:** Nach dem Logout ist das Session-Token sofort ungültig, selbst wenn es vorher kopiert wurde. Autorisierte Anwendungen mit OAuth-Tokens können jedoch weiterhin auf die API zugreifen.

## 4. GraphQL-API verwenden

### 4.1. API-Aufruf mit Bearer Token

```http
POST /graphql/v1 HTTP/1.1
Host: <server.domain>
Authorization: Bearer <ACCESS_TOKEN>
Content-Type: application/json

{
  "query": "{ tblArtikel { rowsRead { fldArtNr } } }"
}
```

### 4.2. Authentifizierungs-Priorität

Der GraphQL-Endpunkt akzeptiert zwei Authentifizierungsmethoden:

1. **Bearer Token** (für externe Anwendungen)
   - Hat Vorrang wenn `Authorization: Bearer` Header vorhanden
   - Bei ungültigem Token: 401 Unauthorized
   - **Kein Rückfall auf Session** bei Fehler

2. **Session Cookie** (für Browser-Zugriff)
   - Wird verwendet wenn kein Bearer Header vorhanden
   - Bei fehlender Session: Anmeldeformular

### 4.3. Berechtigungen

Die tatsächlichen Datenzugriffsrechte werden durch die Berechtigungen des authentifizierten Benutzers in der microtech Software bestimmt, nicht durch OAuth-Scopes.

## 5. Sicherheit

### 5.1. PKCE (Proof Key for Code Exchange)
- **Verpflichtend** für alle Anwendungen (öffentlich und vertraulich)
- Nur S256 (SHA256) unterstützt, plain wird abgelehnt
- Verifier: 43-128 Zeichen
- Schützt vor Code-Injection-Angriffen

### 5.2. Single-Use-Erkennung
- **Authorization Codes**: Nur einmal verwendbar (Standard: 300 s = 5 Min gültig, konfigurierbar)
- **Rotierende Refresh Tokens**: Nur einmal verwendbar
- **Security Breach Response**: Komplette Token-Kette wird bei Wiederverwendung invalidiert

### 5.3. Token-Rotation
- **Automatisch** für öffentliche Anwendungen
- **Optional** für vertrauliche Anwendungen (`rotate_refresh_token=true`)
- Altes Token wird bei Rotation sofort ungültig
- Neu ausgegebene Refresh Tokens erhalten die volle konfigurierte Laufzeit
- Schützt vor Token-Diebstahl

### 5.4. Rate Limiting
- 2 freie Fehlversuche pro IP
- Feste Verzögerung für Versuche 3-25 (Endpunkt-spezifisch)
- 300 s (= 5 Min) Blockade nach 25 Fehlversuchen
- Erfolgreiche Anfragen setzen den Fehlversuchs-Zähler zurück
- Endpunkt-spezifische Verzögerungen:
  - `/authorize`: 100ms zwischen Anfragen
  - `/token`, `/revoke`: 200ms zwischen Anfragen

### 5.5. Session-Verwaltung
- **Gültigkeit**: 600 s (= 10 Min) initial
- **Auto-Verlängerung**: Bei jeder Verwendung
- **Cookie-Eigenschaften**: HttpOnly, SameSite=Lax, Secure (bei HTTPS)
- **Berechtigungen**: Vollzugriff für authentifizierte Benutzer

### 5.6. Formular-Sicherheit
- HMAC-SHA256 Signatur auf allen Formularen
- 300 s (= 5 Min) Gültigkeit
- Zeitstempel-Validierung
- Parameter-Erhaltung bei Anmelde-Unterbrechung

### 5.7. Token-Formate
- Access und Refresh Tokens sind opaque (512-Bit kryptographisch sicher)
- Base64URL-kodiert für Transport
- Ausschließlich zur internen Verwendung
- Keine Introspection-Endpoints verfügbar

## 6. Fehlerbehandlung

### 6.1. OAuth-Fehlercodes

| Fehlercode | HTTP Status | Bedeutung |
|------------|-------------|-----------|
| `invalid_request` | 400 | Fehlende oder ungültige Parameter |
| `invalid_client` | 401 | Client-Authentifizierung fehlgeschlagen |
| `invalid_grant` | 400 | Authorization Code oder Token ungültig/abgelaufen |
| `unauthorized_client` | 400 | Client nicht für diesen Grant Type autorisiert |
| `unsupported_grant_type` | 400 | Grant Type nicht unterstützt |
| `invalid_scope` | 400 | Ungültiger oder nicht erlaubter Scope |
| `access_denied` | 400 | Benutzer hat Zugriff verweigert |
| `unsupported_response_type` | 400 | Response Type nicht unterstützt |
| `invalid_token` | 401 | Bearer Token ungültig (RFC 6750) |
| `server_error` | 500 | Interner Serverfehler |
| `temporarily_unavailable` | 503 | Service temporär nicht verfügbar |

### 6.2. Antwort-Formate

**JSON-Fehlerantwort (OAuth-Fehler):**
```json
{
  "error": "invalid_grant",
  "error_description": "The provided authorization grant is invalid, expired, or revoked"
}
```

**401 Unauthorized mit WWW-Authenticate (RFC 6750):**
```http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="GraphQL API"
Content-Type: application/json

{
  "error": "authentication_required",
  "message": "Bearer token is missing, invalid or expired"
}
```

**GraphQL-Berechtigungsfehler (HTTP 200):**
```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": null,
  "errors": [
    {
      "message": "Validation error: Field 'tblGeheim' not found in type 'Query'",
      "extensions": {"code": "VALIDATION_ERROR"}
    }
  ]
}
```

**Hinweis:** Mit gültigem Token erreicht die Anfrage immer den GraphQL-Server (HTTP 200). Berechtigungsprüfungen erfolgen dann auf GraphQL-Ebene:
- **Schema-Validierung:** Nicht erlaubte Felder/Tabellen sind gar nicht im Schema sichtbar
- **Ausführungsfehler:** Fehlende Rechte für spezifische Operationen werden als GraphQL-Fehler zurückgegeben

Ein HTTP 401 erscheint nur bei fehlendem oder ungültigem Bearer Token.

**Umleitungs-Fehler:**
```
https://app.example.com/callback?
  error=access_denied&
  error_description=The%20user%20denied%20access&
  state=<STATE>
```

### 6.3. Rate Limiting Antworten

```http
HTTP/1.1 429 Too Many Requests
Retry-After: 300
Content-Type: application/json

{
  "error": "too_many_requests",
  "error_description": "Rate limit exceeded. Retry after 300 seconds."
}
```

## 7. Token-Lebenszyklus

| Token-Typ | Standard | Konfigurierbar | Verwendung |
|-----------|----------|----------------|------------|
| Authorization Code | 300 s (= 5 Min) | Ja* | Einmaliger Austausch gegen Tokens |
| Access Token | 3600 s (= 1 Std) | Ja* | API-Zugriff via Bearer |
| Refresh Token | 2592000 s (= 30 Tage) | Ja* | Token-Erneuerung |
| Session Token | 600 s (= 10 Min, auto-verlängernd) | Nein | Browser-Zugriff |

*Konfigurierbar pro Anwendung in der Anwendungsverwaltung

**Hinweise:**
- Eingabe in der Anwendungsverwaltung erfolgt in **Minuten**
- API-Responses geben Zeiten in **Sekunden** zurück

## 8. Best Practices

### 8.1. Sicherheitsempfehlungen

1. **HTTPS zwingend** in Produktivumgebungen
2. **State-Parameter** immer für CSRF-Schutz verwenden (mindestens 128 Bit Entropie)
3. **Token-Speicherung**:
   - Niemals in LocalStorage
   - Verwenden: In-Memory, SessionStorage oder sichere Backend-Speicherung
4. **Kurze Access-Token-Laufzeiten** (maximal 1 Stunde empfohlen)
5. **Minimale Scopes** anfordern (Principle of Least Privilege)
6. **Token-Widerruf** bei Logout implementieren

### 8.2. Wahl der Authentifizierungsmethode

**Session-basiert verwenden für:**
- Browser-basierte Verwaltungswerkzeuge
- Entwicklung und Tests
- Interne Web-Anwendungen

**Bearer Token verwenden für:**
- Externe Anwendungen
- Mobile Apps
- Server-zu-Server-Kommunikation
- API-Automatisierung

### 8.3. Fehlerbehandlung

- Implementieren Sie Retry-Logik mit exponentieller Verzögerung
- Beachten Sie `Retry-After` Header bei 429-Fehlern
- Erneuern Sie Tokens proaktiv vor Ablauf
- Behandeln Sie Token-Rotation-Fehler durch komplette Neuauthentifizierung

### 8.4. Token-Verwaltung

- Speichern Sie Ablaufzeiten und erneuern Sie proaktiv
- Bei Token-Rotation: Neues Token sofort speichern, altes verwerfen
- Implementieren Sie Fallback zu Neuauthentifizierung
- Single-Use-Violations führen zu sofortiger Token-Sperrung (Security Breach)

## Anhang A: Glossar

| Begriff | Beschreibung |
|---------|--------------|
| **Access Token** | Kurzlebiges Token für API-Zugriff |
| **Authorization Code** | Einmaliger Code für Token-Austausch |
| **Bearer Token** | Token-Typ für API-Zugriff via HTTP Authorization Header |
| **Client Credentials** | Client-ID und Client-Secret |
| **Code Challenge** | SHA256-Hash des Code Verifiers (PKCE) |
| **Code Verifier** | Zufälliger String für PKCE |
| **Grant Type** | OAuth-Flow-Typ (authorization_code, refresh_token, etc.) |
| **PKCE** | Proof Key for Code Exchange - Sicherheitserweiterung |
| **Redirect URI** | Rückruf-URL nach Autorisierung |
| **Refresh Token** | Langlebiges Token zur Token-Erneuerung |
| **Scope** | Berechtigungsbereich (z.B. `graphql`) |
| **Secret** | Client-Secret für vertrauliche Anwendungen |
| **Single-Use** | Token/Code kann nur einmal verwendet werden |
| **State** | CSRF-Schutz-Parameter |
| **Token Rotation** | Automatischer Austausch bei Erneuerung |
| **Windows SSO** | Anmeldung via NTLM/Negotiate mit Windows-Domänenkonto (nicht Microsoft-Cloud) |

## Anhang B: Referenzen

- [RFC 6749 - OAuth 2.0](https://tools.ietf.org/html/rfc6749)
- [RFC 7636 - PKCE](https://tools.ietf.org/html/rfc7636)
- [RFC 7009 - Token Revocation](https://tools.ietf.org/html/rfc7009)
- [RFC 6750 - Bearer Token Usage](https://tools.ietf.org/html/rfc6750)
- [RFC 9700 - OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/html/rfc9700)
- [RFC 6762 - Multicast DNS](https://tools.ietf.org/html/rfc6762)
- [ICANN - .internal TLD Reservation](https://www.icann.org/en/board-activities-and-meetings/materials/approved-resolutions-special-meeting-of-the-icann-board-29-07-2024-en#section2.a) (29. Juli 2024)
- [OAuth 2.1 Draft](https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/)