**I didn't explain how to create a project in Firebase
Solution
- I have a
signInWithGoogle
method like this:
darts
" ...\n \n Future<UserCredential?> signInWithGoogle() async {\n try {\n final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();\n \n if (googleUser == null) {\n return null;\n }\n\n final GoogleSignInAuthentication googleAuth = await googleUser.authentication;\n final OAuthCredential credential = GoogleAuthProvider.credential(\n accessToken: googleAuth.accessToken,\n idToken: googleAuth.idToken,\n );\n\n return await _auth.signInWithCredential(credential);\n } on FirebaseAuthException catch (e) {\n throw _handleAuthException(e);\n }\n }\n\n ..."
...
Future<UserCredential?> signInWithGoogle() async {
try {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser == null) {
return null;
}
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final OAuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
return await _auth.signInWithCredential(credential);
} on FirebaseAuthException catch (e) {
throw _handleAuthException(e);
}
}
...
- Then in the event button login with Google:
darts
" ...\n \n onPressed: () async {\n final currentContext = context;\n\n final userCredential = await AuthService().signInWithGoogle();\n if (userCredential != null) {\n final user = userCredential.user;\n final idToken = await user!.getIdToken();\n\n // send user data to backend\n final response = await http.post(\n Uri.parse('${dotenv.env['API_URL']}/api/v1/auth/google-login'), // backend url\n headers: {'Content-Type': 'application/json'},\n body: json.encode({\n 'id_token': idToken,\n }),\n );\n\n if (currentContext.mounted) {\n if (response.statusCode == 200) {\n authService.setUserCredential(userCredential);\n // redirect to home\n Navigator.of(context).pushReplacementNamed('/home');\n } else {\n // show error message\n ScaffoldMessenger.of(context).showSnackBar(\n const SnackBar(\n content: Text('Login failed. Please try again.'),\n ),\n );\n }\n }\n }\n }\n ..."
...
onPressed: () async {
final currentContext = context;
final userCredential = await AuthService().signInWithGoogle();
if (userCredential != null) {
final user = userCredential.user;
final idToken = await user!.getIdToken();
// send user data to backend
final response = await http.post(
Uri.parse('${dotenv.env['API_URL']}/api/v1/auth/google-login'), // backend url
headers: {'Content-Type': 'application/json'},
body: json.encode({
'id_token': idToken,
}),
);
if (currentContext.mounted) {
if (response.statusCode == 200) {
authService.setUserCredential(userCredential);
// redirect to home
Navigator.of(context).pushReplacementNamed('/home');
} else {
// show error message
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Login failed. Please try again.'),
),
);
}
}
}
}
...
- Meanwhile on my Django server, I use the
google-auth
library to validate Firebase tokens:
python
"from google.oauth2 import id_token\nfrom google.auth.transport import requests\nimport json\nimport random\nfrom .models import Account\n\n...\n\ndef google_login(request):\n data = json.loads(request.body)\n token = data['id_token']\n\n try:\n #CLIENT_ID = 'xxxx.apps.googleusercontent.com'\n # idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)\n idinfo = id_token.verify_firebase_token(token, requests.Request())\n\n email = idinfo['email']\n username = idinfo['name']\n\n user, created = Account.objects.get_or_create(\n account_email=email,\n defaults={\n 'account_id': random.randint(10**10, 10**11 - 1),\n 'username': username,\n 'login_with': 'GOOGLE',\n 'active_status': True\n }\n )"
from google.oauth2 import id_token
from google.auth.transport import requests
import json
import random
from .models import Account
...
def google_login(request):
data = json.loads(request.body)
token = data['id_token']
try:
#CLIENT_ID = 'xxxx.apps.googleusercontent.com'
# idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
idinfo = id_token.verify_firebase_token(token, requests.Request())
email = idinfo['email']
username = idinfo['name']
user, created = Account.objects.get_or_create(
account_email=email,
defaults={
'account_id': random.randint(10**10, 10**11 - 1),
'username': username,
'login_with': 'GOOGLE',
'active_status': True
}
)
- the commented part is the code I got from AI, but it doesn't work. I searched for a solution for quite a long time and finally I found a solution from reference. I changed
id_token.verify_oauth2_token
toid_token.verify_firebase_token
and it worked. So for tokens obtained from Firebase, we have to useverify_firebase_token
notverify_oauth2_token
.
Reference
https://github.com/googleapis/google-auth-library-python/issues/316#issuecomment-667777124