> ## Documentation Index
> Fetch the complete documentation index at: https://docs.civic.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Django

> Follow these simple steps to set up Civic Auth with a [Django](https://www.djangoproject.com/) backend (a working example is available in the [github repo](https://github.com/civicteam/civic-auth-py/tree/main/examples/django)).

<Info>
  **Prefer AI-assisted setup?** Use our [AI prompts for Django](/ai-prompts/python/django) to automatically integrate Civic Auth using Claude, ChatGPT, or other AI assistants. Includes a step-by-step video tutorial!
</Info>

<Warning>
  **Important: The SDK Handles Everything**

  The Civic Auth Python SDK abstracts away all token validation complexity. You do **NOT** need to:

  * Implement custom middleware for token validation
  * Parse or validate JWT tokens manually
  * Handle token refresh logic yourself

  Simply use the provided decorators and user access functions - the SDK handles all authentication logic for you.
</Warning>

## Quick Start

### 1. Install Dependencies

```bash theme={null}
pip install "civic-auth[django]"
```

Or, if you're using the `uv` package manager:

```bash theme={null}
uv add "civic-auth[django]"
```

### 2. Configure Your Django Settings

Add Civic Auth configuration to your Django settings:

```python theme={null}
# settings.py

CIVIC_AUTH = {
    "client_id": "YOUR_CLIENT_ID",  # Get this from auth.civic.com
    "redirect_url": "http://localhost:8000/auth/callback",
    "post_logout_redirect_url": "http://localhost:8000/"
}

# Add Civic Auth middleware
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    # Add Civic Auth middleware
    'civic_auth.integrations.django.CivicAuthMiddleware',
]
```

### 3. Add URL Patterns

Include the Civic Auth URLs in your project:

```python theme={null}
# urls.py

from django.contrib import admin
from django.urls import path, include
from civic_auth.integrations.django import get_auth_urls

urlpatterns = [
    path('admin/', admin.site.urls),
    # Add Civic Auth URLs
    path('', include(get_auth_urls())),
    # Your other URLs...
    path('', include('your_app.urls')),  # Replace with your app
]
```

### 4. Create Basic Views

Create views for your application:

```python theme={null}
# views.py

from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from civic_auth.integrations.django import civic_auth_required

def home(request):
    return HttpResponse("""
        <h1>Welcome to My Django App!</h1>
        <p><a href="/auth/login">Login with Civic Auth</a></p>
        <p><a href="/profile">View Profile</a> (requires authentication)</p>
        <p><a href="/dashboard">Dashboard</a> (requires authentication)</p>
    """)

@civic_auth_required
def profile(request):
    user = request.civic_user
    return JsonResponse({
        "message": f"Hello, {user.get('name', 'User')}!",
        "user_info": {
            "id": user.get("id"),
            "email": user.get("email"),
            "name": user.get("name"),
            "picture": user.get("picture")
        }
    })

@civic_auth_required
def dashboard(request):
    user = request.civic_user
    return HttpResponse(f"""
        <h1>Dashboard</h1>
        <p>Welcome, {user.get('name', 'User')}!</p>
        <img src="{user.get('picture', '')}" alt="Profile picture" style="width: 50px; height: 50px; border-radius: 50%;">
        <p>Email: {user.get('email', 'No email')}</p>
        <p><a href="/auth/logout">Logout</a></p>
    """)

def public_page(request):
    return HttpResponse("<h1>Public Page</h1><p>No authentication required</p>")
```

### 5. Add URL Patterns for Your Views

```python theme={null}
# your_app/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
    path('profile/', views.profile, name='profile'),
    path('dashboard/', views.dashboard, name='dashboard'),
    path('public/', views.public_page, name='public'),
]
```

### 6. Run Your Django App

```bash theme={null}
python manage.py runserver
```

Visit `http://localhost:8000` and click the login link to test authentication.

## How It Works

### Authentication Flow

1. User visits `/auth/login` - starts the login process
2. User authenticates with Civic
3. User gets redirected to `/auth/callback` - completes authentication
4. User can now access protected views

### Available Routes

* `/auth/login` - Start authentication
* `/auth/callback` - Handle OAuth callback (auto-created)
* `/auth/logout` - Sign out user

### Working with User Data

The authenticated user is available via `request.civic_user` as a dictionary:

```python theme={null}
@civic_auth_required
def user_info(request):
    user = request.civic_user
    return JsonResponse({
        "id": user.get("id"),
        "email": user.get("email"),
        "name": user.get("name"),
        "picture": user.get("picture")
    })
```

### Protecting Views

Use the `@civic_auth_required` decorator to protect views:

```python theme={null}
from civic_auth.integrations.django import civic_auth_required

@civic_auth_required
def protected_view(request):
    user = request.civic_user
    return HttpResponse(f"Hello {user.get('name', 'User')}, this is protected!")
```

## Template Usage

Access the user in Django templates:

```python theme={null}
# views.py
from django.shortcuts import render
from civic_auth.integrations.django import civic_auth_required

@civic_auth_required
def dashboard_template(request):
    return render(request, 'dashboard.html', {
        'civic_user': request.civic_user
    })
```

```html theme={null}
<!-- templates/dashboard.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Dashboard</title>
</head>
<body>
    {% if civic_user %}
        <h1>Welcome, {{ civic_user.name|default:"User" }}!</h1>
        <img src="{{ civic_user.picture }}" alt="Profile picture">
        <p>Email: {{ civic_user.email|default:"No email" }}</p>
        <a href="/auth/logout">Logout</a>
    {% else %}
        <p><a href="/auth/login">Please login</a></p>
    {% endif %}
</body>
</html>
```

## Django REST Framework

For API views with Django REST Framework:

```python theme={null}
from rest_framework.decorators import api_view
from rest_framework.response import Response
from civic_auth.integrations.django import civic_auth_required

@api_view(['GET'])
@civic_auth_required
def api_profile(request):
    user = request.civic_user
    return Response({
        "authenticated": True,
        "user": {
            "id": user.get("id"),
            "email": user.get("email"),
            "name": user.get("name"),
            "picture": user.get("picture")
        }
    })

@api_view(['GET'])
@civic_auth_required
def api_dashboard(request):
    user = request.civic_user
    return Response({
        "message": f"Welcome to your dashboard, {user.get('name', 'User')}!",
        "user_id": user.get("id")
    })
```

## Complete Example

Here's a complete working Django project structure:

```python theme={null}
# settings.py
import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

SECRET_KEY = 'your-secret-key'
DEBUG = True
ALLOWED_HOSTS = []

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'your_app',  # Replace with your app name
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'civic_auth.integrations.django.CivicAuthMiddleware',
]

ROOT_URLCONF = 'your_project.urls'

CIVIC_AUTH = {
    "client_id": "YOUR_CLIENT_ID",  # Replace with your actual client ID
    "redirect_url": "http://localhost:8000/auth/callback",
    "post_logout_redirect_url": "http://localhost:8000/"
}

# Database, static files, etc. (standard Django configuration)
```

```python theme={null}
# your_project/urls.py
from django.contrib import admin
from django.urls import path, include
from civic_auth.integrations.django import get_auth_urls

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(get_auth_urls())),
    path('', include('your_app.urls')),
]
```

## Configuration Options

| Field                      | Required | Description                                                             |
| -------------------------- | -------- | ----------------------------------------------------------------------- |
| `client_id`                | Yes      | Your Civic Auth Client ID from [auth.civic.com](https://auth.civic.com) |
| `redirect_url`             | Yes      | Where Civic redirects after authentication (must be absolute URL)       |
| `post_logout_redirect_url` | Yes      | Where users go after logout (must be absolute URL)                      |

<Info>
  Note: `redirect_url` and `post_logout_redirect_url` must be absolute URLs.
</Info>

## Next Steps

1. **Get your Client ID**: Sign up at [auth.civic.com](https://auth.civic.com)
2. **Replace `YOUR_CLIENT_ID`** with your actual client ID
3. **Update URLs** when deploying to production
4. **Add more protected views** as needed
5. **Create templates** for better user experience

## Authentication Flows

Civic Auth supports multiple OAuth 2.0 authentication methods to provide maximum security for different application architectures.

<Info>
  **Need client secret authentication?** Civic Auth supports PKCE-only, client secrets, and hybrid PKCE + client secret approaches. See our [Authentication Flows guide](/overview/authentication-flows) for detailed comparison.
</Info>

The examples above use PKCE authentication, which is handled entirely by the Civic Auth SDK and suitable for most applications.

### Access Tokens

Read tokens from the session (or via a CivicAuth instance if exposed):

```python theme={null}
from django.http import JsonResponse
from civic_auth.core import CivicAuth  # for key names
from civic_auth.integrations.django import civic_auth_required

@civic_auth_required
def tokens(request):
    return JsonResponse({
        "access_token": request.session.get(CivicAuth.ACCESS_TOKEN_KEY),
        "id_token": request.session.get(CivicAuth.ID_TOKEN_KEY),
        "refresh_token": request.session.get(CivicAuth.REFRESH_TOKEN_KEY),
        "token_type": "Bearer",
    })
```
