Rename /auth/restricted/ to auth/restricted/{iframe,oidc} for clarity and separation.
This commit is contained in:
@@ -534,7 +534,7 @@ test.describe('API Mode - Direct API Response Format', () => {
|
||||
expect(data.auth).toBeDefined()
|
||||
expect(data.auth.iframe).toBeDefined()
|
||||
expect(data.auth.mode).toBe('login')
|
||||
expect(data.auth.iframe).toContain('/auth/restricted/')
|
||||
expect(data.auth.iframe).toContain('/auth/restricted/iframe')
|
||||
|
||||
console.log(`✓ 401 response includes auth.iframe: ${data.auth.iframe}`)
|
||||
})
|
||||
|
||||
@@ -53,7 +53,7 @@ oid_auth_codes: dict[str, OIDAuthCode] = {}
|
||||
- `GET /auth/oidc/userinfo` — UserInfo endpoint (bearer token)
|
||||
|
||||
### Authorization (via existing restricted app)
|
||||
- `GET /auth/restricted/?client_id=...&redirect_uri=...&response_type=code&scope=openid...`
|
||||
- `GET /auth/restricted/oidc?client_id=...&redirect_uri=...&response_type=code&scope=openid...`
|
||||
|
||||
The restricted app detects OIDC params from URL and handles authentication via WebSocket.
|
||||
|
||||
@@ -83,9 +83,9 @@ The restricted app detects OIDC params from URL and handles authentication via W
|
||||
|
||||
## Authorization Flow
|
||||
|
||||
The `/auth/restricted/` page handles OIDC authorization alongside normal iframe auth:
|
||||
The `/auth/restricted/oidc` page handles OIDC authorization (same code as `/auth/restricted/iframe` for API auth):
|
||||
|
||||
1. Client redirects to `/auth/restricted/?client_id=...&redirect_uri=...&response_type=code&scope=openid&state=...`
|
||||
1. Client redirects to `/auth/restricted/oidc?client_id=...&redirect_uri=...&response_type=code&scope=openid&state=...`
|
||||
2. Frontend detects OIDC params from `window.location.search`
|
||||
3. Frontend passes raw query string to `/auth/ws/authenticate?{query_string}`
|
||||
4. User authenticates via passkey
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ The JSON variants set headers automatically, with body and response in JSON.
|
||||
|
||||
Normally you use apiJson/apiFetch and they handle this automatically. If you need to wire it yourself, on a 401/403 response that includes `auth.iframe`, call `showAuthIframe(...)` and then retry the original request.
|
||||
|
||||
The backend returns 401/403 responses with the correct URL for proper user feedback. Alternatively you may use `/auth/restricted/#mode=login`, `mode=reauth` or `mode=forbidden` to trigger the UX flow you need.
|
||||
The backend returns 401/403 responses with the correct URL for proper user feedback. Alternatively you may use `/auth/restricted/iframe#mode=login`, `mode=reauth` or `mode=forbidden` to trigger the UX flow you need.
|
||||
|
||||
```js
|
||||
import { showAuthIframe, AuthCancelledError } from 'paskia'
|
||||
|
||||
@@ -128,7 +128,7 @@ async def forward_authentication(
|
||||
- If Accept header contains "text/html": HTML page for authentication
|
||||
with data attributes for mode and other metadata.
|
||||
- Otherwise: JSON response with error details and an `iframe` field
|
||||
pointing to /auth/restricted/?mode=... for iframe-based authentication.
|
||||
pointing to /auth/restricted/iframe#mode=... for iframe-based authentication.
|
||||
"""
|
||||
try:
|
||||
ctx = await authz.verify(
|
||||
|
||||
@@ -41,7 +41,7 @@ async def auth_error_content(exc: AuthException) -> dict:
|
||||
# Build hash fragment from mode and metadata
|
||||
params = {"mode": exc.mode, **exc.metadata}
|
||||
fragment = "&".join(f"{k}={v}" for k, v in params.items() if v is not None)
|
||||
iframe_url = f"/auth/restricted/#{fragment}"
|
||||
iframe_url = f"/auth/restricted/iframe#{fragment}"
|
||||
return {
|
||||
"detail": exc.detail,
|
||||
"auth": {
|
||||
|
||||
@@ -102,7 +102,7 @@ async def openid_configuration(request: Request):
|
||||
|
||||
return {
|
||||
"issuer": issuer,
|
||||
"authorization_endpoint": f"{issuer}/auth/restricted/",
|
||||
"authorization_endpoint": f"{issuer}/auth/restricted/oidc",
|
||||
"token_endpoint": f"{issuer}/auth/oidc/token",
|
||||
"userinfo_endpoint": f"{issuer}/auth/oidc/userinfo",
|
||||
"jwks_uri": f"{issuer}/.well-known/jwks.json",
|
||||
@@ -131,9 +131,10 @@ async def jwks():
|
||||
return get_jwks()
|
||||
|
||||
|
||||
@app.get("/auth/restricted/")
|
||||
@app.get("/auth/restricted/iframe")
|
||||
@app.get("/auth/restricted/oidc")
|
||||
async def restricted_view():
|
||||
"""Serve the restricted/authentication UI for iframe embedding."""
|
||||
"""Serve the restricted/authentication UI for iframe or OpenID Connect."""
|
||||
return Response(*await vitedev.read("/auth/restricted/index.html"))
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Implements OpenID Connect 1.0 Authorization Code flow:
|
||||
- POST /token - Token endpoint (code exchange)
|
||||
- GET /userinfo - UserInfo endpoint (bearer token)
|
||||
|
||||
Authorization is handled by /auth/restricted/ which passes OIDC params to
|
||||
Authorization is handled by /auth/restricted/oidc which passes OIDC params to
|
||||
the /auth/ws/authenticate WebSocket.
|
||||
"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user