API - Multitenancy - Works with Postman only - laravel

When i login through the flutter client, i receive the previous users content.
I assume this is due to an issue in the logout function.
Everything works fine in Postman(Relevant user content is presented in Postman)
lib\providers\auth_provider.dart
import 'package:demo_app/services/api.dart';
import 'package:flutter/material.dart';
class AuthProvider extends ChangeNotifier {
bool isAuthenticated = false;
late String token;
ApiService apiService = ApiService('');
Future<void> register(String name, String email, String password, String passwordConfirm, String deviceName) async{
token = await apiService.register(name, email, password, passwordConfirm, deviceName);
isAuthenticated = true;
notifyListeners();
}
Future<void> logIn(String email, String password, String deviceName) async {
token = await apiService.logIn(email, password, deviceName);
isAuthenticated = true;
notifyListeners();
}
Future<void> logOut() async {
token = '';
isAuthenticated = false;
notifyListeners();
}
}
The api.dart file looks like this
lib\services\api.dart
class ApiService{
late String token;
ApiService(this.token);
final String baseUrl = 'http://flutter-api.test/api/';
Future<List<Category>> fetchCategories() async {
http.Response response =
await http.get(Uri.parse('${baseUrl}categories'),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
HttpHeaders.acceptHeader: 'application/json',
HttpHeaders.authorizationHeader: 'Bearer $token'
},
);
List categories = jsonDecode(response.body);
return categories.map((category) => Category.fromJson(category)).toList();
}
..
..
Future<String> logIn(String email, String password, String deviceName) async {
String uri = '${baseUrl}auth/login';
http.Response response = await http.post(Uri.parse(uri),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
HttpHeaders.acceptHeader: 'application/json',
},
body: jsonEncode({
'email': email,
'password': password,
'device_name': deviceName
})
);
if(response.statusCode == 422){
Map<String, dynamic> body = jsonDecode(response.body);
Map<String, dynamic> errors = body['errors'];
String errorMessage = '';
errors.forEach((key, value){
value.forEach((element){
errorMessage += element + '\n';
});
});
throw Exception(errorMessage);
}
return response.body;
}
}
The category_privder.dart file looks like this
lib\providers\category_provider.dart
import 'package:demo_app/models/category.dart';
import 'package:demo_app/providers/auth_provider.dart';
import 'package:demo_app/services/api.dart';
import 'package:flutter/material.dart';
class CategoryProvider extends ChangeNotifier{
List<Category> categories = [];
late ApiService apiService;
late AuthProvider authProvider;
CategoryProvider(this.authProvider){
apiService = ApiService(authProvider.token);
init();
}
Future init() async{
categories = await apiService.fetchCategories();
notifyListeners();
}
Future<void> addCategory(String name) async{
try{
Category addedCategory = await apiService.addCategory(name);
categories.add(addedCategory);
notifyListeners();
} catch(e){
await authProvider.logOut();
// ignore: avoid_print
// print(e);
}
}
Future<void> updateCategory(Category category) async{
try{
Category updatedCategory = await apiService.updateCategory(category);
int index = categories.indexOf(category);
categories[index] = updatedCategory;
notifyListeners();
} catch(e){
await authProvider.logOut();
}
}
Future<void> deleteCategory(Category category) async{
try{
await apiService.deleteCategory(category.id);
categories.remove(category);
notifyListeners();
} catch(e){
await authProvider.logOut();
}
}
}
I am trying to get the flutter client to display the relevant categories of a particular user. The Laravel part seems to work well, because everything works fine in Postman
Maybe it is something to do with the BuildContext
How can i solve this issue
lib\screens\login.dart
import 'package:flutter/material.dart';
import 'package:demo_app/providers/auth_provider.dart';
// import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'dart:io';
import 'dart:async';
// import 'dart:developer' as developer;
// import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
class Login extends StatefulWidget{
const Login({super.key});
#override
State<Login> createState() => _LoginState(); // Alternative for _LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final emailController = TextEditingController();
final passwordController = TextEditingController();
String errorMessage = '';
String? deviceName;
#override
void initState() {
super.initState();
getDeviceName();
}
#override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(
title: const Text('Login'),
),
body: Container(
color: Theme.of(context).primaryColorDark,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Card(
elevation: 8,
margin: const EdgeInsets.only(left: 16.0, right: 16.0),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.emailAddress,
controller: emailController,
validator: (String? value){
if(value!.isEmpty){
return 'Enter Email';
}
return null;
},
onChanged: (text) => setState(() => errorMessage = ''),
decoration: const InputDecoration(
labelText: 'Email',
),
),
TextFormField(
obscureText: true,
enableSuggestions: false,
autocorrect: false,
controller: passwordController,
validator: (String? value){
if(value!.isEmpty){
return 'Enter password';
}
return null;
},
onChanged: (text) => setState(() => errorMessage = ''),
decoration: const InputDecoration(
labelText: 'Password',
),
),
ElevatedButton(
onPressed: () => submit(),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 36)
),
child: const Text('Login'),
),
Text(errorMessage, style: const TextStyle(color: Colors.red)),
Padding(
padding: const EdgeInsets.only(top:20.0),
child: InkWell(
onTap: () {
Navigator.pushNamed(context, '/register');
},
child: const Text("Register New User", style: TextStyle(fontSize: 14)),
),
),
],
),
)
),
),
],
),
),
);
}
Future<void> submit() async{
final form = _formKey.currentState;
if(!form!.validate()){
return;
}
final AuthProvider provider = Provider.of<AuthProvider>(context, listen: false);
try {
await provider.logIn(
emailController.text,
passwordController.text,
deviceName ?? 'Some Device'
);
} catch(e){
setState(() {
errorMessage = e.toString().replaceAll('Exception:', '');
});
}
}
Future<void> getDeviceName() async{
final deviceInfoPlugin = DeviceInfoPlugin();
try{
if (Platform.isAndroid){
var build = await deviceInfoPlugin.androidInfo;
setState((){
deviceName = build.model;
});
}
else if (Platform.isIOS){
var build = await deviceInfoPlugin.iosInfo;
setState((){
deviceName = build.model;
});
}
} on PlatformException{
setState((){
deviceName = 'Failed to get platform version';
});
}
}
}

