Implementing User Authentication in Flutter: A Step-by-Step Guide to Login with API

 In this tutorial, we will walk you through the process of implementing user authentication in a Flutter application using an API. We will cover everything from setting up the project to handling login errors gracefully.


api_service.dart

class ApiService {
final String _baseUrl = 'http://hyperquiz.hirenow.co.in/api/login';

Future<LoginResponse> login(String username, String password) async {
final url = Uri.parse(_baseUrl);

final headers = {
'Authorization': 'Bearer 35|3c6l1ZQvk2EGl6kE7TIOHaCRXp6FpuzzSbXFhnBs',
'Content-Type': 'application/json',
};

final body = json.encode({
'username': username,
'password': password,
});

final response = await http.post(
url,
headers: headers,
body: body,
);

final Map<String, dynamic> responseData = json.decode(response.body);

if (response.statusCode == 200) {
if (responseData['status'] == 'error') {
throw Exception(responseData['message']['error'][0]);
}
return LoginResponse.fromJson(responseData);
} else {
throw Exception('Failed to login: ${response.reasonPhrase}');
}
}
}

login_screen.dart

class LoginScreen extends StatefulWidget {
@override
_LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final ApiService _apiService = ApiService();
String _errorMessage = '';

void _login() async {
final username = _usernameController.text;
final password = _passwordController.text;

setState(() {
_errorMessage = '';
});

try {
final loginResponse = await _apiService.login(username, password);
// Handle successful login
print('Login successful: ${loginResponse.data.accessToken}');
print('User: ${loginResponse.data.user.username}');

// Save user ID to SharedPreferences
// SharedPreferences prefs = await SharedPreferences.getInstance();
// await prefs.setInt('userId', loginResponse.data.user.id);

// Navigate to home screen or any other screen
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => HomeScreen()),
// );

} catch (e) {
// Handle login failure
setState(() {
_errorMessage = e.toString().replaceAll('Exception: ', '');
});
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Login'),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
children: [
if (_errorMessage.isNotEmpty)
Text(
_errorMessage,
style: TextStyle(color: Colors.red),
),
TextField(
controller: _usernameController,
decoration: InputDecoration(labelText: 'Username'),
),
TextField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _login,
child: Text('Login'),
),
],
),
),
);
}
}

main.dart

// Main function and MyApp widget
void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Login Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: LoginScreen(),
);
}
}

models.dart

class Address {
final String? country;
final String address;
final String state;
final String zip;
final String city;

Address({
this.country,
required this.address,
required this.state,
required this.zip,
required this.city,
});

factory Address.fromJson(Map<String, dynamic> json) {
return Address(
country: json['country'],
address: json['address'],
state: json['state'],
zip: json['zip'],
city: json['city'],
);
}
}

class User {
final int id;
final String firstname;
final String lastname;
final String username;
final String? avatar;
final String email;
final String? countryCode;
final String? mobile;
final int refBy;
final String? referralCode;
final Address address;
final int status;
final dynamic kycData;
final int kv;
final int ev;
final int sv;
final int profileComplete;
final dynamic verCodeSendAt;
final int ts;
final int tv;
final dynamic tsc;
final dynamic banReason;
final int coins;
final int score;
final dynamic loginBy;
final int deleteStatus;
final DateTime createdAt;
final DateTime updatedAt;

User({
required this.id,
required this.firstname,
required this.lastname,
required this.username,
this.avatar,
required this.email,
this.countryCode,
this.mobile,
required this.refBy,
this.referralCode,
required this.address,
required this.status,
this.kycData,
required this.kv,
required this.ev,
required this.sv,
required this.profileComplete,
this.verCodeSendAt,
required this.ts,
required this.tv,
this.tsc,
this.banReason,
required this.coins,
required this.score,
this.loginBy,
required this.deleteStatus,
required this.createdAt,
required this.updatedAt,
});

factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
firstname: json['firstname'],
lastname: json['lastname'],
username: json['username'],
avatar: json['avatar'],
email: json['email'],
countryCode: json['country_code'],
mobile: json['mobile'],
refBy: json['ref_by'],
referralCode: json['referral_code'],
address: Address.fromJson(json['address']),
status: json['status'],
kycData: json['kyc_data'],
kv: json['kv'],
ev: json['ev'],
sv: json['sv'],
profileComplete: json['profile_complete'],
verCodeSendAt: json['ver_code_send_at'],
ts: json['ts'],
tv: json['tv'],
tsc: json['tsc'],
banReason: json['ban_reason'],
coins: json['coins'],
score: json['score'],
loginBy: json['login_by'],
deleteStatus: json['delete_status'],
createdAt: DateTime.parse(json['created_at']),
updatedAt: DateTime.parse(json['updated_at']),
);
}
}

class Data {
final User user;
final String accessToken;
final String tokenType;

Data({
required this.user,
required this.accessToken,
required this.tokenType,
});

factory Data.fromJson(Map<String, dynamic> json) {
return Data(
user: User.fromJson(json['user']),
accessToken: json['access_token'],
tokenType: json['token_type'],
);
}
}

class LoginResponse {
final String remark;
final String status;
final Map<String, dynamic> message;
final Data data;

LoginResponse({
required this.remark,
required this.status,
required this.message,
required this.data,
});

factory LoginResponse.fromJson(Map<String, dynamic> json) {
return LoginResponse(
remark: json['remark'],
status: json['status'],
message: json['message'],
data: Data.fromJson(json['data']),
);
}
}




Comments

Popular posts from this blog

Unlocking the Power of OOP: A Beginner's Guide to Objects, Encapsulation, Inheritance, Abstraction, and Polymorphism

HTTP GET Response in Flutter

Building a Flutter Firebase Firestore CRUD App