Mark-Lasfar commited on
Commit
df032da
·
1 Parent(s): be59b4c

Update authorize for google & github

Browse files
Files changed (2) hide show
  1. api/auth.py +18 -0
  2. templates/login.html +80 -99
api/auth.py CHANGED
@@ -6,10 +6,17 @@ from httpx_oauth.clients.github import GitHubOAuth2
6
  from api.database import SessionLocal
7
  from api.models import User, OAuthAccount
8
  import os
 
 
 
 
9
 
10
  cookie_transport = CookieTransport(cookie_max_age=3600)
11
 
12
  SECRET = os.getenv("JWT_SECRET")
 
 
 
13
 
14
  def get_jwt_strategy() -> JWTStrategy:
15
  return JWTStrategy(secret=SECRET, lifetime_seconds=3600)
@@ -20,11 +27,22 @@ auth_backend = AuthenticationBackend(
20
  get_strategy=get_jwt_strategy,
21
  )
22
 
 
23
  GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
24
  GOOGLE_CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET")
25
  GITHUB_CLIENT_ID = os.getenv("GITHUB_CLIENT_ID")
26
  GITHUB_CLIENT_SECRET = os.getenv("GITHUB_CLIENT_SECRET")
27
 
 
 
 
 
 
 
 
 
 
 
28
  google_oauth_client = GoogleOAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET)
29
  github_oauth_client = GitHubOAuth2(GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET)
30
 
 
6
  from api.database import SessionLocal
7
  from api.models import User, OAuthAccount
8
  import os
9
+ import logging
10
+
11
+ # Setup logging
12
+ logger = logging.getLogger(__name__)
13
 
14
  cookie_transport = CookieTransport(cookie_max_age=3600)
15
 
16
  SECRET = os.getenv("JWT_SECRET")
17
+ if not SECRET or len(SECRET) < 32:
18
+ logger.error("JWT_SECRET is not set or too short.")
19
+ raise ValueError("JWT_SECRET is required (at least 32 characters).")
20
 
21
  def get_jwt_strategy() -> JWTStrategy:
22
  return JWTStrategy(secret=SECRET, lifetime_seconds=3600)
 
27
  get_strategy=get_jwt_strategy,
28
  )
29
 
30
+ # OAuth credentials
31
  GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
32
  GOOGLE_CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET")
33
  GITHUB_CLIENT_ID = os.getenv("GITHUB_CLIENT_ID")
34
  GITHUB_CLIENT_SECRET = os.getenv("GITHUB_CLIENT_SECRET")
35
 
36
+ # Log OAuth credentials status
37
+ logger.info("GOOGLE_CLIENT_ID is set: %s", bool(GOOGLE_CLIENT_ID))
38
+ logger.info("GOOGLE_CLIENT_SECRET is set: %s", bool(GOOGLE_CLIENT_SECRET))
39
+ logger.info("GITHUB_CLIENT_ID is set: %s", bool(GITHUB_CLIENT_ID))
40
+ logger.info("GITHUB_CLIENT_SECRET is set: %s", bool(GITHUB_CLIENT_SECRET))
41
+
42
+ if not all([GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET]):
43
+ logger.error("One or more OAuth environment variables are missing.")
44
+ raise ValueError("All OAuth credentials (GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET) are required.")
45
+
46
  google_oauth_client = GoogleOAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET)
47
  github_oauth_client = GitHubOAuth2(GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET)
48
 
templates/login.html CHANGED
@@ -104,12 +104,12 @@
104
  </button>
105
  </form>
106
  <div class="flex justify-center gap-4 mt-4 flex-wrap">
107
- <button id="googleLoginBtn" class="inline-flex items-center bg-gradient-to-r from-white to-gray-200 text-gray-800 px-6 py-3 rounded-full font-semibold hover:scale-105 transition-transform">
108
  Login with Google <i class="bx bxl-google ml-2"></i>
109
- </button>
110
- <button id="githubLoginBtn" class="inline-flex items-center bg-gradient-to-r from-gray-800 to-black text-white px-6 py-3 rounded-full font-semibold hover:scale-105 transition-transform">
111
  Login with GitHub <i class="bx bxl-github ml-2"></i>
112
- </button>
113
  </div>
114
  <p class="mt-4">Don't have an account? <a href="/register" class="text-emerald-300 hover:underline">Register</a></p>