Related

Flutter Deleting a record through the API

I am using a Laravel Api and a Flutter app as the client. This is a basic CRUD app and i was able to update the records through the API but when it comes to deleting a record, an exception is thrown and i am unable to findout the issue.
Laravel 8 App looks like this
routes\api.php
Route::apiResource('categories', \App\Http\Controllers\Api\CategoryController::class);
app\Http\Controllers\Api\CategoryController.php
public function destroy(Category $category)
{
$category->delete();
return response()->noContent();
}
Flutter App looks like this
lib\screens\categories.dart
import 'package:flutter/material.dart';
import 'package:demo_app/models/category.dart';
import 'package:demo_app/widgets/category_edit.dart';
import 'package:demo_app/providers/category_provider.dart';
import 'package:provider/provider.dart';
// import 'package:http/http.dart' as http;
class Categories extends StatefulWidget {
const Categories({super.key});
#override
CategoriesState createState() => CategoriesState();
}
class CategoriesState extends State<Categories> {
#override
Widget build(BuildContext context) {
final provider = Provider.of<CategoryProvider>(context);
List<Category> categories = provider.categories;
return Scaffold(
appBar: AppBar(
title: const Text('Categories'),
),
body: ListView.builder(
itemCount: categories.length,
itemBuilder: (context, index) {
Category category = categories[index];
return ListTile(
title: Text(category.name),
trailing:
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: const Icon(Icons.edit),
onPressed: () {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) {
return CategoryEdit(category, provider.updateCategory);
});
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () => showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('confirmation'),
content: const Text('Are you sure you want to delete?'),
actions: [
TextButton(
onPressed: () => deleteCategory(provider.deleteCategory, category),
child: const Text('Confirm')
),
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Cancel')
),
]
);
}
),
),
],
),
);
},
)
);
}
Future deleteCategory(Function callback, Category category) async{
await callback(category);
if (!mounted) return;
Navigator.pop(context);
}
}
lib\services\api.dart
// import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:demo_app/models/category.dart';
// import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class ApiService{
ApiService();
final String baseUrl = 'http://flutter-api.test/api/';
Future<List<Category>> fetchCategories() async {
http.Response response =
await http.get(Uri.parse('${baseUrl}categories'));
List categories = jsonDecode(response.body);
return categories.map((category) => Category.fromJson(category)).toList();
}
Future <Category> updateCategory(Category category) async {
// String uri = '${baseUrl}categories/$category.id';
String uri = '${baseUrl}categories/${category.id}';
http.Response response = await http.put(Uri.parse(uri),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
HttpHeaders.acceptHeader: 'application/json',
},
body: jsonEncode({'name': category.name}));
if(response.statusCode != 200){
throw Exception('Error happened on update');
}
return Category.fromJson(jsonDecode(response.body));
}
Future<void> deleteCategory(id) async {
String uri = '${baseUrl}categories/$id';
http.Response response = await http.delete(Uri.parse(uri));
if(response.statusCode != 204){
throw Exception('Error happened on delete');
}
}
}
lib\providers\category_provider.dart
// import 'dart:io';
import 'package:demo_app/models/category.dart';
import 'package:flutter/material.dart';
import 'package:demo_app/services/api.dart';
class CategoryEdit extends StatefulWidget {
final Category category;
final Function categoryCallback;
const CategoryEdit(this.category, this.categoryCallback, {Key? key}) : super(key: key);
#override
CategoryEditState createState() => CategoryEditState();
}
class CategoryEditState extends State<CategoryEdit> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final categoryNameController = TextEditingController();
ApiService apiService = ApiService();
String errorMessage = '';
#override
void initState(){
categoryNameController.text = widget.category.name;
super.initState();
}
#override
Widget build(BuildContext context){
return Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: Column(children: <Widget>[
TextFormField(
onChanged: (text) => setState(() => errorMessage = ''),
controller: categoryNameController,
validator: (String? value) {
if (value!.isEmpty) {
return 'Enter category name';
}
return null;
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Category Name',
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
ElevatedButton(
child: const Text('Save'),
onPressed: () => saveCategory(context),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red
),
child: const Text('Cancel'),
onPressed: () => Navigator.pop(context),
),
],
),
Text(errorMessage, style: const TextStyle(color: Colors.red),)
]
)
)
);
}
Future saveCategory(BuildContext context) async {
final form = _formKey.currentState;
if(!form!.validate())
{
return;
}
widget.category.name = categoryNameController.text;
await widget.categoryCallback(widget.category);
if (!mounted) return;
Navigator.pop(context);
}
}
This is the exception i get
flutter: Exception: Error happened on delete
It returns the Error Code 500 and i was able to sort the error from the Server side

