saved token in login page and how to receive it on List page in flutter? - flutter

I have two pages,
Login page
list page
Already saved token in login page, but how to receive it on list page inside Future?
Login page response
Future<Album> createAlbum(String employee_custom_id, String password) async {
final response = await http.post(
Uri.parse('https://portal-api.jomakhata.com/api/auth/login'),
headers: <String, String>{
'Content-Type': 'application/json',
},
body: jsonEncode(<String, String>{
'employee_custom_id': employee_custom_id,
'password': password,
}),
);
final data = json.decode(response.body);
if (response.statusCode == 200) {
saveToken(data);
log('$data');
return Album.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to create album.');
}
}
//save token
void saveToken(data) async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("token", data['token']);
sharedPreferences.setInt("userId", data['userId']);
}
Now i want to received it on list page, but can't set it on token section
**List page **
Future<List<ListAlbum>> listData() async {
final token = // I want to receive token here that i saved in login page.
String url =
'https://portal-api.jomakhata.com/api/getOrganizationData?token=${token}';
Dio dio = new Dio();
dio.options.headers['Content-Type'] = 'application/json';
final body = {'limit': 100, 'orderBy': 'idEmployee', 'orderType': 'DESC'};
final response = await dio.post(url, data: body);
}

If I understand correctly you are asking this
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
final token = sharedPreferences.getString("token");

Wouldn't this make sense?
Future<List<ListAlbum>> listData() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
final token = sharedPreferences.getString("token");
String url =
'https://portal-api.jomakhata.com/api/getOrganizationData?token=${token}';
Dio dio = new Dio();
dio.options.headers['Content-Type'] = 'application/json';
final body = {'limit': 100, 'orderBy': 'idEmployee', 'orderType': 'DESC'};
final response = await dio.post(url, data: body);
}

Related

An optimize way for tryAutoLogin function in flutter?