115
  <p id="errorMsg" class="text-red-500 mt-4 hidden"></p>
@@ -189,107 +189,88 @@
189
  📲 Install MG Chat
190
  </button>
191
  </footer>
 
192
  <script>
193
- const loginForm = document.getElementById('loginForm');
194
- const loginBtn = document.getElementById('loginBtn');
195
- const spinner = document.getElementById('spinner');
196
- const errorMsg = document.getElementById('errorMsg');
197
- loginForm.addEventListener('submit', async (e) => {
198
- e.preventDefault();
199
- spinner.classList.remove('hidden');
200
- errorMsg.classList.add('hidden');
201
- const formData = new FormData(loginForm);
202
- try {
203
- const response = await fetch('/auth/jwt/login', {
204
- method: 'POST',
205
- body: formData
206
- });
207
- spinner.classList.add('hidden');
208
- if (response.ok) {
209
- window.location.href = '/chat';
210
- } else {
211
- const error = await response.json();
212
- errorMsg.textContent = error.detail || 'Login failed. Please try again.';
213
- errorMsg.classList.remove('hidden');
214
- }
215
- } catch (error) {
216
- spinner.classList.add('hidden');
217
- errorMsg.textContent = 'An error occurred. Please try again.';
218
  errorMsg.classList.remove('hidden');
219
  }
220
- });
221
- function showCardDetails(cardId) {
222
- document.getElementById(`${cardId}-details`).classList.remove('hidden');
 
 
223
  }
224
- function closeCardDetails(cardId) {
225
- document.getElementById(`${cardId}-details`).classList.add('hidden');
 
 
 
 
 
 
 
226
  }
227
- // Google Login
228
- document.getElementById('googleLoginBtn').addEventListener('click', async () => {
229
- try {
230
- const response = await fetch('/auth/google/authorize');
231
- const data = await response.json();
232
- if (data.authorization_url) {
233
- window.location.href = data.authorization_url;
234
- } else {
235
- console.error('No authorization URL received');
236
- errorMsg.textContent = 'Error starting Google login. Try again.';
237
- errorMsg.classList.remove('hidden');
238
- }
239
- } catch (error) {
240
- console.error('Error initiating Google login:', error);
241
- errorMsg.textContent = 'Error starting Google login. Try again.';
242
- errorMsg.classList.remove('hidden');
243
- }
244
- });
245
- // GitHub Login
246
- document.getElementById('githubLoginBtn').addEventListener('click', async () => {
247
- try {
248
- const response = await fetch('/auth/github/authorize');
249
- const data = await response.json();
250
- if (data.authorization_url) {
251
- window.location.href = data.authorization_url;
252
- } else {
253
- console.error('No authorization URL received');
254
- errorMsg.textContent = 'Error starting GitHub login. Try again.';
255
- errorMsg.classList.remove('hidden');
256
- }
257
- } catch (error) {
258
- console.error('Error initiating GitHub login:', error);
259
- errorMsg.textContent = 'Error starting GitHub login. Try again.';
260
- errorMsg.classList.remove('hidden');
261
- }
262
- });
263
- // تسجيل Service Worker لتفعيل الـ PWA
264
- if ('serviceWorker' in navigator) {
265
- navigator.serviceWorker.register('/static/js/sw.js')
266
- .then(function(reg) {
267
- console.log('✅ Service Worker Registered', reg);
268
- }).catch(function(err) {
269
- console.error('❌ Service Worker registration failed', err);
270
  });
 
271
  }
272
- // التعامل مع حدث beforeinstallprompt لتثبيت التطبيق
273
- let deferredPrompt;
274
- window.addEventListener('beforeinstallprompt', (e) => {
275
- e.preventDefault();
276
- deferredPrompt = e;
277
- const installBtn = document.getElementById('installAppBtn');
278
- if (installBtn) {
279
- installBtn.style.display = 'block';
280
- installBtn.addEventListener('click', () => {
281
- deferredPrompt.prompt();
282
- deferredPrompt.userChoice.then(choice => {
283
- if (choice.outcome === 'accepted') {
284
- console.log('✅ User accepted the install prompt');
285
- } else {
286
- console.log('❌ User dismissed the install prompt');
287
- }
288
- deferredPrompt = null;
289
- });
290
- });
291
- }
292
- });
293
- </script>
294
  </body>
295
  </html>
 