MissingPluginException(No implementation found for method login on channel app.meedu/flutter_facebook_auth)

i got this error but not solve.i follow the step properly
this is code of my login page
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:provider/provider.dart';
class loginpage extends StatefulWidget {
const loginpage({Key? key}) : super(key: key);
#override
State<loginpage> createState() => _loginpageState();
}
enum LoginType { facebook, google, apple }
class _loginpageState extends State<loginpage> {
FirebaseAuth _auth = FirebaseAuth.instance;
bool _fetching = true;
User? get _currentUser => _auth.currentUser;
#override
void initState() {
super.initState();
_checkLogin();
}
Future<void> _checkLogin() async {
await Future.delayed(Duration(seconds: 1));
_fetching = false;
setState(() {});
}
void _login(LoginType type) async {
setState(() {
_fetching = true;
});
OAuthCredential? credential;
if (type == LoginType.facebook) {
credential = (await _loginWithFacebook()) as OAuthCredential;
} else if (type == LoginType.google) {
credential = (await _loginWithGoogle()) as OAuthCredential;
}
if (credential != null) {
await _auth.signInWithCredential(credential);
}
setState(() {
_fetching = false;
});
}
Future<OAuthCredential?> _loginWithFacebook() async {
final AccessToken accessToken = (await FacebookAuth.instance.login()) as AccessToken;
print(accessToken);
return FacebookAuthProvider.credential(
accessToken.token,
);
}
Future<OAuthCredential?> _loginWithGoogle() async {
try {
final GoogleSignInAccount? account = await GoogleSignIn(scopes: ['email']).signIn();
if (account != null) {
// Obtain the auth details from the request
final GoogleSignInAuthentication googleAuth = await account.authentication;
return GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
}
return null;
} catch (e) {
print(e);
return null;
}
}
Future<void> _logOut() async {
final List<UserInfo> data = _currentUser!.providerData;
String providerId = "firebase";
for (final item in data) {
if (item.providerId != "firebase") {
providerId = item.providerId;
break;
}
}
await _auth.signOut();
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
width: double.infinity,
height: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (!_fetching && _currentUser == null)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () => _login(LoginType.facebook),
child: Text("FACEBOOK"),
),
SizedBox(width: 10),
TextButton (
onPressed: () => _login(LoginType.google),
child: Text("GOOGLE"),
),
],
),
if (_fetching) CircularProgressIndicator(),
if (_currentUser != null) ...[
Text("HI ...."),
Text(_currentUser!.displayName ??" "),
SizedBox(height: 20),
TextButton(
onPressed: _logOut,
child: Text("LOG OUT"),
),
]
],
),
),
),
);
}
}
how to solve this? i follow all instruction properly.