I want to create a function for auto login like Facebook in flutter but don't know the best way to do it.
My function for login and auto login, I used SharedPreferences plugin for store data.
SignIn function:
Future<void> signIn(String userName, String pass) async {
final url = Uri.parse('MyAPI_login');// sorry it for privacy
debugPrint("$userName / $pass");
try {
var respone = await http.post(url, body: {
'user_name': userName,
'password': pass,
'platform': 'mobile',
'device_token': '',
});
final reponseData = jsonDecode(respone.body);
_userName = userName;
_token = reponseData['data']['accessToken'];
_expiryDate = DateTime.now().add(Duration(
seconds: int.parse(reponseData['data']['tokenExpireAt'].toString())));
_refreshToken = reponseData['data']['refreshToken'].toString();
_timerRefreshToken =
int.parse(reponseData['data']['refreshTokenExpireAt'].toString());
// debugPrint(
// '$_token \n $_expiryDate \n $_refreshToken \n $_timerRefreshToken');
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final userData = json.encode({
'_userId': _userName.toString(),
'token': _token.toString(),
'expiryDate': _expiryDate!.toIso8601String(),
'refreshToken': _refreshToken,
'timerRefreshToken': _timerRefreshToken.toString(),
});
await prefs.setString('userData', userData);
} catch (error) {
throw Exception(error.toString());
}}
TryAutoLogin function:
Future<bool> tryAutoLogin() async {
final prefs = await SharedPreferences.getInstance();
if (!prefs.containsKey('userData')) {
return false;
}
final extractedUserData = json
.decode(prefs.getString('userData').toString()) as Map<String, dynamic>;
final expiryDate =
DateTime.parse(extractedUserData['expiryDate'].toString());
if (expiryDate.isBefore(DateTime.now())) {
_token = extractedUserData['refreshToken'].toString();
_expiryDate = DateTime.now().add(
Duration(seconds: int.parse(extractedUserData['timerRefreshToken'])));
_refreshNewToken(extractedUserData['refreshToken'].toString());
}
return true;}
RefreshNewToken function:
Future<void> _refreshNewToken(String oldRefreshToken) async {
final url =
Uri.parse('MyAPI_refreshtoken');
var respone = await http.post(url, body: {'refreshToken': oldRefreshToken});
debugPrint(respone.body);}
My API for login response is like this:
{"data":{"tokenKey":"Authorization","tokenType":"Bearer","accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl9pZCI6ImE1YzkyMTQwLTA3Y2YtMTFlZC1hNDQ2LTYzY2YyNjNiZjllMiIsInVzZXJfaWQiOiJDODAzQ0I3RS1CQTcyLTQ4NjgtQjdEMC05NkRBOUNCREQyMTkiLCJ1c2VyX25hbWUiOiIxMDAyMCIsImZ1bGxfbmFtZSI6IkzDqiBUaOG7iyBMacOqbiIsImlzQWRtaW5pc3RyYXRvciI6MCwidXNlcl9jb21wYW5pZXMiOltdLCJpYXQiOjE2NTgyODIzOTMsImV4cCI6MTY1ODI4NTk5M30.3kMByfweUhzQM-4d5S0G7tUaC0e-nZLJF3_dbdV_7fM","tokenExpireAt":1658285940964,"refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl9pZCI6ImE1YzkyMTQwLTA3Y2YtMTFlZC1hNDQ2LTYzY2YyNjNiZjllMiIsInVzZXJfaWQiOiJDODAzQ0I3RS1CQTcyLTQ4NjgtQjdEMC05NkRBOUNCREQyMTkiLCJ1c2VyX25hbWUiOiIxMDAyMCIsImZ1bGxfbmFtZSI6IkzDqiBUaOG7iyBMacOqbiIsImlzQWRtaW5pc3RyYXRvciI6MCwidXNlcl9jb21wYW5pZXMiOltdLCJpYXQiOjE2NTgyODIzOTMsImV4cCI6MTY1ODM2ODc5M30.Bv7PZrnx9zDzwIuxNMppFxlwZlJEnthVjEYBKYl-aWM","refreshTokenExpireAt":1658368740964},"message":"Logged in successfully!","status":200,"errors":null}
Also, my API has a refresh token request, it returns like this:
{"data":{"tokenKey":"Authorization","tokenType":"Bearer","accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl9pZCI6ImE1ZjQyOGUwLTA3Y2YtMTFlZC1hNDQ2LTYzY2YyNjNiZjllMiIsInVzZXJfaWQiOiJDODAzQ0I3RS1CQTcyLTQ4NjgtQjdEMC05NkRBOUNCREQyMTkiLCJ1c2VyX25hbWUiOiIxMDAyMCIsImZ1bGxfbmFtZSI6IkzDqiBUaOG7iyBMacOqbiIsImlzQWRtaW5pc3RyYXRvciI6MCwidXNlcl9jb21wYW5pZXMiOltdLCJpYXQiOjE2NTgyODIzOTQsImV4cCI6MTY1ODI4NTk5NH0.wcyouoprMHFnRD4_oSpP9RSasxMBrktX6nZI2x2PQec","tokenExpireAt":1658285940242,"refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl9pZCI6ImE1ZjQyOGUwLTA3Y2YtMTFlZC1hNDQ2LTYzY2YyNjNiZjllMiIsInVzZXJfaWQiOiJDODAzQ0I3RS1CQTcyLTQ4NjgtQjdEMC05NkRBOUNCREQyMTkiLCJ1c2VyX25hbWUiOiIxMDAyMCIsImZ1bGxfbmFtZSI6IkzDqiBUaOG7iyBMacOqbiIsImlzQWRtaW5pc3RyYXRvciI6MCwidXNlcl9jb21wYW5pZXMiOltdLCJpYXQiOjE2NTgyODIzOTQsImV4cCI6MTY1ODM2ODc5NH0.y-8MP4M_1LzCwmqo_KQZGyQXkycrxdOLWz_fdqIPRyQ","refreshTokenExpireAt":1658368740242},"message":"Request successfully!","status":200,"errors":null}

I create flutter with api call but the data not showing at fresh install

