Authenticating Flutter Application Using Laravel API and Passport
Authenticating Flutter Application Using Laravel API and Passport
Prerequisite
1. Know how to set up a laravel environment,
2. Have a flutter environment setup
3. Know how to create a flutter starter app
4. Read and complete the tutorial Laravel 6 API
Authentication with Laravel Passport. It will help
in setting up the Backend Service used for this tutorial.
5. Complete the tutorial on No 4. and keep the Laravel
server running
why flutter?
Folder structure
Create your folder structure like so:
Folder Structure
screen respectively.
network_utils/api.dart
class Network{
final String _url = 'http://localhost:8000/api/v1';
//if you are using android studio emulator, change localhost to 10.0.2.2
var token;
_getToken() async {
SharedPreferences localStorage = await
SharedPreferences.getInstance();
token = jsonDecode(localStorage.getString('token'))['token'];
}
_setHeaders() => {
'Content-type' : 'application/json',
'Accept' : 'application/json',
'Authorization' : 'Bearer $token'
};
our Laravel API.
This function checks for token stored in the user device and
assigns it to the initially defined String token;
main.dart
This is the main entry point to our application, here we will check
if the user is authenticated and return either the login screen or
the home screen.
import
'package:flutter/material.dart';
import 'package:tutorial_app/screen/login.dart';
import 'package:tutorial_app/screen/home.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(MyApp());
login.dart
import
'dart:convert';
import 'package:flutter/material.dart';
import 'package:tutorial_app/network_utils/api.dart';
import 'package:tutorial_app/screen/home.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tutorial_app/screen/register.dart';
class Login extends StatefulWidget {
@override
_LoginState createState() => _LoginState();
}
TextFormField(
style: TextStyle(color: Color(0xFF000000)),
cursorColor: Color(0xFF9b9b9b),
keyboardType: TextInputType.text,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.email,
color: Colors.grey,
),
hintText: "Email",
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
),
validator: (emailValue) {
if (emailValue.isEmpty) {
return 'Please enter email';
}
email = emailValue;
return null;
},
),
TextFormField(
style: TextStyle(color: Color(0xFF000000)),
cursorColor: Color(0xFF9b9b9b),
keyboardType: TextInputType.text,
obscureText: true,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.vpn_key,
color: Colors.grey,
),
hintText: "Password",
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
),
validator: (passwordValue) {
if (passwordValue.isEmpty) {
return 'Please enter some text';
}
password = passwordValue;
return null;
},
),
Padding(
padding: const EdgeInsets.all(10.0),
child: FlatButton(
child: Padding(
padding: EdgeInsets.only(
top: 8, bottom: 8, left: 10, right:
10),
child: Text(
_isLoading? 'Proccessing...' : 'Login',
textDirection: TextDirection.ltr,
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
),
),
),
color: Colors.teal,
disabledColor: Colors.grey,
shape: new RoundedRectangleBorder(
borderRadius:
new BorderRadius.circular(20.0)),
onPressed: () {
if (_formKey.currentState.validate()) {
_login();
}
},
),
),
],
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 20),
child: InkWell(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => Register()));
},
child: Text(
'Create new Account',
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
),
),
),
),
],
),
),
)
],
),
),
);
}
void _login() async{
setState(() {
_isLoading = true;
});
var data = {
'email' : email,
'password' : password
};
setState(() {
_isLoading = false;
});
}
}
setState(() {
_isLoading = false;
});
Collect the form values and build a data Object which will be pass
to our API call.
register.dart
TextFormField(
style: TextStyle(color: Color(0xFF000000)),
cursorColor: Color(0xFF9b9b9b),
keyboardType: TextInputType.text,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.email,
color: Colors.grey,
),
hintText: "Email",
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
),
validator: (emailValue) {
if (emailValue.isEmpty) {
return 'Please enter email';
}
email = emailValue;
return null;
},
),
TextFormField(
style: TextStyle(color: Color(0xFF000000)),
cursorColor: Color(0xFF9b9b9b),
keyboardType: TextInputType.text,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.insert_emoticon,
color: Colors.grey,
),
hintText: "First Name",
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
),
validator: (firstname) {
if (firstname.isEmpty) {
return 'Please enter your first name';
}
fname = firstname;
return null;
},
),
TextFormField(
style: TextStyle(color: Color(0xFF000000)),
cursorColor: Color(0xFF9b9b9b),
keyboardType: TextInputType.text,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.insert_emoticon,
color: Colors.grey,
),
hintText: "Last Name",
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
),
validator: (lastname) {
if (lastname.isEmpty) {
return 'Please enter your last name';
}
lname = lastname;
return null;
},
),
TextFormField(
style: TextStyle(color: Color(0xFF000000)),
cursorColor: Color(0xFF9b9b9b),
keyboardType: TextInputType.text,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.phone,
color: Colors.grey,
),
hintText: "Phone",
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
),
validator: (phonenumber) {
if (phonenumber.isEmpty) {
return 'Please enter phone number';
}
phone = phonenumber;
return null;
},
),
TextFormField(
style: TextStyle(color: Color(0xFF000000)),
cursorColor: Color(0xFF9b9b9b),
keyboardType: TextInputType.text,
obscureText: true,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.vpn_key,
color: Colors.grey,
),
hintText: "Password",
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
),
validator: (passwordValue) {
if (passwordValue.isEmpty) {
return 'Please enter some text';
}
password = passwordValue;
return null;
},
),
Padding(
padding: const EdgeInsets.all(10.0),
child: FlatButton(
child: Padding(
padding: EdgeInsets.only(
top: 8, bottom: 8, left: 10, right:
10),
child: Text(
_isLoading? 'Proccessing...' :
'Register',
textDirection: TextDirection.ltr,
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
),
),
),
color: Colors.teal,
disabledColor: Colors.grey,
shape: new RoundedRectangleBorder(
borderRadius:
new BorderRadius.circular(20.0)),
onPressed: () {
if (_formKey.currentState.validate()) {
_register();
}
},
),
),
],
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 20),
child: InkWell(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => Login()));
},
child: Text(
'Already Have an Account',
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
),
),
),
),
],
),
),
)
],
),
),
);
}
void _register()async{
setState(() {
_isLoading = true;
});
var data = {
'email' : email,
'password': password,
'phone': phone,
'fname': fname,
'lname': lname
};
setState(() {
_isLoading = false;
});
}
}
lib/main.dart
Here, we will retrieve user data stored in localStorage, and also
implement logout action.
import
'dart:convert';
import 'package:flutter/material.dart';
import 'package:tutorial_app/screen/login.dart';
import 'package:tutorial_app/network_utils/api.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
if(user != null) {
setState(() {
name = user['fname'];
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test App'),
backgroundColor: Colors.teal,
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Hi, $name',
style: TextStyle(
fontWeight: FontWeight.bold
),
),
Center(
child: RaisedButton(
elevation: 10,
onPressed: (){
logout();
},
color: Colors.teal,
shape: RoundedRectangleBorder(borderRadius:
BorderRadius.all(Radius.circular(10))),
child: Text('Logout'),
),
),
],
),
),
);
}
if(user != null) {
setState(() {
name = user['fname'];
});
}
}
You can set this user data to any variable declared to hold user
data, I set user['fname'] to a String name , this is later used in
the Text widget on line 40,
Text('Hi, $name',
style: TextStyle(
fontWeight: FontWeight.bold
),
),
Run application
Run your application on an emulator device or host your laravel
backend on heroku to properly test from an external
device. Ensure edit your base URL in any case.