User Login with Wrong Credintials in Flutter/Laravel API

I develop Flutter app with Laravel backend when I test logon through Postman it works well and I receive tokens and when I give wrong username or password it gives me error.
Here is the Login function:
login(String email, String password) async{
var url = '$serverUrl/login';
final response = await http.post(url,
headers: {
'Accept':'application/json'
},
body: {
"email":"$email",
"password":"$password"
}
);
status = response.body.contains('error');
var data = json.decode(response.body);
if(status){
print('data : ${data["error"]}');
}else{
print('data : ${data["token"]}');
_save(data["token"]);
}
}
But when I build the Flutter app it allows Login with wrong usernames or password and navigate to Dashboard screen.
This is Login page code
class LoginPageState extends State<LoginPage>{
DataBaseHelper dataBaseHelper = new DataBaseHelper();
String msgStatus;
final TextEditingController _emailController = new TextEditingController();
final TextEditingController _passwordController = new TextEditingController();
_onPressed(){
setState(() {
if(_emailController.text.trim().toLowerCase().isNotEmpty &&
_passwordController.text.trim().isNotEmpty){
dataBaseHelper.login(_emailController.text.trim().toLowerCase(),
_passwordController.text.trim()).whenComplete((){
if(dataBaseHelper.status){
_showDialog();
msgStatus = 'Check email or password';
debugPrint("${_emailController.text.trim().toLowerCase()} ${_passwordController.text.trim()}" );
}else{
Navigator.pushReplacementNamed(context, '/dashboard');
}
});
}
});
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
title: 'login',
home: Scaffold(
appBar: AppBar(
title: Text('Login'),
),
body: Container(),
),
);
}
void _showDialog(){
showDialog(
context:context,
builder : (BuildContext context){
return AlertDialog(
title: Text('Failed'),
content: Text('Check your email or password'),
actions: [
RaisedButton(
onPressed: (){
Navigator.of(context).pop();
},
child: Text('Close',
),
),
],
);
});
}
}
Laravel side:
class APILoginController extends Controller
{
//
public function login(Request $request){
$validator = Validator::make($request -> all(),[
'email' => 'required|string|email|max:255',
'password' =>'required'
]);
if($validator->fails()){
return response()->json($validator->errors());
}
$credentials = $request->only('email', 'password');
try {
if(! $token = JWTAuth::attempt($credentials)
){
return response()->json(['error'=>'invalid username or password'], [401]);
}
} catch (JWTException $e) {
//throw $th;
return response()->json(['error'=>'could not create token'], [500]);
}
return response()->json(compact('token'));
}
}

