I want user in my app to stay logged in. I'm using the firebase authentification with IDToken which lasts for 1hour until it expires. I want to auto refresh the session everytime if it is going to expire.
what Ive read so far here https://firebase.google.com/docs/reference/rest/auth/#section-refresh-token it should be somehow possible with https://securetoken.googleapis.com/v1/token?key=[API_KEY]
This is my full code for authentification right now (flutter)
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../provider/http_exception.dart';
import 'dart:async';
import 'package:shared_preferences/shared_preferences.dart';
class Auth with ChangeNotifier {
String _token;
DateTime _expiryDate;
String _userId;
Timer _authTimer;
bool wasLoggedOut = false;
bool onBoarding = false;
Future<void> createUser(String email, String firstName, String lastName) async {
final url = 'https://test45.firebaseio.com/users/$userId.json?auth=$token';
final response = await http.put(url, body: json.encode({
'userEmail': email,
'userIsArtist': false,
'userFirstName': firstName,
'userLastName': lastName,
}));
print('post ist done');
print(json.decode(response.body));
}
bool get isAuth {
return token != null;
}
String get userId {
return _userId;
}
String get token {
if (_expiryDate != null &&
_expiryDate.isAfter(DateTime.now()) &&
_token != null) {
return _token;
}
return null;
}
Future<void> authenticate(
String email, String password, String urlSegement) async {
final url = 'https://identitytoolkit.googleapis.com/v1/accounts:$urlSegement?key=AIzaSyD8pb3M325252dfsDC-4535dfd';
try {
final response = await http.post(url,
body: json.encode({
'email': email,
'password': password,
'returnSecureToken': true,
}));
final responseData = json.decode(response.body);
if (responseData['error'] != null) {
throw HttpException(responseData['error']['message']);
}
_token = responseData['idToken'];
_userId = responseData['localId'];
_expiryDate = DateTime.now().add(Duration(seconds: int.parse(responseData['expiresIn'])));
_autoLogout();
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final userData = json.encode({
'token': _token,
'userId': _userId,
'expiryDate': _expiryDate.toIso8601String(),
});
prefs.setString('userData', userData);
} catch (error) {
throw error;
}
}
Future<void> signup(String email, String password) async {
return authenticate(email, password, 'signUp');
}
Future<void> signin(String email, String password) async {
return authenticate(email, password, 'signInWithPassword');
}
Future<bool> tryAutoLogin() async {
final prefs = await SharedPreferences.getInstance();
if(!prefs.containsKey('userData')){
return false;
}
final extractedUserData = json.decode(prefs.getString('userData')) as Map<String, Object>;
final expiryDate = DateTime.parse(extractedUserData['expiryDate']);
if(expiryDate.isBefore(DateTime.now())) {
return false;
}
_token = extractedUserData['token'];
_userId = extractedUserData['userId'];
_expiryDate = expiryDate;
notifyListeners();
_autoLogout();
return true;
}
Future<void> logout() async {
_token = null;
_userId = null;
_expiryDate = null;
if(_authTimer != null){
_authTimer.cancel();
_authTimer = null;
}
notifyListeners();
final prefs = await SharedPreferences.getInstance();
prefs.remove('userData');
}
void _autoLogout() {
if(_authTimer != null) {
_authTimer.cancel();
}
final timetoExpiry = _expiryDate.difference(DateTime.now()).inSeconds;
_authTimer = Timer(Duration(seconds: timetoExpiry), logout);
}
}
how to modify my auth.dart to achieve the auto refreshing?
EDIT:
As mentioned in the comments, im working with providers where I have the following functions to retrieve the token:
update(String token, id, List<items> itemsList) {
authToken = token;
userId = id;
}
also in every of my API calls im using the auth parameter already:
var url = 'https://test45.firebaseio.com/folder/$inside/$ym.json?auth=$authToken';
I just need somebody who can show me how to modify my code with the refresh token.
Thanks in advance!
EDIT:
I tried to implement it, but im getting an infinite loop, please help:
String get token {
if (_expiryDate != null &&
_expiryDate.isAfter(DateTime.now()) &&
_token != null) {
return _token;
}
refreshSession();
}
Future<void> refreshSession() async {
final url = 'https://securetoken.googleapis.com/v1/token?key=5437fdjskfsdk38438?grant_type=refresh_token?auth=$token';
try {
final response = await http.post(url,
body: json.encode({
'token_type': 'Bearer',
}));
final responseData = json.decode(response.body);
if (responseData['error'] != null) {
throw HttpException(responseData['error']['message']);
}
_token = responseData['id_token'];
_userId = responseData['user_id'];
_expiryDate = DateTime.now().add(Duration(seconds: int.parse(responseData['expires_in'])));
_autoLogout();
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final userData = json.encode({
'token': _token,
'userId': _userId,
'expiryDate': _expiryDate.toIso8601String(),
});
prefs.setString('userData', userData);
} catch (error) {
throw error;
}
}
I edited your refresh_token() function.
Firstly, you should use your web api key on your firebase project with the link. You should also save the refresh token. And if you post like this, it will work. If don't work, try without json.encode() function on your body as I commit.
Future<void> refreshSession() async {
final url =
'https://securetoken.googleapis.com/v1/token?key=$WEB_API_KEY';
//$WEB_API_KEY=> You should write your web api key on your firebase project.
try {
final response = await http.post(
url,
headers: {
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
},
body: json.encode({
'grant_type': 'refresh_token',
'refresh_token': '[REFRESH_TOKEN]', // Your refresh token.
}),
// Or try without json.encode.
// Like this:
// body: {
// 'grant_type': 'refresh_token',
// 'refresh_token': '[REFRESH_TOKEN]',
// },
);
final responseData = json.decode(response.body);
if (responseData['error'] != null) {
throw HttpException(responseData['error']['message']);
}
_token = responseData['id_token'];
_refresh_token = responseData['refresh_token']; // Also save your refresh token
_userId = responseData['user_id'];
_expiryDate = DateTime.now()
.add(Duration(seconds: int.parse(responseData['expires_in'])));
_autoLogout();
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final userData = json.encode({
'token': _token,
'refresh_token': _refresh_token,
'userId': _userId,
'expiryDate': _expiryDate.toIso8601String(),
});
prefs.setString('userData', userData);
} catch (error) {
throw error;
}
}
This is your full auth.dart file which I edited.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../provider/http_exception.dart';
import 'dart:async';
import 'package:shared_preferences/shared_preferences.dart';
class Auth with ChangeNotifier {
String _token;
String _refresh_token;
DateTime _expiryDate;
String _userId;
Timer _authTimer;
bool wasLoggedOut = false;
bool onBoarding = false;
Future<void> createUser(String email, String firstName, String lastName) async {
final url = 'https://test45.firebaseio.com/users/$userId.json?auth=$token';
final response = await http.put(url, body: json.encode({
'userEmail': email,
'userIsArtist': false,
'userFirstName': firstName,
'userLastName': lastName,
}));
print('post ist done');
print(json.decode(response.body));
}
bool get isAuth {
return token != null;
}
String get userId {
return _userId;
}
String get token {
if (_expiryDate != null &&
_expiryDate.isAfter(DateTime.now()) &&
_token != null && _refresh_token!=null) {
return _token;
}
refreshSession();
return null;
}
Future<void> authenticate(
String email, String password, String urlSegement) async {
final url = 'https://identitytoolkit.googleapis.com/v1/accounts:$urlSegement?key=AIzaSyD8pb3M325252dfsDC-4535dfd';
try {
final response = await http.post(url,
body: json.encode({
'email': email,
'password': password,
'returnSecureToken': true,
}));
final responseData = json.decode(response.body);
if (responseData['error'] != null) {
throw HttpException(responseData['error']['message']);
}
_token = responseData['idToken'];
_refresh_token = responseData['refreshToken'];
_userId = responseData['localId'];
_expiryDate = DateTime.now().add(Duration(seconds: int.parse(responseData['expiresIn'])));
_autoLogout();
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final userData = json.encode({
'token': _token,
'refresh_token': _refresh_token,
'userId': _userId,
'expiryDate': _expiryDate.toIso8601String(),
});
prefs.setString('userData', userData);
} catch (error) {
throw error;
}
}
Future<void> signup(String email, String password) async {
return authenticate(email, password, 'signUp');
}
Future<void> signin(String email, String password) async {
return authenticate(email, password, 'signInWithPassword');
}
Future<bool> tryAutoLogin() async {
final prefs = await SharedPreferences.getInstance();
if(!prefs.containsKey('userData')){
return false;
}
final extractedUserData = json.decode(prefs.getString('userData')) as Map<String, Object>;
final expiryDate = DateTime.parse(extractedUserData['expiryDate']);
if(expiryDate.isBefore(DateTime.now())) {
return false;
}
_token = extractedUserData['token'];
_refresh_token = extractedUserData['refresh_token'];
_userId = extractedUserData['userId'];
_expiryDate = expiryDate;
notifyListeners();
_autoLogout();
return true;
}
Future<void> logout() async {
_token = null;
_refresh_token = null;
_userId = null;
_expiryDate = null;
if(_authTimer != null){
_authTimer.cancel();
_authTimer = null;
}
notifyListeners();
final prefs = await SharedPreferences.getInstance();
prefs.remove('userData');
}
void _autoLogout() {
if(_authTimer != null) {
_authTimer.cancel();
}
final timetoExpiry = _expiryDate.difference(DateTime.now()).inSeconds;
_authTimer = Timer(Duration(seconds: timetoExpiry), logout);
}
Future<void> refreshSession() async {
final url =
'https://securetoken.googleapis.com/v1/token?key=$WEB_API_KEY';
//$WEB_API_KEY=> You should write your web api key on your firebase project.
try {
final response = await http.post(
url,
headers: {
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
},
body: json.encode({
'grant_type': 'refresh_token',
'refresh_token': '[REFRESH_TOKEN]', // Your refresh token.
}),
// Or try without json.encode.
// Like this:
// body: {
// 'grant_type': 'refresh_token',
// 'refresh_token': '[REFRESH_TOKEN]',
// },
);
final responseData = json.decode(response.body);
if (responseData['error'] != null) {
throw HttpException(responseData['error']['message']);
}
_token = responseData['id_token'];
_refresh_token = responseData['refresh_token']; // Also save your refresh token
_userId = responseData['user_id'];
_expiryDate = DateTime.now()
.add(Duration(seconds: int.parse(responseData['expires_in'])));
_autoLogout();
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final userData = json.encode({
'token': _token,
'refresh_token': _refresh_token,
'userId': _userId,
'expiryDate': _expiryDate.toIso8601String(),
});
prefs.setString('userData', userData);
} catch (error) {
throw error;
}
}
}
You need to save the refresh token.
Follow this topic to refresh your IDToken using the refresh token: https://firebase.google.com/docs/reference/rest/auth#section-refresh-token
When making any calls to the API, use a function to retrieve the IDToken. This function must check if the current IDToken is still valid and, if not, ask for a new one (using the link provided).
I think the Dio library is right for you
dio = Dio();
dio.options.baseUrl = URL_API_PROD;
dio.interceptors.add(InterceptorsWrapper(
onRequest: (Options option) async{
//getToken() : you can check token expires and renew in this function
await getToken().then((result) {
token = result;
});
option.headers = {
"Authorization": "Bearer $token"
};
}
));
Response response = await dio.get('/api/users');
body expects string...Hence change body in refreshSession() to body: 'grant_type=refresh_token&refresh_token=[YOUR REFRESH TOKEN]',.
You need to load 'refreshToken' from SharedPreferences before sending http.post request.
Related
I am buidling flutter woocommerce store app for customers. I want to create/register a new customer using Dio() and I am using WordPress Plugin JWT Authentication for WP REST API for authentication. Here if i want to access URL for Customers Its showing following response. URL= "https://example.com/wp-json/wc/v3/customers"
My Custutomer Model file is:
class CustomerModel {
String email;
String firstName;
String lastName;
String password;
CustomerModel(
{required this.email,
required this.firstName,
required this.lastName,
required this.password});
Map<String, dynamic> toJson() {
Map<String, dynamic> map = {};
map.addAll({
'email': email,
'first_name': firstName,
'last_name': lastName,
'password': password,
'username': email
});
return map;
}
}
My API Service Mothod to create customer is:
Future<bool> createCustomer(CustomerModel model) async {
var authToken =
base64.encode(utf8.encode(Config.key + ':' + Config.sceret));
print(authToken);
bool ret = false;
try {
print("${Config.url+ Config.customerURL}");
var response = await Dio().post(Config.url + Config.customerURL,
data: model.toJson(),
options: new Options(headers: {
HttpHeaders.authorizationHeader: 'Basic $authToken',
HttpHeaders.contentTypeHeader: 'application/json'
}));
print(response.statusCode);
if (response.statusCode == 201) {
ret = true;
}
} on DioError catch (e) {
if (e.response?.statusCode == 404) {
ret = false;
} else {
ret = false;
}
}
return ret;
}
I am sharing my source code. Please download and solve.
https://drive.google.com/file/d/1ZFjsjeEqsGHVJXbmye_BB98gcD-bQFAW/view?usp=share_link
HttpHeaders.authorizationHeader: 'Basic $authToken'
Make this 'Bearer $authToken'
I have some mistakes with flutter and firebase, if someone can help would be great here is my auth controller
class AuthController extends GetxController {
final FirebaseAuth auth = FirebaseAuth.instance;
final Rxn<User> _firebaseUser = Rxn<User>();
Rx<XFile>? _pickedImage;
XFile? get profilePhoto => _pickedImage?.value;
// final user = FirebaseAuth.instance.currentUser.obs;
Rxn<User> get user => _firebaseUser;
// final user = FirebaseAuth.instance.currentUser;
#override
onInit() {
_firebaseUser.bindStream(auth.authStateChanges());
super.onInit();
}
// void register(
// String name, String email, String password, XFile? image) async {
// try {
// UserCredential _authResult = await auth.createUserWithEmailAndPassword(
// email: email.trim(), password: password);
// //create user in database.dart
// String downloadUrl = await uploadToStorage(image!);
// UserModel _user = UserModel(
// id: _authResult.user?.uid,
// name: name,
// email: _authResult.user?.email,
// profilePic: downloadUrl,
// );
// if (await Database().createNewUser(_user)) {
// Get.find<UserController>().user = _user;
// }
// } catch (e) {
// Get.snackbar(
// "Error creating Account",
// e.toString(),
// snackPosition: SnackPosition.BOTTOM,
// );
// }
// }
void register(
String name, String email, String password, XFile? image) async {
try {
if (name.isNotEmpty &&
email.isNotEmpty &&
password.isNotEmpty &&
image != null) {
// save out user to our ath and firebase firestore
UserCredential _authResult = await auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
String downloadUrl = await uploadToStorage(image);
UserModel _user = UserModel(
id: _authResult.user?.uid,
name: name,
email: _authResult.user?.email,
profilePic: downloadUrl,
);
if (await Database().createNewUser(_user)) {
Get.find<UserController>().user = _user;
} else {
Get.snackbar(
'Error Creating Account',
'Please enter all the fields',
);
}
}
} catch (e) {
Get.snackbar(
'Error Creating Account',
e.toString(),
);
}
}
void login(String email, password) async {
try {
UserCredential _authResult = await auth.signInWithEmailAndPassword(
email: email.trim(), password: password);
Get.find<UserController>().user =
await Database().getUser(_authResult.user?.uid ?? '');
} catch (e) {
Get.snackbar("About User", "User message",
snackPosition: SnackPosition.BOTTOM,
titleText: Text("Acount creation failed"),
messageText:
Text(e.toString(), style: TextStyle(color: Colors.white)));
}
}
Future<void> signOut() async {
await auth.signOut();
Get.find<UserController>().clear();
}
Future pickImage() async {
print("call on click add photo icon");
final ImagePicker _picker = ImagePicker();
final XFile? pickedImage =
await _picker.pickImage(source: ImageSource.gallery);
print('picked image filled with image from gallery'); //This doesnt print at
if (pickedImage != null) {
Get.snackbar('Profile Picture',
'You have successfully selected your profile picture!');
// print(pickedImage.path);
}
_pickedImage = Rx<XFile>(pickedImage!);
// print(_pickedImage);
// print(profilePhoto);
}
// upload to firebase storage
Future<String> uploadToStorage(XFile? image) async {
Reference ref = FirebaseStorage.instance
.ref('')
.child('profilePics')
.child(auth.currentUser!.uid);
// print(ref);
UploadTask uploadTask = ref.putFile(File(image?.path ?? 'idemo'));
print(uploadTask);
// TaskSnapshot snap = await uploadTask;
String downloadUrl = await (await uploadTask).ref.getDownloadURL();
print(downloadUrl);
return downloadUrl;
}
}
Here is my function to createNewUser
class Database {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<bool> createNewUser(UserModel user) async {
try {
await _firestore.collection("users").doc(user.id).set({
"name": user.name,
"email": user.email,
"profilePhoto": user.profilePic
});
return true;
} catch (e) {
print(e);
return false;
}
}
Here is HomeController
class HomeController extends GetxController {
final Rxn<List<TodoModel>> todoList = Rxn<List<TodoModel>>([]);
var selectedDate = DateTime.now().obs;
List<TodoModel>? get todos => todoList.value;
#override
void onInit() {
super.onInit();
String? uid = Get.find<AuthController>().auth.currentUser?.uid ?? '';
print(uid);
todoList.bindStream(Database().todoStream(uid));
}
chooseDate() async {
DateTime? pickedDate = await showDatePicker(
context: Get.context!,
initialDate: selectedDate.value,
firstDate: DateTime(2000),
lastDate: DateTime(2024),
//initialEntryMode: DatePickerEntryMode.input,
// initialDatePickerMode: DatePickerMode.year,
);
if (pickedDate != null && pickedDate != selectedDate.value) {
selectedDate.value = pickedDate;
}
}
}
and here is View page
GetX<HomeController>(
init: Get.put<HomeController>(HomeController()),
builder: (HomeController todoController) {
if (todoController.todos != null) {
// print(todoController.todos?.done ?? false);
return Expanded(
child: ListView.builder(
itemCount: todoController.todos?.length,
itemBuilder: (_, index) {
return TodoCard(
uid: controller.user.value?.uid ?? '',
todo: todoController.todos![index],
);
},
),
);
} else {
return Text("loading...");
}
},
),
So, I have an error when I register a new user I got this error:
The following assertion was thrown building Builder(dirty):
a document path must be a non-empty string
Failed assertion: line 116 pos 14: ‘path.isNotEmpty’
And here is output from terminal:
The relevant error-causing widget was
GetMaterialApp
lib/main.dart:23
When the exception was thrown, this was the stack
#2 _JsonCollectionReference.doc
#3 Database.todoStream
#4 HomeController.onInit
#5 GetLifeCycleBase._onStart
#6 InternalFinalCallback.call
#7 GetInstance._startController
#8 GetInstance._initDependencies
#9 GetInstance.find
#10 GetInstance.put
#11 Inst.put
So a problem is with this path, and when I reload from the visual studio I god the right user with the right data. So the problem is when I register a user for the first time.
It looks like uid is empty, which you should also be able to see from looking up print(uid); in your output.
When your application or web page loads, Firebase automatically tries to restore the previously signed in user from its local state. This requires that it makes a call to the server however (for example to check if the account has been disabled) and while that call is going on, your main code continues to execute and the currentUser variable is going to be null.
Your code needs to take this into account. The easiest way to do this is to not depend on currentUser, but instead to use an reactively respond to changes in the authentication state as shown in the first example in the documentation on getting the current user:
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user != null) {
print(user.uid);
}
});
The authStateChange method here returns a stream that fires an event whenever the authentication state changes, so when the user signs in or signs out. The common way to use this stream is to either set the user to the state of your widget, or to use the stream directly in a StreamBuilder.
I'm trying to use Firebase to login, but I'm getting Type 'Null' is not a sub type of string as error when I try to parse _userId = responseData['localId'];
When I try to parse _token = responseData['idToken'];, it works correctly.
responseData['localId'] is not NULL.
Here is full code:
class Auth with ChangeNotifier {
String? _token;
String? _userId;
Future<void> _authenticate(
String email, String password, String urlSegment) async {
var url = Uri.parse(
'https://www.google.com');
var body = json.encode({
'email': email,
'password': password,
'returnSecureToken': true,
});
try {
final response = await http.post(url, body: body);
final responseData = json.decode(response.body);
_token = responseData['idToken'];
_userId = responseData['localId'];
} catch (err) {
throw err;
}
}
Future<void> login(String email, String password) async {
return _authenticate(email, password, 'signInWithPassword');
}
}
I can log in with Facebook, but I can not register Cloud Firestore. How do I get the resources to suggest? I can log in with Google, but here I have problems. I've shared the codes below. I'm not receiving an error. The information comes from Facebook but clicking on the button on the try catch process:
Future<Kullanici> facebookIleGiris() async {
print("Login wiht facebook");
FacebookLoginResult _result = await _facebookLogin.logIn(['email']);
switch(_result.status){
case FacebookLoginStatus.cancelledByUser:
print("user logout");
break;
case FacebookLoginStatus.error:
print("error");
break;
case FacebookLoginStatus.loggedIn:
await _loginWithFacebook(_result);
break;
}
}
_loginWithFacebook(FacebookLoginResult _result) async {
FacebookAccessToken accessToken = _result.accessToken;
AuthCredential _credential =
FacebookAuthProvider.getCredential(accessToken: accessToken.token);
AuthResult result = await _firebaseAuth.signInWithCredential(_credential);
print('${result.user.uid} ');
print('${result.user.displayName} now login');
print('${result.user.email} ');
print('${result.user.photoUrl} ');
print('${result.user.phoneNumber}');
return _kullaniciOlustur(result.user);
ButtonClick
void _faceIleGiris() async {
print("user clicked");
var _yetkilendirmeServisi = Provider.of<YetkilendirmeServisi>(context, listen: false);
print("user 2. step");
try {
Kullanici kullanici = await _yetkilendirmeServisi.facebookIleGiris();
print("kullanici kontrole başladi ${kullanici.email}");
if (kullanici != null) {
print(" ${kullanici.email}");
Kullanici fireStoreKullanici = await FirestoreServisi().kullaniciGetir(kullanici.id);
if (fireStoreKullanici == null) {
print("user created ${kullanici.email}");
FirestoreServisi().kullaniciOlustur(
id: kullanici.id,
email: kullanici.email,
kullaniciAdi: kullanici.userName,
fotoUrl: kullanici.fotoUrl
);
print(" ${kullanici.email}");
print("the end");
}
}
}
catch(ex){
print(ex);
}
User.dart
import 'package:flutter/cupertino.d art';
import 'package:cloud_firestore/cloud_firestore. dart';
import 'package:firebase_auth/firebase_auth. dart';
class Kullanici{
final String id;
final String userName;
final String email;
final String fotoUrl;
Kullanici({#required this.id, this.userName, this.email, this.fotoUrl});
factory Kullanici.firebasedenUret(FirebaseUser user){
return Kullanici(id:user.uid,
userName: user.displayName,
email: user.email,
fotoUrl: user.photoUrl
);
}
factory Kullanici.dokumandanuret(DocumentSnapshot doc){
return Kullanici(
id: doc.documentID,
userName: doc['kullaniciAdi'],
email: doc['email'],
fotoUrl: doc['fotoUrl']
);
}
}
createUser method:
//Kullaniciolustur
class FirestoreServisi{
final Firestore _firestore= Firestore.instance;
Future<void> kullaniciOlustur({id,email,kullaniciAdi, fotoUrl=""}) async {
await _firestore.collection("kullanicilar").document(id).setData({
"kullaniciAdi":kullaniciAdi,
"email":email,
"fotoUrl":fotoUrl,
"dTarih":""
});
}
When the FacebookIleGiris () method is logged in with Facebook, the function to be initiated to the initiated function and the error has been solved.
facebookIleGiris() async {
print("facebook ile giriş başladi");
FacebookLoginResult _result = await _facebookLogin.logIn(['email']);
switch(_result.status){
case FacebookLoginStatus.loggedIn:
var a= await _loginWithFacebook(_result);
return a;
break;
case FacebookLoginStatus.cancelledByUser:
print("kullanici çıktı");
break;
case FacebookLoginStatus.error:
print("error");
break;
}
}
_loginWithFacebook(FacebookLoginResult _result) async {
FacebookAccessToken accessToken = _result.accessToken;
AuthCredential _credential =
FacebookAuthProvider.getCredential(accessToken: accessToken.token);
AuthResult result = await _firebaseAuth.signInWithCredential(_credential);
print('${result.user.uid} ');
print('${result.user.displayName} şimdi giriş yaptı');
print('${result.user.photoUrl} ');
print('${result.user.email} ');
print(result.runtimeType);
return _kullaniciOlustur(result.user);
I'm trying to insert data to firestore with the authenticated user id as the document id but i got null from the parameter.
Please take a look at my script.
void didChangeDependencies() {
uid = '';
super.didChangeDependencies();
}
Future _fetchUID() async {
var auth = AuthProvider.of(context).auth;
return await auth.getCurrentUser().then((user) => _uid = user.uid);
}
_validateAndSubmit() async {
setState(() {
_errorMessage = '';
_isLoading = true;
});
if (_validateAndSave()) {
try {
_fetchUID();
await Report.create(_uid, _suspectName, _plateNumber, _civilizationId,
_drivingLicenseId, _clause, _description);
return Navigator.of(context).pop();
} catch (e) {
setState(() {
_isLoading = false;
_errorMessage = e.message;
});
print(_errorMessage);
throw Exception(e);
}
}
}
In this method below you can see that I have already tried to set the _uid, but I still cannot get the _uid value.
Future _fetchUID() async {
var auth = AuthProvider.of(context).auth;
return await auth.getCurrentUser().then((user) => _uid = user.uid);
}
This is how the getCurrentUser() method looks like.
Future<FirebaseUser> getCurrentUser() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user;
}
Am I doing it wrong?
First of all, you mixed the Future.then syntax and the async await syntax.
You should probably write your method this way:
void _fetchUID() async {
var auth = AuthProvider.of(context).auth;
_uid = (await auth.getCurrentUser()).uid;
}
If _uid is still null for you after calling _fetchUID this way, then you are simply not signed in, meaning that there is no FirebaseUser as you first need to sign in.
In your _validateAndSubmit method, you also first need to await your _fetchUID call, otherwise it will pass _uid before it has been assigned a value.
...
try {
await _fetchUID();
await Report.create(_uid, ..);
...