May refer for intro
Table of Contents
Clerk authentication Flutter Video Tutorial
Complete video tutorial link explaining each step.
Code
main.dart
Designing the screen to accept user name and password
return Scaffold(
appBar: AppBar(title: const Text("Clerk Login")),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
),
TextField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
),
const SizedBox(height: 20),
ElevatedButton(onPressed: _signUp, child: Text("Sign In")),
],
),
),
);
if user login is successful then proceed to next step that is
if(_user!=null){
return Scaffold(
appBar: AppBar(title: const Text("Welcome"),),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("Name: ${_user!.username}"),
Text("Email: ${_user!.email}"),
ElevatedButton(onPressed: _auth.signOut, child: Text("Sign Out"))
],
)
)
);
}
Full Code
import 'dart:async';
import 'package:clerk_auth/clerk_auth.dart' as clerk;
import 'package:clerk_flutter/clerk_flutter.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const CustomSignIn());
}
class CustomSignIn extends StatefulWidget {
const CustomSignIn({super.key});
@override
State<CustomSignIn> createState() => _CustomSignInState();
}
class _CustomSignInState extends State<CustomSignIn> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
late final ClerkAuthState _auth;
clerk.User? _user;
bool _loading = false;
late final StreamSubscription _errorSub;
@override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){
if(!mounted) return;
_auth = ClerkAuth.of(context);
_user = _auth.user;
_auth.addListener(_updateUser);
_errorSub = _auth.errorStream.listen((err){
if(mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(err.message))
);
}
});
});
}
void _updateUser() {
if(!mounted) return;
setState(() {
_user = _auth.user;
});
}
Future<void> _signIn() async {
setState(() {
_loading = true;
});
try {
await _auth.attemptSignIn(
strategy: clerk.Strategy.password,
identifier: _emailController.text,
password: _passwordController.text,
);
} finally {
if (mounted) {
setState(() {
_loading = false;
});
}
}
}
Future<void> _signUp() async {
setState(() {
_loading = true;
});
try {
await _auth.attemptSignUp(
strategy: clerk.Strategy.emailCode,
username: "Abhi",
emailAddress: _emailController.text,
password: _passwordController.text,
passwordConfirmation: _passwordController.text
);
} finally {
if (mounted) {
setState(() {
_loading = false;
});
}
}
}
@override
Widget build(BuildContext context) {
if(_user!=null){
return Scaffold(
appBar: AppBar(title: const Text("Welcome"),),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("Name: ${_user!.username}"),
Text("Email: ${_user!.email}"),
ElevatedButton(onPressed: _auth.signOut, child: Text("Sign Out"))
],
)
)
);
}
return Scaffold(
appBar: AppBar(title: const Text("Clerk Login")),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
),
TextField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
),
const SizedBox(height: 20),
ElevatedButton(onPressed: _signUp, child: Text("Sign In")),
],
),
),
);
}
@override
void dispose() {
_emailController.dispose();
_passwordController.dispose();
if(mounted){
_auth.removeListener(_updateUser);
}
_errorSub.cancel();
super.dispose();
}
}