Flask路由含#号致404错误,如何获取Google API返回的id_token?
Hey there! Let's tackle this problem step by step—your 404 error and missing id_token are tied together, and it all comes down to how browsers handle URL fragments (the # part).
Why You're Seeing a 404
The #id_token=... portion of your URL is called a fragment identifier. Browsers never send this part of the URL to the server—so when Google redirects you to http://localhost:8000/afterlogin/#id_token=..., your Flask server only receives the request for /afterlogin/. If you haven't defined a route for that path, Flask throws a 404. Even if you did have the route, the server still can't access the id_token from the fragment.
Solution 1: Get the id_token via Frontend JavaScript (For Implicit Flow)
Since the fragment lives only in the browser, you'll need to use JavaScript to grab it, then send it to your Flask backend. Here's how to set this up:
Step 1: Add the Flask Route for /afterlogin/
First, create a route that returns an HTML page with JavaScript to handle the fragment:
from flask import Flask, render_template, request, jsonify app = Flask(__name__) # Route to serve the page that will process the fragment @app.route('/afterlogin/') def after_login(): return render_template('after_login.html') # Route to receive the id_token from the frontend @app.route('/api/save-token', methods=['POST']) def save_token(): id_token = request.json.get('id_token') if not id_token: return jsonify({'error': 'No token provided'}), 400 # Here you can validate the id_token with Google, save it to a session, etc. # Example validation (using google-auth-library): # from google.oauth2 import id_token # from google.auth.transport import requests # try: # id_info = id_token.verify_oauth2_token(id_token, requests.Request(), YOUR_CLIENT_ID) # user_id = id_info['sub'] # except ValueError: # return jsonify({'error': 'Invalid token'}), 400 return jsonify({'status': 'success', 'message': 'Token received'}) if __name__ == '__main__': app.run(port=8000, debug=True)
Step 2: Create the HTML Template with JavaScript
Make a templates/after_login.html file that reads the fragment and sends it to your backend:
<!DOCTYPE html> <html> <head> <title>Processing Login...</title> </head> <body> <script> // Extract the fragment (remove the leading #) const fragment = window.location.hash.slice(1); // Parse the fragment like query parameters const params = new URLSearchParams(fragment); const idToken = params.get('id_token'); if (idToken) { // Send the token to Flask backend fetch('/api/save-token', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({id_token: idToken}), }) .then(response => response.json()) .then(data => { console.log('Success:', data); // Redirect to another page or show a success message here window.location.href = '/dashboard'; }) .catch(error => { console.error('Error:', error); alert('Failed to process login. Please try again.'); }); } else { alert('No login token found. Please try logging in again.'); } </script> </body> </html>
Solution 2: Use Authorization Code Flow (More Secure)
If your app is a server-side application (most Flask apps are), you should switch to Google's Authorization Code Flow instead of Implicit Flow. This flow returns an authorization code as a query parameter (not a fragment), which your Flask server can directly access. You then exchange this code for the id_token and access_token securely on the backend.
Here's a quick snippet of how this works:
import requests from flask import Flask, request, jsonify app = Flask(__name__) YOUR_CLIENT_ID = 'your-google-client-id' YOUR_CLIENT_SECRET = 'your-google-client-secret' REDIRECT_URI = 'http://localhost:8000/afterlogin/' @app.route('/afterlogin/') def after_login(): code = request.args.get('code') if not code: return jsonify({'error': 'Authorization code missing'}), 400 # Exchange code for tokens token_response = requests.post( 'https://oauth2.googleapis.com/token', data={ 'code': code, 'client_id': YOUR_CLIENT_ID, 'client_secret': YOUR_CLIENT_SECRET, 'redirect_uri': REDIRECT_URI, 'grant_type': 'authorization_code' } ) token_data = token_response.json() id_token = token_data.get('id_token') # Validate and use the id_token here return jsonify({'id_token': id_token}) if __name__ == '__main__': app.run(port=8000, debug=True)
Don't forget to update your Google OAuth 2.0 client settings to use the Authorization Code Flow (select "Web application" type and ensure your redirect URI is correct).
Final Notes
- The 404 error is fixed by adding the
/afterlogin/route in Flask. - Fragments are client-side only, so you need JS to access them if using Implicit Flow.
- Authorization Code Flow is more secure because tokens are never exposed in the browser's URL or history.
内容的提问来源于stack exchange,提问作者VivekChoudhary1

