---
title: "Sichere Authentifizierung und Autorisierung in SPAs: OpenID Connect und OAuth 2.0 mit PKCE"
source: https://bitvaria.com/secure-auth-spa-oauth
---

19\. Okt. 2024 · [IT-Sicherheit](https://bitvaria.com/category/it-sicherheit/)  · 6 min read

# Sichere Authentifizierung und Autorisierung in SPAs: OpenID Connect und OAuth 2.0 mit PKCE

Ein detaillierter Leitfaden zu sicheren Authentifizierungs- und Autorisierungsstrategien für Single-Page Applications (SPAs). OAuth 2.0 und OpenID Connect werden in Kombination mit PKCE genutzt, um eine sichere und effiziente Zugriffskontrolle zu gewährleisten.

![Ein detaillierter Leitfaden zu sicheren Authentifizierungs- und Autorisierungsstrategien für Single-Page Applications (SPAs). OAuth 2.0 und OpenID Connect werden in Kombination mit PKCE genutzt, um eine sichere und effiziente Zugriffskontrolle zu gewährleisten.](https://bitvaria.com/_astro/fingerprint.Bkjct1ta.jpeg)

Moderne Webanwendungen, insbesondere Single-Page Applications (SPAs), stellen besondere Anforderungen an Authentifizierungs- und Autorisierungsmechanismen. Hierbei setzen sich zunehmend die Standards OAuth 2.0 und OpenID Connect als Best Practices durch, die zusammen eine tragfähige Basis für sichere Authentifizierungsabläufe bilden.

### Was ist OAuth 2.0?

OAuth 2.0 ist ein Industriestandard für die Autorisierung von Zugriffen, der es Anwendungen ermöglicht, im Namen eines Nutzers sicher auf Ressourcen zuzugreifen. Anders als bei herkömmlichen Authentifizierungsmethoden erhalten Anwendungen nicht direkt die Anmeldeinformationen des Nutzers, sondern ein Access Token, das Zugriffe kontrolliert und den Zugang begrenzt. Damit wird ein hohes Maß an Sicherheit erreicht, das besonders für dynamische Webanwendungen relevant ist.

### Was ist OpenID Connect?

OpenID Connect baut auf OAuth 2.0 auf und erweitert es um einen zusätzlichen Authentifizierungs-Layer. Während OAuth 2.0 hauptsächlich zur Autorisierung dient, ermöglicht OpenID Connect die sichere und standardisierte Authentifizierung. Dies wird durch den ID Token erreicht, der Informationen über die Identität des Nutzers liefert. Ein Beispiel hierfür wäre eine Anwendung, die nicht nur Zugriff auf bestimmte Ressourcen, sondern auch die Identität des Nutzers sicher verifizieren möchte, etwa durch Profilinformationen oder eine eindeutige User-ID.

## Best Practice für SPAs: Authorization Code Flow mit PKCE

Für SPAs gilt der Authorization Code Flow mit PKCE als der empfohlene Authentifizierungsablauf. Diese Methode bietet erhöhte Sicherheit, indem sie eine zusätzliche Verifizierungsebene zwischen Client und Server einführt. Die früher empfohlene Alternative, der Implicit Flow, ist für SPAs mittlerweile überholt, da er Sicherheitsrisiken birgt, wie etwa die direkte Exposition von Access Tokens im Browser. Der PKCE-Flow verhindert dies, indem der Access Token nicht mehr direkt über die Redirect-URL ausgeliefert wird: die SPA tauscht erst einen Authorization Code zusammen mit dem Code Verifier gegen den Token. Wo der Token danach liegt, entscheidet die Architektur und nicht PKCE. Wer ihn gar nicht erst in den Browser lassen will, setzt ein Backend for Frontend davor, das den Token hält und nur ein Session-Cookie an die SPA gibt.

### Ablauf im Detail

#### 1\. Initiale Authentifizierungsanfrage an den Authorization Server

```mermaid
%%{init: {'theme':'dark'}}%%
sequenceDiagram
    participant User
    participant SPA
    participant AuthServer as Authorization Server

    SPA->>SPA: Generate Code Verifier and Code Challenge
    User->>SPA: User initiates login
    SPA->>AuthServer: Redirect to /authorize with Code Challenge
```

Ein Code Verifier und Code Challenge werden für PKCE erstellt und der Code Challenge wird an den Authorization Server übergeben.

```javascript
function generateRandomString(length) {
    const array = new Uint8Array(length);
    window.crypto.getRandomValues(array);
    return Array.from(
        array,
        (byte) => ('0' + byte.toString(16)).slice(-2)
        ).join('');
}

async function generateCodeChallenge(codeVerifier) {
    const encoder = new TextEncoder();
    const data = encoder.encode(codeVerifier);
    const digest = await window.crypto.subtle.digest('SHA-256', data);
    return btoa(String.fromCharCode(...new Uint8Array(digest)))
        .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

const codeVerifier = generateRandomString(64);
const codeChallenge = await generateCodeChallenge(codeVerifier); 
```

Die SPA beginnt den Authentifizierungsprozess, indem sie den Benutzer zur Login-Seite des Authorization Servers weiterleitet. Hier wird der generierte Challenge mitgegeben.

```
https://auth-server.com/authorize
?response_type=code
&client_id=your-client-id
&redirect_uri=https://your-app.com/callback
&scope=profile email
&state=xyz123
&code_challenge=generatedCodeChallenge
&code_challenge_method=S256
```

#### 2\. Empfang des Authorization Codes und Anforderung des Access Tokens

```mermaid
%%{init: {'theme':'dark'}}%%
sequenceDiagram
    participant SPA
    participant Backend
    participant AuthServer as Authorization Server

    SPA->>Backend: Send Authorization Code and Code Verifier
    Backend->>AuthServer: POST /token with Code and Code Verifier
    AuthServer->>Backend: Returns Access Token and Refresh Token
    Backend->>Backend: Store Access and Refresh Tokens securely
```

Nach erfolgreicher Authentifizierung leitet der Authorization Server den Benutzer an die `redirect_uri` der SPA zurück und fügt den Authorization Code hinzu. Die SPA extrahiert den Authorization Code und sendet ihn zusammen mit dem **Code Verifier** in einer sicheren POST-Anfrage an das Backend.

```
POST /token HTTP/1.1
Host: auth-server.com
Content-Type: application/x-www-form-urlencoded

client_id=your-client-id
&code=abcd1234
&redirect_uri=https://your-app.com/callback
&grant_type=authorization_code
&code_verifier=originalCodeVerifier
```

Das Backend speichert die Tokens sicher und gibt sie nicht an die SPA weiter.

#### 3\. Erstellung eines kurzlebigen Session-Tokens und Setzen im HTTP-Only Cookie

```mermaid
%%{init: {'theme':'dark'}}%%
sequenceDiagram
    participant SPA
    participant Backend

    Backend->>SPA: Set HTTP-Only Session Token Cookie
```

Das Backend erstellt ein **kurzlebiges Session-Token** und setzt dieses als HTTP-Only Cookie, das nur bei sicheren Verbindungen (HTTPS) verwendet wird.

#### 4\. CSRF-Token für zusätzliche Sicherheit

```mermaid
%%{init: {'theme':'dark'}}%%
sequenceDiagram
    participant SPA
    participant Backend

    Backend->>SPA: Provide CSRF Token
    SPA->>Backend: Include CSRF Token in requests
    Backend->>Backend: Verify CSRF Token on each request
```

Zusätzlich generiert das Backend ein CSRF-Token und übergibt es an die SPA, entweder in einem nicht-HTTP-Only Cookie oder als `<meta>`\-Tag. Die SPA sendet das CSRF-Token bei jeder Anfrage im Header mit, sodass das Backend Anfragen verifizieren kann.

#### 5\. Authentifizierte Anfragen von der SPA an das Backend

```mermaid
%%{init: {'theme':'dark'}}%%
sequenceDiagram
    participant SPA
    participant Backend

    SPA->>Backend: Authenticated API request with Session Token and CSRF Token
    Backend->>Backend: Verify Session and CSRF Token
    Backend->>SPA: Return protected resources
```

Die SPA nutzt das Session-Token für autorisierte Anfragen an das Backend. Das HTTP-Only Cookie mit dem Session-Token wird automatisch bei jeder Anfrage gesendet. Das CSRF-Token wird ebenfalls mitgesendet und vom Backend geprüft.

#### 6\. Token-Erneuerung bei Ablauf des Access Tokens

```mermaid
%%{init: {'theme':'dark'}}%%
sequenceDiagram
    participant SPA
    participant Backend
    participant AuthServer as Authorization Server

    Backend->>AuthServer: Use Refresh Token to get new Access Token
    AuthServer->>Backend: Return new Access Token
    Backend->>Backend: Update Session Token and set new cookie
```

Das Backend verwaltet die Erneuerung des Access Tokens, wenn es abläuft, indem es den Refresh Token verwendet. Falls der Session-Token oder der Access Token abläuft, fordert das Backend automatisch einen neuen Access Token an und aktualisiert das Session-Token.

* * *

#### Sicherheitsvorteile

1.  **Token-Verwaltung im Backend**: Der Access Token und Refresh Token bleiben im Backend gespeichert, wodurch sie vor Angriffen auf das Frontend geschützt sind.
2.  **Schutz durch HTTP-Only Cookie**: Das Session-Token im HTTP-Only Cookie ist vor JavaScript und XSS-Angriffen sicher.
3.  **CSRF-Schutz**: Das CSRF-Token verhindert Cross-Site-Request-Forgery-Angriffe.
4.  **Kurzlebiges Session-Token**: Durch die kurze Lebensdauer des Session-Tokens ist der Zugriff auf das Backend im Falle einer Kompromittierung begrenzt.

## Bedrohungsmodellierung und Sicherheitsrisiken ohne PKCE

Ohne den PKCE-Mechanismus könnten Angreifer durch sogenannte “Authorization Code Injection”- oder “Code Interception”-Angriffe den Authorization Code abfangen und nutzen, um unrechtmäßig auf sensible Daten zuzugreifen. Indem PKCE eine zusätzliche Validierungsebene zwischen Client und Authorization Server einfügt, sorgt es dafür, dass nur der ursprünglich autorisierte Client Zugang erhält. Die Generierung eines einzigartigen Code Verifiers und die Hashing-Methodik zur Code Challenge machen PKCE zu einer zuverlässigen Lösung für SPAs und erhöhen die Sicherheit für den Zugriff auf das Backend erheblich.

## Best Practices zur Implementierung

Eine sorgfältige Implementierung des PKCE-Flows verlangt, dass bestimmte Sicherheitsanforderungen eingehalten werden:

1.  Sicheres Speichern des Code Verifiers: Der Code Verifier sollte während des gesamten Authentifizierungsprozesses sicher gespeichert und danach verworfen werden, um unautorisierten Zugriff zu vermeiden.
2.  Verwendung sicherer Verbindungen: Sämtliche Kommunikation zwischen SPA, Backend und Authorization Server sollte über HTTPS erfolgen, um Abhörangriffe zu verhindern.
3.  Einschränkungen für Redirect URIs: Nur vordefinierte und vertrauenswürdige Redirect URIs dürfen in der OAuth-Konfiguration zugelassen werden, um mögliche Umleitungen auf bösartige Domains zu unterbinden.

Durch das Einhalten dieser Best Practices lässt sich das Risiko von Sicherheitslücken minimieren und eine stabile Authentifizierungsarchitektur aufbauen.

## Erweiterte Sicherheitsmaßnahmen

Zusätzlich zur PKCE-Implementierung können weitere Sicherheitsmaßnahmen eingesetzt werden:

-   Content Security Policy (CSP): Durch das Setzen einer CSP können Quellen für Skripte und Ressourcen explizit eingeschränkt werden, um die Ausführung potenziell schadhafter Inhalte zu unterbinden.
-   Subresource Integrity (SRI): Mit SRI-Hashes wird die Integrität externer Ressourcen sichergestellt, indem Inhalte nur geladen werden, wenn sie mit dem angegebenen Hash übereinstimmen. Dies schützt vor Manipulationen durch bösartige Drittanbieter.
-   Secure Storage: Jegliche Token-Speicherung im Client (falls erforderlich) sollte mithilfe sicherer Web APIs wie sessionStorage oder Secure Cookies erfolgen und strikt über httpOnly und SameSite-Attribute abgesichert werden. Diese zusätzlichen Schutzmaßnahmen ergänzen den PKCE-basierten Authorization Code Flow und stellen sicher, dass die SPA optimal vor Angriffen geschützt ist.

-   [OAuth 2.0](https://bitvaria.com/tag/oauth-2-0/)
-   [PKCE](https://bitvaria.com/tag/pkce/)
-   [Authentifizierung](https://bitvaria.com/tag/authentifizierung/)
-   [Sicherheitsarchitektur](https://bitvaria.com/tag/sicherheitsarchitektur/)

Share:

[Back to Blog](https://bitvaria.com/blog/)

## Erklärte Begriffe

- **PKCE**: Proof Key for Code Exchange. Verbessert die Sicherheit bei der Erstellung und Nutzung des Access-Token
- **Code Verifier**: Zufälliger, schwer vorhersagbarer String. Wird nur einmalig für den Authentifizierungsprozess genutzt.
- **Code Challenge**: Der Code Verifier wird mittels SHA-256 gehasht und base64-url-codiert, um einen Code Challenge zu erzeugen. Auch die Code Challenge wird nur einmal für den Authentifizierungsprozess genutzt und muss darüber hinaus nicht gespeichert werden.
- **HTTP-Only Cookie**: Auf HTTP-Only Cookies kann von Javascript nicht zugegriffen werden. Diese Cookies werden jedem Request automatisch beigefügt.
- **CSRF-Token**: Das CSRF-Token verhindert Cross-Site-Request-Forgery-Angriffe. Das CSRF-Token ist ein zufälliger, schwer vorhersagbarer Zeichen- oder Zahlenstring (oft zwischen 32 und 128 Zeichen lang), der für jede Sitzung oder Benutzerinteraktion generiert wird.
- **nicht-HTTP-Only Cookie**: Das Cookie muss von Javascript ausgelesen werden können um es explizit dem Request-Header hinzuzufügen.