So I create an app with rest API, but the data not showing on a fresh install
This is for gettoken and save to shared prefs
getInit() async {
String myUrl = "$serverUrl/get-token";
http.Response response = await http.post(Uri.parse(myUrl),
body: {'secret': 'code'});
debugPrint(response.statusCode.toString());
debugPrint(response.body);
var data = json.decode(response.body)["data"];
_save(data["access_token"]);
// return data;
}
//SAVE TOKEN
_save(String token) async {
final prefs = await SharedPreferences.getInstance();
const key = 'token';
final value = token;
prefs.setString(key, value);
debugPrint("new token save " + value);
}
This for getlist item, need bearer access token from shared prefs
getRecList() async {
final prefs = await SharedPreferences.getInstance();
const key = 'token';
final value = prefs.get(key) ?? 0;
String myUrl = "$serverUrl/home";
http.Response response = await http.get(Uri.parse(myUrl), headers: {
'Accept': 'application/json',
'Authorization': 'Bearer $value'
});
debugPrint(response.body);
if (response.statusCode == 200) {
List data = jsonDecode(response.body)['data'];
List<ModelKost> modelkost =
data.map((item) => ModelKost.fromJson(item)).toList();
return modelkost;
} else {
return <ModelKost>[];
}
}
So every time I fresh install, home page does not show any data because getRecList item is forbidden access...
The log says token success, but getRecList fails because not get access token, it only happens on fresh install if I refresh/hot reload the list showing normally ...
so I guess the function getRecList wrong here, but I have no idea to fix it ...
i think the problem is you are not waiting for token value. use await when geting value from shared preferences
So I create an app with rest API, but the data not showing on a fresh install
getRecList() async {
final prefs = await SharedPreferences.getInstance();
const key = 'token';
final value =await prefs.get(key) ?? 0; //use await here
String myUrl = "$serverUrl/home";
http.Response response = await http.get(Uri.parse(myUrl), headers: {
'Accept': 'application/json',
'Authorization': 'Bearer $value'
});
debugPrint(response.body);
if (response.statusCode == 200) {
List data = jsonDecode(response.body)['data'];
List<ModelKost> modelkost =
data.map((item) => ModelKost.fromJson(item)).toList();
return modelkost;
} else {
return <ModelKost>[];
}
}

how to do post request if there is multiple image to be sent with other data

#I am trying to sent my data through rest api all my data seem to be sent accept for my image
static Future<String> postHomework(String classId,String sectionId,String subjectId,String homeWorkTitle,String link,String homeworkDetail, List<XFile> homeworkImage,String submissionDate,BuildContext context) async{
String userData;
String token;
SharedPreferences prefs = await SharedPreferences.getInstance();
userData = prefs.getString("userData");
if(userData!=null){
token = json.decode(userData)['token'];
}else{
return null;
}
http.MultipartRequest request = http.MultipartRequest("POST",Uri.parse("Api goes here"));
Map<String,String> headers = {"Content-Type":"multipart/form-data",'Authorization': 'Bearer $token'};
var bytes = await Future.wait(homeworkImage.map((image) =>image.readAsBytes()));
request.files.addAll(bytes.map((b) =>http.MultipartFile.fromBytes('file', b)));
request.headers.addAll(headers);
request.fields['classid'] = classId;
request.fields['subjectid'] =subjectId;
request.fields['content'] = homeworkDetail;
request.fields['title'] = homeWorkTitle;
request.fields['submission_date'] = submissionDate;
request.fields['section_id'] = sectionId;
http.StreamedResponse responseAttachmentSTR = await request.send();
final reqAttachment = request.files.length;
if(responseAttachmentSTR.statusCode == 200){
print(reqAttachment);
Navigator.of(context).pushNamed("Homework-section-subject-list");
}
print(responseAttachmentSTR.statusCode);
return "SENT";
}
the problem is i am not able to send the images i picked from my gallery to server
Check this out.
I think you have to listen to the response like this :
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});

Flutter: What is the Correct approach to get value from Future?

I have a function that which returns user token, and saves it to shared preference, if token is present it saves it to SP. Another method awaits for the token and if token is present authenticates user
Here is my code
login(username, password) async {
final String url = "http://10.0.2.2:8080/api/auth/signin"; // iOS
final http.Response response = await http.post(
url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'username': username,
'password': password,
}),
);
LoginModel userSave = loginModelFromJson(response.body);
print(response.body);
final SharedPreferences prefs = await SharedPreferences.getInstance();
bool result = await prefs.setString('user', jsonEncode(userSave));
print(result);
}
This piece of code works as expected, but I'm having issue getting the token value from Future.
Case Scenario: User enters username and password and authenticates with server. Incase account exists a token is generated from server and sent to app and stored in shared prefs. token if available is picked from shared prefs and used to login to app, but the check of the token is done before it is generated and saved
Future<LoginModel> getUserInfo() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
Map<String, dynamic> userMap;
final String userStr = prefs.getString('user');
if (userStr != null) {
userMap = jsonDecode(userStr) as Map<String, dynamic>;
}
if (userMap != null) {
final LoginModel user = LoginModel.fromJson(userMap);
print(user);
return user;
}
return null;
}
the token gets called way before it is saved throwing an error of null
RoundedButton(
text: "LOGIN",
press: () async {
if (_formKey.currentState.validate()) {
progressDialog.show();
await login(
username,
password,
);
SharedPreferences prefs =
await SharedPreferences.getInstance();
String token = prefs.getString("accessToken");
getUserInfo();
// ignore: null_aware_in_condition
if (token == null) {
progressDialog.hide();
showAlertsDialog(context);
// ignore: null_aware_in_condition
} else {
progressDialog.hide();
showAlertzDialog(context);
}
}
},
),
I believe there is very small logical mistake, but unable to find it myself.
I believe you cannot directly call jsonEncode with a custom object like the way you do it in jsonEncode(userSave). Do print(jsonEncode(userSave)); to see if the value is properly being converted into a string.

