notionhive-ai commited on
Commit
d705087
·
verified ·
1 Parent(s): ab5398d

Update auth.py

Browse files
Files changed (1) hide show
  1. auth.py +48 -17
auth.py CHANGED
@@ -1,5 +1,6 @@
 
1
  from fastapi import APIRouter, Request, HTTPException
2
- from fastapi.responses import RedirectResponse
3
  from google_auth_oauthlib.flow import Flow
4
  from dotenv import load_dotenv
5
  import os
@@ -9,19 +10,13 @@ router = APIRouter()
9
 
10
  CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
11
  CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET")
12
- ENV_REDIRECT_URI = os.getenv("REDIRECT_URI") # optional override
13
 
14
  SCOPES = ["https://www.googleapis.com/auth/calendar"]
15
 
16
  def build_redirect_uri(request: Request) -> str:
17
- """
18
- Prefer env REDIRECT_URI if set.
19
- Otherwise, derive from request with proxy headers so it works on HF + local.
20
- """
21
  if ENV_REDIRECT_URI:
22
  return ENV_REDIRECT_URI.strip().rstrip("/")
23
-
24
- # Respect reverse proxy headers (HF Spaces)
25
  proto = request.headers.get("x-forwarded-proto") or request.url.scheme
26
  host = request.headers.get("x-forwarded-host") or request.headers.get("host") or request.url.hostname
27
  return f"{proto}://{host}/auth/callback".rstrip("/")
@@ -45,8 +40,6 @@ def login(request: Request):
45
  redirect_uri = build_redirect_uri(request)
46
  flow = build_flow(redirect_uri)
47
  flow.redirect_uri = redirect_uri
48
-
49
- # IMPORTANT: offline access so we get refresh_token
50
  auth_url, _ = flow.authorization_url(
51
  prompt="consent",
52
  include_granted_scopes="true",
@@ -54,23 +47,61 @@ def login(request: Request):
54
  )
55
  return RedirectResponse(auth_url)
56
 
57
- @router.get("/auth/callback")
 
 
58
  async def auth_callback(request: Request):
 
59
  code = request.query_params.get("code")
60
- if not code:
61
- raise HTTPException(status_code=400, detail="Missing code")
 
 
 
 
 
62
 
63
  redirect_uri = build_redirect_uri(request)
64
  flow = build_flow(redirect_uri)
65
  flow.redirect_uri = redirect_uri
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  try:
68
  flow.fetch_token(code=code)
69
- credentials = flow.credentials
70
  return {
71
- "access_token": credentials.token,
72
- "refresh_token": credentials.refresh_token,
73
- "expiry": credentials.expiry.isoformat() if credentials.expiry else None,
74
  }
75
  except Exception as e:
76
  raise HTTPException(status_code=500, detail=f"Failed to fetch token: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # auth.py
2
  from fastapi import APIRouter, Request, HTTPException
3
+ from fastapi.responses import RedirectResponse, JSONResponse
4
  from google_auth_oauthlib.flow import Flow
5
  from dotenv import load_dotenv
6
  import os
 
10
 
11
  CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
12
  CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET")
13
+ ENV_REDIRECT_URI = os.getenv("REDIRECT_URI") # optional
14
 
15
  SCOPES = ["https://www.googleapis.com/auth/calendar"]
16
 
17
  def build_redirect_uri(request: Request) -> str:
 
 
 
 
18
  if ENV_REDIRECT_URI:
19
  return ENV_REDIRECT_URI.strip().rstrip("/")
 
 
20
  proto = request.headers.get("x-forwarded-proto") or request.url.scheme
21
  host = request.headers.get("x-forwarded-host") or request.headers.get("host") or request.url.hostname
22
  return f"{proto}://{host}/auth/callback".rstrip("/")
 
40
  redirect_uri = build_redirect_uri(request)
41
  flow = build_flow(redirect_uri)
42
  flow.redirect_uri = redirect_uri
 
 
43
  auth_url, _ = flow.authorization_url(
44
  prompt="consent",
45
  include_granted_scopes="true",
 
47
  )
48
  return RedirectResponse(auth_url)
49
 
50
+ # accept GET/POST and trailing slash
51
+ @router.api_route("/auth/callback", methods=["GET", "POST"])
52
+ @router.api_route("/auth/callback/", methods=["GET", "POST"])
53
  async def auth_callback(request: Request):
54
+ # try query first
55
  code = request.query_params.get("code")
56
+ # also accept POST (some proxies can end up posting back)
57
+ if not code and request.method == "POST":
58
+ try:
59
+ form = await request.form()
60
+ code = form.get("code")
61
+ except Exception:
62
+ code = None
63
 
64
  redirect_uri = build_redirect_uri(request)
65
  flow = build_flow(redirect_uri)
66
  flow.redirect_uri = redirect_uri
67
 
68
+ if not code:
69
+ # Return diagnostics so we can see what arrived
70
+ return JSONResponse(
71
+ status_code=400,
72
+ content={
73
+ "detail": "Missing code",
74
+ "method": request.method,
75
+ "url": str(request.url),
76
+ "query": dict(request.query_params),
77
+ "headers": {
78
+ "x-forwarded-proto": request.headers.get("x-forwarded-proto"),
79
+ "x-forwarded-host": request.headers.get("x-forwarded-host"),
80
+ "host": request.headers.get("host"),
81
+ },
82
+ "derived_redirect_uri": redirect_uri,
83
+ },
84
+ )
85
+
86
  try:
87
  flow.fetch_token(code=code)
88
+ cred = flow.credentials
89
  return {
90
+ "access_token": cred.token,
91
+ "refresh_token": cred.refresh_token,
92
+ "expiry": cred.expiry.isoformat() if cred.expiry else None,
93
  }
94
  except Exception as e:
95
  raise HTTPException(status_code=500, detail=f"Failed to fetch token: {e}")
96
+
97
+ @router.get("/auth/debug")
98
+ def auth_debug(request: Request):
99
+ return {
100
+ "derived_redirect_uri": build_redirect_uri(request),
101
+ "request_url": str(request.url),
102
+ "headers": {
103
+ "x-forwarded-proto": request.headers.get("x-forwarded-proto"),
104
+ "x-forwarded-host": request.headers.get("x-forwarded-host"),
105
+ "host": request.headers.get("host"),
106
+ },
107
+ }