LogIn screen skipped on flutter

Currently I am designing my UI for the login screen and Firebase authentication is already in effect as I can see the username on the firebase console, however I try to edit my UI for the login screen, but the login screen is skipped and is continuously logged in, so I cannot see the changes I am making for the UI of my login screen, here is my code:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'home.dart';
class Login extends StatefulWidget {
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
final GoogleSignIn googleSignIn = new GoogleSignIn();
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
SharedPreferences preferences;
bool loading = false;
bool isLogedin = false;
#override
void initState() {
super.initState();
isSignedIn();
}
void isSignedIn() async {
setState(() {
loading = true;
});
preferences = await SharedPreferences.getInstance();
isLogedin = await googleSignIn.isSignedIn();
if (isLogedin) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => HomePage()));
}
setState(() {
loading = false;
});
}
Future handleSignIn() async {
preferences = await SharedPreferences.getInstance();
setState(() {
loading = true;
});
GoogleSignInAccount googleUser = await googleSignIn.signIn();
GoogleSignInAuthentication googleSignInAuthentication =
await googleUser.authentication;
AuthCredential credential = GoogleAuthProvider.getCredential(
idToken: googleSignInAuthentication.idToken,
accessToken: googleSignInAuthentication.accessToken);
FirebaseUser firebaseUser =
(await firebaseAuth.signInWithCredential(credential)).user;
if (firebaseUser != null) {
final QuerySnapshot result = await Firestore.instance
.collection("users")
.where("id", isEqualTo: firebaseUser.uid)
.getDocuments();
final List<DocumentSnapshot> documents = result.documents;
if (documents.length == 0) {
//insert the user to our collection
Firestore.instance
.collection("users")
.document(firebaseUser.uid)
.setData({
"id": firebaseUser.uid,
"username": firebaseUser.displayName,
"profilePicture": firebaseUser.photoUrl
});
await preferences.setString("id", firebaseUser.uid);
await preferences.setString("username", firebaseUser.displayName);
await preferences.setString("photUrl", firebaseUser.displayName);
} else {
await preferences.setString("id", documents[0]['id']);
await preferences.setString("username", documents[0]['username']);
await preferences.setString("photoUrl", documents[0]['photoUrl']);
}
Fluttertoast.showToast(msg: "Login was successful");
setState(() {
loading = false;
});
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => HomePage()));
} else {
Fluttertoast.showToast(msg: "Login failed :(");
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
centerTitle: true,
title: new Text(
"Login",
style: TextStyle(color: Colors.red.shade900),
),
elevation: 0.1,
),
body: Stack(children: <Widget>[
Visibility(
visible: loading ?? true,
child: Center(
child: Container(
alignment: Alignment.center,
color: Colors.white.withOpacity(0.9),
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
))))
,
]),
bottomNavigationBar: Container(
child: Padding(
padding: const EdgeInsets.only(left:12.0, right: 12, top: 12, bottom: 12),
child: FlatButton(
color: Colors.red.shade900,
onPressed: () {
handleSignIn();
},
child: Text(
'Sign in/ Sign up with Google',
style: TextStyle(color: Colors.white),
)),
),
),
);
}
}
This is my code for the UI of login, however I cannot see the edits I am making on this on my emulator, as the login screen just skips (actually it appears for like 0.5 seconds and goes directly to the homepage). Could someone help me out?
You are navigating the logged-in user to the home page.
void isSignedIn() async {
setState(() {
loading = true;
});
preferences = await SharedPreferences.getInstance();
isLogedin = await googleSignIn.isSignedIn();
if (isLogedin) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => HomePage()));
}
setState(() {
loading = false;
});
}
Either you can implement Logout in the app or just comment out the auto logged in part until your testing finish.

How can I login on Flutter app with Laravel basic authenticaiton using email and password