How to get the token for register api in flutter

I am having the Url for Token generation,by using http post i am getting the token.now my problem was i have to use the generated token as header in register api(another api).
Future<Map<String, dynamic>> fetchPost() async {
print('feg');
final response = await http.post(
'/rest_api/gettoken&grant_type=client_credentials',
headers: {HttpHeaders.authorizationHeader: "Basic token"},
);
final responseJson = json.decode(response.body);
print("Result: ${response.body}");
//return Post.fromJson(responseJson);
return responseJson;
}
here i am getting the token i want to use that token to register api
Future<Register> fetchPost() async {
print('feg');
final response = await http.post(
'your base url/rest/register/register',
headers: { HttpHeaders.authorizationHeader: "Bearer token",
HttpHeaders.contentTypeHeader: "application/json"},
);
var responseJson = json.decode(response.body);
print("Result: ${response.body}");
return Register.fromJson(responseJson);
}
this is the post method for register api,i want to use previously generated bearer token in above api headers.
Another option, is use secure storage whit Keychain (Android) and Keystore (iOS)
https://pub.dev/packages/flutter_secure_storage
Add in your pubspec.yaml
dependencies:
flutter_secure_storage: ^3.2.1+1
And in your code, import library and save
Future<Map<String, dynamic>> fetchPost() async {
final storage = FlutterSecureStorage();
print('feg');
final response = await http.post(
'/rest_api/gettoken&grant_type=client_credentials',
headers: {HttpHeaders.authorizationHeader: "Basic token"},
);
final responseJson = json.decode(response.body);
print("Result: ${response.body}");
//return Post.fromJson(responseJson);
/// Write token in token key with security
await prefs.write(key: 'token',value: responseJson['token']);
return responseJson;
}
If you need read, use this code:
Future<Register> fetchPost() async {
final storage = FlutterSecureStorage();
print('feg');
String token = await storage.read(key: 'token');
final response = await http.post(
'your base url/rest/register/register',
headers: { HttpHeaders.authorizationHeader: token,
HttpHeaders.contentTypeHeader: "application/json"},
);
var responseJson = json.decode(response.body);
print("Result: ${response.body}");
return Register.fromJson(responseJson);
}
you can save the generated token in the shared preferences. Then you can use it in any request later.
first add in pubspec.yaml
dependencies:
shared_preferences: ^0.5.3+4
then import it in your code:
import 'package:shared_preferences/shared_preferences.dart';
so when you get your token
Future<Map<String, dynamic>> fetchPost() async {
print('feg');
final response = await http.post(
'/rest_api/gettoken&grant_type=client_credentials',
headers: {HttpHeaders.authorizationHeader: "Basic token"},
);
final responseJson = json.decode(response.body);
print("Result: ${response.body}");
//return Post.fromJson(responseJson);
SharedPreferences prefs = await SharedPreferences.getInstance();
//now set the token inside the shared_preferences
//I assumed that the token is a field in the json response, but check it before!!
await prefs.setString('token',responseJson['token']);
return responseJson;
}
and when you need to send the request just get the token from the shared_preferences:
Future<Register> fetchPost() async {
print('feg');
SharedPreferences prefs = await SharedPreferences.getInstance();
String token = prefs.getString('token');
final response = await http.post(
'your base url/rest/register/register',
headers: { HttpHeaders.authorizationHeader: token,
HttpHeaders.contentTypeHeader: "application/json"},
);
var responseJson = json.decode(response.body);
print("Result: ${response.body}");
return Register.fromJson(responseJson);
}