fix: connexion OAuth Gitea — redirect URI invalide (erreur 'Unregistered Redirect URI')
Le /auth/login construisait le redirect_uri avec le schéma http:// en dur et dupliquait l'expression dans login/callback : toute URL d'accès non enregistrée (https, reverse proxy, hostname, port différent) était rejetée par Gitea avec 'Unregistered Redirect URI' — les 2 liens 'Connect Gitea' et 'Register with Gitea' de Workspaces → Gitea Projects étaient touchés. - nouveau helper get_redirect_uri(request) : override explicite OAUTH_REDIRECT_URI (si défini), sinon schéma depuis X-Forwarded-Proto (fallback request scheme) + hôte depuis X-Forwarded-Host (fallback Host) - redirect_uri stocké en session à l'authorize et réutilisé tel quel dans l'échange de code (plus de dérive entre les deux étapes) - même correctif dans GitHubProvider.exchange_code (ignorait le paramètre) - config : oauth_redirect_uri par défaut vide (dynamique) au lieu de localhost:8080 en dur - .env.example documente OAUTH_REDIRECT_URI - 4 tests de régression (host header, X-Forwarded-Proto/Host, override env, URL d'authorize) — 178/179 OK, l'échec restant (test_views_calendar) est pré-existant et dépend de la date
This commit is contained in:
@@ -1691,6 +1691,57 @@ def test_oauth_login_with_mode_link_and_provider_github(client):
|
||||
assert "github" in resp.text.lower() or "not configured" in resp.text.lower()
|
||||
|
||||
|
||||
def _oauth_request(headers: dict):
|
||||
"""Minimal Starlette Request for get_redirect_uri() unit tests."""
|
||||
from fastapi import Request
|
||||
raw = [(k.lower().encode(), v.encode()) for k, v in headers.items()]
|
||||
return Request({
|
||||
"type": "http", "method": "GET", "path": "/auth/login",
|
||||
"headers": raw, "server": ("testserver", 80), "scheme": "http",
|
||||
"query_string": b"", "client": ("127.0.0.1", 1234),
|
||||
})
|
||||
|
||||
|
||||
def test_get_redirect_uri_from_host_header():
|
||||
"""get_redirect_uri() derives the URI from the Host header."""
|
||||
from app.routers.auth import get_redirect_uri
|
||||
uri = get_redirect_uri(_oauth_request({"host": "192.168.30.101:8080"}))
|
||||
assert uri == "http://192.168.30.101:8080/auth/callback"
|
||||
|
||||
|
||||
def test_get_redirect_uri_respects_forwarded_proto_and_host():
|
||||
"""Behind a TLS reverse proxy, scheme/https + forwarded host win."""
|
||||
from app.routers.auth import get_redirect_uri
|
||||
uri = get_redirect_uri(_oauth_request({
|
||||
"host": "flowdeck-internal:8080",
|
||||
"x-forwarded-proto": "https",
|
||||
"x-forwarded-host": "flowdeck.dracodev.net",
|
||||
}))
|
||||
assert uri == "https://flowdeck.dracodev.net/auth/callback"
|
||||
|
||||
|
||||
def test_get_redirect_uri_env_override_wins(monkeypatch):
|
||||
"""An explicit OAUTH_REDIRECT_URI pins the URI regardless of request."""
|
||||
from app.routers.auth import get_redirect_uri
|
||||
from app.config import settings
|
||||
monkeypatch.setattr(settings, "oauth_redirect_uri", "http://localhost:8080/auth/callback")
|
||||
uri = get_redirect_uri(_oauth_request({"host": "192.168.30.101:8080"}))
|
||||
assert uri == "http://localhost:8080/auth/callback"
|
||||
monkeypatch.undo()
|
||||
|
||||
|
||||
def test_oauth_login_redirect_uri_dynamic(client):
|
||||
"""The authorize URL carries the request-derived redirect_uri (encoded)."""
|
||||
resp = client.get(
|
||||
"/auth/login?provider=gitea",
|
||||
headers={"X-Forwarded-Proto": "https", "X-Forwarded-Host": "flowdeck.dracodev.net"},
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert resp.status_code == 302
|
||||
assert "login/oauth" in resp.headers.get("location", "").lower()
|
||||
assert "redirect_uri=https%3A%2F%2Fflowdeck.dracodev.net%2Fauth%2Fcallback" in resp.headers["location"]
|
||||
|
||||
|
||||
def test_oauth_callback_invalid_state(client):
|
||||
"""GET /auth/callback?code=test&state=invalid — 400 for invalid state."""
|
||||
resp = client.get("/auth/callback?code=test_code&state=invalid_state")
|
||||
|
||||
Reference in New Issue
Block a user