After creating a new Laravel project, what I did was only making authentication using php artisan make:auth. I needed to get CSRF token to log in on the Flutter app, so I simple commented out CSRF token in the middleware.
The error I am getting is 302 which is redirection error. I was redirected to '/home'. So, I just simply returned 'User data' when successfully logged in, but I am still getting the same error. There is not enough documentation about Flutter of how to authenticate using email and password if i have web service already deployed on the web hosting company.
If I installed basic authentication on Laravel, how can I authenticate on Flutter? I don't need CSRF token for now for testing purposes.
flutter login code
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:embedded_mobile/screens/home.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:embedded_mobile/models/user.dart';
var routes = <String, WidgetBuilder>{
"/home": (BuildContext context) => HomeScreen(),
"/login": (BuildContext context) => LoginWithRestfulApi(),
};
class LoginWithRestfulApi extends StatefulWidget {
#override
_LoginWithRestfulApiState createState() => _LoginWithRestfulApiState();
}
class _LoginWithRestfulApiState extends State<LoginWithRestfulApi>
with TickerProviderStateMixin {
static var uri = "http://blackboardembedded.dx.am";
static BaseOptions options = BaseOptions(
baseUrl: uri,
responseType: ResponseType.plain,
connectTimeout: 30000,
receiveTimeout: 30000,
followRedirects: false,
validateStatus: (code) {
return code < 500;
});
static Dio dio = Dio(options);
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
TextEditingController _emailController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
bool _isLoading = false;
Future<bool> _onBackPressed() {}
Future<dynamic> _loginUser(String email, String password) async {
try {
Options options = Options(
contentType: ContentType.parse('application/json'),
);
Response response = await dio.post('/login',
data: {"email": email, "password": password}, options: options);
if (response.statusCode == 200 ||
response.statusCode == 201 ) {
var responseJson = json.decode(response.data);
return responseJson;
} else if (response.statusCode == 401) {
throw Exception("Incorrect Email/Password");
} else
throw Exception('Authentication Error');
} on DioError catch (exception) {
if (exception == null ||
exception.toString().contains('SocketException')) {
throw Exception("Network Error");
} else if (exception.type == DioErrorType.RECEIVE_TIMEOUT ||
exception.type == DioErrorType.CONNECT_TIMEOUT) {
throw Exception(
"Could'nt connect, please ensure you have a stable network.");
} else {
return null;
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
leading: new IconButton(
icon: new Icon(Icons.arrow_back, color: Colors.black),
onPressed: () => Navigator.of(context).pushNamed('/login'),
),
title: Text("Send Location")),
body: Center(
child: Container(
child: _isLoading
? CircularProgressIndicator()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(20.0),
child: TextField(
controller: _emailController,
decoration: InputDecoration(
hintText: 'Email',
),
),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: TextField(
controller: _passwordController,
decoration: InputDecoration(
hintText: 'Password',
),
),
),
new SizedBox(
width: 200,
height: 50,
child: RaisedButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(50.0)),
child: Text("Login"),
color: Colors.amber,
onPressed: () async {
setState(() => _isLoading = true);
var res = await _loginUser(
_emailController.text, _passwordController.text);
setState(() => _isLoading = false);
JsonUser user = JsonUser.fromJson(res);
if (user != null) {
Navigator.of(context).push(MaterialPageRoute<Null>(
builder: (BuildContext context) {
return new LoginScreen(
user: user,
);
}));
} else {
Scaffold.of(context).showSnackBar(SnackBar(
content:
Text("Email or password is incorrect")));
}
},
),
),
],
),
),
),
);
}
}
class LoginScreen extends StatelessWidget {
LoginScreen({#required this.user});
final JsonUser user;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Login Screen")),
body: Center(
child: user != null
? Text("Logged IN \n \n Email: ${user.email} ")
: Text("Yore not Logged IN"),
),
);
}
}
for your app, you need to authenticate users over the api routes, which does not require CSRF tokens by default. you can achieve this using Laravel Passport or JWT auth

Resources