mirror of
https://github.com/eduardogsilva/wireguard_webadmin.git
synced 2026-03-22 08:26:17 +00:00
68 lines
2.2 KiB
Python
68 lines
2.2 KiB
Python
|
|
from urllib.parse import urlsplit
|
||
|
|
|
||
|
|
from auth_gateway.services.challenge_service import (
|
||
|
|
CHALLENGE_COOKIE_NAME,
|
||
|
|
generate_altcha_challenge,
|
||
|
|
generate_challenge_cookie,
|
||
|
|
verify_altcha_solution,
|
||
|
|
)
|
||
|
|
from fastapi import APIRouter, Form, Request
|
||
|
|
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
|
||
|
|
|
||
|
|
router = APIRouter()
|
||
|
|
|
||
|
|
|
||
|
|
def _safe_next(url: str | None, external_path: str) -> str:
|
||
|
|
if not url:
|
||
|
|
return f"{external_path}/login"
|
||
|
|
parts = urlsplit(url)
|
||
|
|
if parts.scheme or parts.netloc:
|
||
|
|
return f"{external_path}/login"
|
||
|
|
path = parts.path or "/"
|
||
|
|
if not path.startswith("/"):
|
||
|
|
return f"{external_path}/login"
|
||
|
|
return f"{path}?{parts.query}" if parts.query else path
|
||
|
|
|
||
|
|
|
||
|
|
@router.get("/challenge", response_class=HTMLResponse)
|
||
|
|
async def challenge_page(request: Request, next: str = "/"):
|
||
|
|
external_path = request.app.state.settings.external_path
|
||
|
|
return request.app.state.templates.TemplateResponse(
|
||
|
|
"challenge.html",
|
||
|
|
{"request": request, "external_path": external_path, "next": next},
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
@router.get("/challenge/data")
|
||
|
|
async def challenge_data(request: Request):
|
||
|
|
hmac_key = request.app.state.settings.challenge_secret
|
||
|
|
challenge = generate_altcha_challenge(hmac_key)
|
||
|
|
return JSONResponse(challenge)
|
||
|
|
|
||
|
|
|
||
|
|
@router.post("/challenge/verify")
|
||
|
|
async def challenge_verify(request: Request, next: str = Form("/"), altcha: str = Form(...)):
|
||
|
|
hmac_key = request.app.state.settings.challenge_secret
|
||
|
|
external_path = request.app.state.settings.external_path
|
||
|
|
|
||
|
|
if not verify_altcha_solution(altcha, hmac_key):
|
||
|
|
return request.app.state.templates.TemplateResponse(
|
||
|
|
"challenge.html",
|
||
|
|
{"request": request, "external_path": external_path, "next": next, "error": True},
|
||
|
|
status_code=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
cookie_value = generate_challenge_cookie(hmac_key)
|
||
|
|
safe_next = _safe_next(next, external_path)
|
||
|
|
response = RedirectResponse(safe_next, status_code=303)
|
||
|
|
response.set_cookie(
|
||
|
|
key=CHALLENGE_COOKIE_NAME,
|
||
|
|
value=cookie_value,
|
||
|
|
httponly=True,
|
||
|
|
secure=request.app.state.settings.secure_cookies,
|
||
|
|
samesite="strict",
|
||
|
|
path="/",
|
||
|
|
max_age=300,
|
||
|
|
)
|
||
|
|
return response
|