> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended**:
> ```bash
> npx @scalekit-inc/cli setup
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for 40+ agents.
> Skills: integrating-agentkit, implementing-saaskit, adding-mcp-oauth, implementing-modular-sso, implementing-scim-provisioning.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Django session middleware

Add hosted login and an encrypted session cookie to Django with ScalekitAuthMiddleware
Use `scalekit.frameworks.django` to add hosted login, an encrypted `sk_session` cookie, token refresh, and logout.

Typical flow: install the `django` extra, add settings and `ScalekitAuthMiddleware`, include the auth URLs, and decorate one view with `@login_required`. There is no `ScalekitAuth` instance to construct.

Requires `scalekit-sdk-python` 2.17.0 or later.

Register these URLs in the Scalekit Dashboard under **Authentication > Redirects** before you test. Paths have **no trailing slash**.

| Dashboard field | Must match |
| --- | --- |
| **Redirect URI** | `SCALEKIT_REDIRECT_URI` exactly, for example `http://localhost:8000/callback` |
| **Post Logout Redirect URI** | Absolute URL after full logout, for example `http://localhost:8000/` |
| **Initiate Login URL** | Login path, for example `http://localhost:8000/login` |

Store credentials in environment variables. Never hard-code secrets.

```bash title=".env" showLineNumbers=false
SCALEKIT_ENVIRONMENT_URL=https://your-env.scalekit.com
SCALEKIT_CLIENT_ID=skc_...
SCALEKIT_CLIENT_SECRET=...
COOKIE_ENCRYPTION_SECRET=   # openssl rand -base64 32
REDIRECT_URI=http://localhost:8000/callback
```

Keep `COOKIE_ENCRYPTION_SECRET` identical on every server instance.

## Install the package

```bash title="Terminal" showLineNumbers=false
pip install "scalekit-sdk-python[django]"
```

## Protect a route

```python title="settings.py" wrap showLineNumbers=false

MIDDLEWARE = [
    # ...
    "scalekit.frameworks.django.ScalekitAuthMiddleware",
]

SCALEKIT_ENV_URL = os.environ["SCALEKIT_ENVIRONMENT_URL"]
SCALEKIT_CLIENT_ID = os.environ["SCALEKIT_CLIENT_ID"]
SCALEKIT_CLIENT_SECRET = os.environ["SCALEKIT_CLIENT_SECRET"]
SCALEKIT_REDIRECT_URI = os.environ["REDIRECT_URI"]
SCALEKIT_COOKIE_ENCRYPTION_SECRET = os.environ["COOKIE_ENCRYPTION_SECRET"]
SCALEKIT_COOKIE_SECURE = False  # set True behind HTTPS
```

```python title="urls.py" wrap showLineNumbers=false
from django.urls import include, path
from . import views

urlpatterns = [
    path("", include("scalekit.frameworks.django")),
    path("account", views.account),
]
```

```python title="views.py" wrap showLineNumbers=false
from django.http import JsonResponse
from scalekit.frameworks.django import login_required

@login_required
def account(request):
    return JsonResponse({"sub": request.scalekit_user["sub"]})
```

Open `http://localhost:8000/account`. A missing session returns **302** to `/login`, not a JSON 401.

`request.scalekit_user` is access-token claims, or `None` when the visitor is anonymous. `sub` is always present on an authenticated user. `email` appears only when you add it as a custom access-token claim.

> note: Middleware does not block anonymous requests
>
> `ScalekitAuthMiddleware` sets `request.scalekit_user` and refreshes the cookie. It does not redirect. Use `@login_required` on views that must be signed in. This matches Django's `AuthenticationMiddleware` plus `login_required`.

> caution: Set SCALEKIT_COOKIE_SECURE=False on local HTTP
>
> `SCALEKIT_COOKIE_SECURE` defaults to `True`. Set it `False` for local HTTP. Set it `True` in production.

<div class="sdk-client-page">

### ScalekitAuthMiddleware
<div class="sdk-method-section">
  
    

      Django middleware that reads `sk_session` on every request. Sets `request.scalekit_user` (`None` if unauthenticated) and writes a refreshed cookie about 10 seconds before expiry.

      Add the class path to `MIDDLEWARE`. Required settings: `SCALEKIT_REDIRECT_URI`, `SCALEKIT_COOKIE_ENCRYPTION_SECRET`, and either `SCALEKIT_CLIENT` or `SCALEKIT_ENV_URL` + `SCALEKIT_CLIENT_ID` + `SCALEKIT_CLIENT_SECRET`.

      
        Incoming request.
      
      
        Downstream response, with a new or cleared session cookie when needed.
      

```python wrap showLineNumbers=false
MIDDLEWARE = [
    "scalekit.frameworks.django.ScalekitAuthMiddleware",
]
```

    
  
</div>

### login_required
<div class="sdk-method-section">
  
    

      View decorator that requires `request.scalekit_user`. Redirects to `SCALEKIT_LOGIN_PATH?returnTo=...` when the user is missing. Requires `ScalekitAuthMiddleware`.

      
        Django view to protect.
      
      
        Wrapped view. Missing session → 302, never JSON 401.
      

```python wrap showLineNumbers=false
from scalekit.frameworks.django import login_required

@login_required
def billing(request):
    return JsonResponse({"sub": request.scalekit_user["sub"]})
```

    
  
</div>

### get_session
<div class="sdk-method-section">
  
    

      Read-only session lookup when you also need `expires_at`. Most views can read `request.scalekit_user` instead. Does not refresh or write a cookie.

      
        Incoming request.
      
      
        `{"user": ..., "expires_at": ...}`, or `None`. Never includes `access_token`, `refresh_token`, or `id_token`.
      

```python wrap showLineNumbers=false
from scalekit.frameworks.django import get_session

session = get_session(request)
if session:
    print(session["user"]["sub"], session["expires_at"])
```

    
  
</div>

</div>


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
