mirror of
https://github.com/pocketpaw/pocketpaw.git
synced 2026-05-20 00:41:09 +00:00
Remove /api/qr and /api/v1/qr from exempt_paths in auth middleware so the QR endpoint can no longer be hit without a valid session. Previously any network-reachable client could GET /api/qr, decode the PNG, and extract a fully valid 1-hour session token — a complete auth bypass (OWASP A01 — Broken Access Control). Changes: - Remove /api/qr and /api/v1/qr from exempt_paths in dashboard_auth.py - Reduce QR pairing token TTL from 1 hour to 60 seconds - Add ttl_seconds param to create_session_token() for short-lived tokens - Add audit log event on QR code generation - Update v1 QR endpoint (/api/v1/auth.py) with matching fix - Update tests: unauthenticated /api/qr now returns 401 - Update docs to reflect auth requirement Fixes #854
68 lines
2.0 KiB
Plaintext
68 lines
2.0 KiB
Plaintext
---
|
|
title: Generate QR Login Code
|
|
description: "Generate a QR code for mobile device login to the PocketPaw dashboard. Scan the QR code with your phone to authenticate without manually entering credentials or tokens."
|
|
api: GET /api/qr
|
|
baseUrl: http://localhost:8000
|
|
layout: '@/layouts/APIEndpointLayout.astro'
|
|
auth: bearer
|
|
section: API Reference
|
|
ogType: article
|
|
keywords: ["qr code login", "mobile auth", "qr authentication"]
|
|
tags: ["api", "authentication"]
|
|
---
|
|
|
|
## Overview
|
|
|
|
Generates a QR code PNG image that encodes the dashboard URL with an embedded access token. Scanning this QR code on a mobile device automatically authenticates the user.
|
|
|
|
This endpoint **requires authentication**. The caller must already have a valid session (via Bearer token, session cookie, or localhost bypass). The QR code embeds a short-lived (60-second) pairing token so that a leaked QR image cannot grant long-lived access.
|
|
|
|
## Response
|
|
|
|
Returns a PNG image (`image/png` content type) as a streaming response.
|
|
|
|
<RequestExample>
|
|
<Tabs items={["cURL", "JavaScript", "Python"]}>
|
|
<Tab title="cURL">
|
|
```bash
|
|
curl -X GET "http://localhost:8000/api/qr" \
|
|
-H "Authorization: Bearer $TOKEN" -o login-qr.png
|
|
```
|
|
</Tab>
|
|
<Tab title="JavaScript">
|
|
```javascript
|
|
const response = await fetch("http://localhost:8000/api/qr", {
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
});
|
|
const blob = await response.blob();
|
|
const url = URL.createObjectURL(blob);
|
|
// Use url in an <img> tag or download link
|
|
console.log("QR code blob URL:", url);
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```python
|
|
import requests
|
|
|
|
response = requests.get(
|
|
"http://localhost:8000/api/qr",
|
|
headers={"Authorization": f"Bearer {token}"},
|
|
)
|
|
with open("login-qr.png", "wb") as f:
|
|
f.write(response.content)
|
|
print("QR code saved to login-qr.png")
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
</RequestExample>
|
|
|
|
<ResponseExample>
|
|
<Tabs items={["200"]}>
|
|
<Tab title="200">
|
|
```
|
|
Binary PNG image (content-type: image/png)
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
</ResponseExample>
|