104
  </button>
105
  </form>
106
  <div class="flex justify-center gap-4 mt-4 flex-wrap">
107
+ <a id="googleLoginBtn" href="/auth/google" class="inline-flex items-center bg-gradient-to-r from-white to-gray-200 text-gray-800 px-6 py-3 rounded-full font-semibold hover:scale-105 transition-transform">
108
  Login with Google <i class="bx bxl-google ml-2"></i>
109
+ </a>
110
+ <a id="githubLoginBtn" href="/auth/github" class="inline-flex items-center bg-gradient-to-r from-gray-800 to-black text-white px-6 py-3 rounded-full font-semibold hover:scale-105 transition-transform">
111
  Login with GitHub <i class="bx bxl-github ml-2"></i>
112
+ </a>
113
  </div>
114
  <p class="mt-4">Don't have an account? <a href="/register" class="text-emerald-300 hover:underline">Register</a></p>
115
  <p id="errorMsg" class="text-red-500 mt-4 hidden"></p>
 
189
  📲 Install MG Chat
190
  </button>
191
  </footer>
192
+
193
  <script>
194
+ const loginForm = document.getElementById('loginForm');
195
+ const loginBtn = document.getElementById('loginBtn');
196
+ const spinner = document.getElementById('spinner');
197
+ const errorMsg = document.getElementById('errorMsg');
198
+
199
+ // Handle email/password login
200
+ loginForm.addEventListener('submit', async (e) => {
201
+ e.preventDefault();
202
+ spinner.classList.remove('hidden');
203
+ errorMsg.classList.add('hidden');
204
+ const formData = new FormData(loginForm);
205
+ try {
206
+ const response = await fetch('/auth/jwt/login', {
207
+ method: 'POST',
208
+ body: formData
209
+ });
210
+ spinner.classList.add('hidden');
211
+ if (response.ok) {
212
+ window.location.href = '/chat';
213
+ } else {
214
+ const error = await response.json();
215
+ errorMsg.textContent = error.detail || 'Login failed. Please try again.';
 
 
 
216
  errorMsg.classList.remove('hidden');
217
  }
218
+ } catch (error) {
219
+ spinner.classList.add('hidden');
220
+ errorMsg.textContent = 'An error occurred. Please try again.';
221
+ errorMsg.classList.remove('hidden');
222
+ console.error('Error during login:', error);
223
  }
224
+ });
225
+
226
+ // Check for error query parameters on page load (for OAuth errors)
227
+ window.addEventListener('load', () => {
228
+ const urlParams = new URLSearchParams(window.location.search);
229
+ const error = urlParams.get('error');
230
+ if (error) {
231
+ errorMsg.textContent = decodeURIComponent(error);
232
+ errorMsg.classList.remove('hidden');
233
  }
234
+ });
235
+
236
+ // Handle card details toggle
237
+ function showCardDetails(cardId) {
238
+ document.getElementById(`${cardId}-details`).classList.remove('hidden');
239
+ }
240
+
241
+ function closeCardDetails(cardId) {
242
+ document.getElementById(`${cardId}-details`).classList.add('hidden');
243
+ }
244
+
245
+ // Service Worker for PWA
246
+ if ('serviceWorker' in navigator) {
247
+ navigator.serviceWorker.register('/static/js/sw.js')
248
+ .then(reg => console.log(' Service Worker Registered', reg))
249
+ .catch(err => console.error('❌ Service Worker registration failed', err));
250
+ }
251
+
252
+ // Handle PWA install prompt
253
+ let deferredPrompt;
254
+ window.addEventListener('beforeinstallprompt', (e) => {
255
+ e.preventDefault();
256
+ deferredPrompt = e;
257
+ const installBtn = document.getElementById('installAppBtn');
258
+ if (installBtn) {
259
+ installBtn.style.display = 'block';
260
+ installBtn.addEventListener('click', () => {
261
+ deferredPrompt.prompt();
262
+ deferredPrompt.userChoice.then(choice => {
263
+ if (choice.outcome === 'accepted') {
264
+ console.log('✅ User accepted the install prompt');
265
+ } else {
266
+ console.log(' User dismissed the install prompt');
267
+ }
268
+ deferredPrompt = null;
 
 
 
 
 
 
 
 
269
  });
270
+ });
271
  }
272
+ });
273
+ </script>
274
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  </body>
276
  </html>