FIX: Made Oauth more secure
Changed styling
This commit is contained in:
@@ -27,7 +27,10 @@ def init_oauth(app):
|
||||
client_secret=app.config['GOOGLE_CLIENT_SECRET'],
|
||||
authorize_url='https://accounts.google.com/o/oauth2/auth',
|
||||
access_token_url='https://oauth2.googleapis.com/token',
|
||||
client_kwargs={'scope': 'openid profile email'},
|
||||
client_kwargs={
|
||||
'scope': 'openid profile email',
|
||||
'prompt': 'select_account' # Forces account selection even if already logged in
|
||||
},
|
||||
api_base_url='https://www.googleapis.com/oauth2/v1/',
|
||||
userinfo_endpoint='https://openidconnect.googleapis.com/v1/userinfo',
|
||||
server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
|
||||
@@ -40,13 +43,18 @@ def login_google():
|
||||
"""
|
||||
Redirects to Google's OAuth authorization page
|
||||
"""
|
||||
# Creates nonce to be sent
|
||||
# Create both nonce and state
|
||||
session["nonce"] = token_urlsafe(16)
|
||||
session["state"] = token_urlsafe(32)
|
||||
session["origin"] = request.args.get("next")
|
||||
|
||||
|
||||
# Make sure session is saved before redirect
|
||||
session.modified = True
|
||||
|
||||
return google.authorize_redirect(
|
||||
f'{url}/api/google_auth',
|
||||
nonce=session['nonce']
|
||||
redirect_uri=f'{url}/api/google_auth',
|
||||
nonce=session['nonce'],
|
||||
state=session['state']
|
||||
)
|
||||
|
||||
|
||||
@@ -56,10 +64,22 @@ def google_auth():
|
||||
Receives token from Google OAuth and authenticates it to validate login
|
||||
"""
|
||||
try:
|
||||
# Check state parameter before authorizing
|
||||
returned_state = request.args.get('state')
|
||||
stored_state = session.get('state')
|
||||
|
||||
if not stored_state or stored_state != returned_state:
|
||||
print(f"State mismatch: stored={stored_state}, returned={returned_state}", flush=True)
|
||||
return jsonify({
|
||||
'error': f"mismatching_state: CSRF Warning! State not equal in request and response.",
|
||||
'message': 'Authentication failed'
|
||||
}), 400
|
||||
|
||||
# State matched, proceed with token authorization
|
||||
token = google.authorize_access_token()
|
||||
|
||||
# Verifies token as well as nonce
|
||||
nonce = session.pop('nonce', None)
|
||||
# Verify nonce
|
||||
nonce = session.get('nonce')
|
||||
if not nonce:
|
||||
return jsonify({'error': 'Missing nonce in session'}), 400
|
||||
|
||||
@@ -97,22 +117,33 @@ def google_auth():
|
||||
)
|
||||
user_data = get_session_info_email(user_email)
|
||||
|
||||
origin = session.pop("origin", f"{url.replace('/api', '')}")
|
||||
# Store origin, username and user_id before clearing session
|
||||
origin = session.get("origin", f"{url.replace('/api', '')}")
|
||||
username = user_data["username"]
|
||||
user_id = user_data["user_id"]
|
||||
|
||||
# Clear session and set new data
|
||||
session.clear()
|
||||
session["username"] = user_data["username"]
|
||||
session["user_id"] = user_data["user_id"]
|
||||
session["username"] = username
|
||||
session["user_id"] = user_id
|
||||
|
||||
# Ensure session is saved
|
||||
session.modified = True
|
||||
|
||||
print(f"session: {session.get('username')}. user_id: {session.get('user_id')}", flush=True)
|
||||
|
||||
return redirect(origin)
|
||||
|
||||
except OAuthError as e:
|
||||
print(f"OAuth Error: {str(e)}", flush=True)
|
||||
return jsonify({
|
||||
'message': 'Authentication failed',
|
||||
'error': str(e)
|
||||
}), 400
|
||||
|
||||
except Exception as e:
|
||||
print(f"Unexpected Error: {str(e)}", flush=True)
|
||||
return jsonify({
|
||||
'message': 'An unexpected error occurred',
|
||||
'error': str(e)
|
||||
}), 500
|
||||
}), 500
|
||||
Reference in New Issue
Block a user