> **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/)

---

# Flask session middleware

Add hosted login and an encrypted session cookie to Flask with ScalekitAuth
Use `ScalekitAuth` from `scalekit.frameworks.flask` to add hosted login, an encrypted `sk_session` cookie, token refresh, and logout.

Typical flow: install the `flask` extra, construct `ScalekitAuth` with the Flask app, and decorate one view with `@auth.requires_auth`.

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

Register these URLs in the Scalekit Dashboard under **Authentication > Redirects** before you test:

| Dashboard field | Must match |
| --- | --- |
| **Redirect URI** | `redirect_uri` exactly, for example `http://localhost:5001/callback` |
| **Post Logout Redirect URI** | Absolute URL after full logout, for example `http://localhost:5001/` |
| **Initiate Login URL** | Login path, for example `http://localhost:5001/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:5001/callback
```

Keep `COOKIE_ENCRYPTION_SECRET` identical on every server instance. The SDK does not ship a default.

## Install the package

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

## Protect a route

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

from flask import Flask
from scalekit.frameworks.flask import ScalekitAuth

app = Flask(__name__)
auth = ScalekitAuth(
    app,
    env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"],
    client_id=os.environ["SCALEKIT_CLIENT_ID"],
    client_secret=os.environ["SCALEKIT_CLIENT_SECRET"],
    redirect_uri=os.environ["REDIRECT_URI"],
    cookie_encryption_secret=os.environ["COOKIE_ENCRYPTION_SECRET"],
    cookie_secure=False,  # set True behind HTTPS
)

@app.route("/account")
@auth.requires_auth
def account():
    return {"sub": auth.current_user["sub"]}
```

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

`auth.current_user` is access-token claims. `sub` is always present. `email` appears only when you add it as a custom access-token claim.

> caution: Set cookie_secure=False on local HTTP
>
> `cookie_secure` defaults to `True`. Some browsers drop a `Secure` cookie on plain `http://localhost`, which looks like a session that never sticks. Set `cookie_secure=False` for local HTTP. Set it `True` in production.

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

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

      Creates the Flask session helper. Pass `app` to register routes immediately, or call `init_app` later.

      
        Flask app. When provided, registers `/login`, `/callback`, and `/logout`.
      
      
        Existing client. When omitted, the constructor builds one from `env_url`, `client_id`, and `client_secret`.
      
      
        Scalekit environment URL.
      
      
        Application client ID.
      
      
        Application client secret.
      
      
        Exact **Redirect URI** registered in the dashboard.
      
      
        Secret used to encrypt `sk_session`. Generate with `openssl rand -base64 32`.
      
      
        Session cookie name.
      
      
        Set `False` for local HTTP.
      
      
        Login view path.
      
      
        Callback view path.
      
      
        Logout view path.
      
      
        Fallback path after login when `returnTo` is absent.
      
      
        Where logout lands. Defaults to `post_login_redirect`.
      
      
        When `True`, logout ends the Scalekit session with `id_token_hint`.
      
      
        Helper with `requires_auth`, `current_user`, and `get_session`.
      

```python wrap showLineNumbers=false
auth = ScalekitAuth(
    app,
    env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"],
    client_id=os.environ["SCALEKIT_CLIENT_ID"],
    client_secret=os.environ["SCALEKIT_CLIENT_SECRET"],
    redirect_uri=os.environ["REDIRECT_URI"],
    cookie_encryption_secret=os.environ["COOKIE_ENCRYPTION_SECRET"],
)
```

    
  
</div>

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

      Registers the login, callback, and logout views on a Flask app. Use this when you construct `ScalekitAuth` without `app`.

      
        Flask application.
      
      
        Routes are added in place.
      

```python wrap showLineNumbers=false
auth = ScalekitAuth(
    redirect_uri=os.environ["REDIRECT_URI"],
    cookie_encryption_secret=os.environ["COOKIE_ENCRYPTION_SECRET"],
    env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"],
    client_id=os.environ["SCALEKIT_CLIENT_ID"],
    client_secret=os.environ["SCALEKIT_CLIENT_SECRET"],
)
auth.init_app(app)
```

    
  
</div>

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

      View decorator that requires a valid session. Sets `g.scalekit_user` and refreshes the cookie about 10 seconds before expiry. Redirects to `login_path` when the session is missing.

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

```python wrap showLineNumbers=false
@app.route("/billing")
@auth.requires_auth
def billing():
    return {"sub": auth.current_user["sub"]}
```

    
  
</div>

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

      Access-token claims for the current request. Same object as `g.scalekit_user`.

      
        Claims when `requires_auth` has run, otherwise `None`.
      

```python wrap showLineNumbers=false
sub = auth.current_user["sub"]
```

    
  
</div>

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

      Read-only session lookup for a public page that shows logged-in vs logged-out state. Does not refresh or write a cookie. Only `requires_auth` refreshes the session.

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

```python wrap showLineNumbers=false
session = auth.get_session()
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 |
