flutterpluginfidologinapi 0.61.41
flutterpluginfidologinapi: ^0.61.41 copied to clipboard
Fido Login API Flutter plugin (Gen 1).
example/lib/main.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:developer' as logger;
import 'package:http/http.dart' as http;
import 'dart:convert' as convert;
//import 'package:fluttertoast/fluttertoast.dart';
import 'package:flutter/services.dart';
import 'package:flutterpluginfidologinapi/flutterpluginfidologinapi.dart';
//String openClientId = "G-1k3ry-2uL5CWHeTJ6_xGx_vvR2APVTNtQcFtscmCiYFIpnmHQ7Pdqk52SWFyPgIA2d_dSi7aTEyY_XiZexQA==";
//String openBaseURL = "https://75cd4c30-bf11-11eb-9de4-5756235242ab.qa.loginid.io";
String openBaseURL = "https://2baf9200-8c67-11ed-91c2-1b5124d8e4c8.qa.loginid.io";
String openClientId = "8D8xVGCvRSW-MBnFHLh3djOp8fmNx4ksRwlSRsNTMMgE4P9jqD8O_0hovSyHYIKQV1tu71Mn12W1gY7js7OXLw";
String secureClientId = "NiDsO7HYR0gZxwmAUjXQXeeJK9ipojw4qzNHrxPgYaw70ivW6TUnGHgBgjf6y7ZrFpa42KC-a1Ipsqe1fa8OIA==";
String secureBaseURL = "https://5f83f920-b849-11eb-9de4-5756235242ab.qa.loginid.io";
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String? _platformVersion = 'Unknown';
bool? _hasAccount = false;
bool? _isLoggedIn = false;
String _username = '';
@override
void initState() {
super.initState();
initializeState();
}
// Fido login plugin api are asynchronous, so we initialize in an async method.
Future<void> initializeState() async {
String? platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
platformVersion = await FPLoginApi.getPlatformVersion();
logger.log("version ${platformVersion}");
} on PlatformException catch (e) {
platformVersion = 'Failed to get platform version.';
logger.log("version ${platformVersion} ${e}");
}
FidoCapability capa = await FPLoginApi.checkFidoCapability();
logger.log("capa ${capa}");
//String clientId = secureClientId;
//String baseURL = secureBaseURL;
String clientId = openClientId;
String baseURL = openBaseURL;
//String clientId = "VN2w-Vld-KSsqq1hOf6G3LYNz8XeD1cO4nuZfSCh1nrr1vrh3UYNDhdcRka-YjUnXJSG7djjqAuBBo61oYJCDw==";
//String baseURL="https://24f8017c-a1b0-4b3a-8bae-b735448875a5.qa1-native.awstest.loginid.io";
//String clientId= "UHx0SYlIowhXRU5wO08CltoJBv3XvL4GcgXJYhZOybXJKnBRIQhbBGieyjl7dVNwk3ClZ-yhkPx7ks60jkhOLg==";
//String baseURL="https://675f56c0-96e5-11ea-9435-a52928307cc1.sandbox-apse1.native-api.loginid.io";
await FPLoginApi.configure(clientId, baseURL);
FPLoginApi.setAttestationType("self");
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
bool? hasAccount = await FPLoginApi.hasAccount();
bool? isLoggedIn = await FPLoginApi.isLoggedIn();
logger.log(" hasAccount ${hasAccount}");
logger.log(" isLoggedIn ${isLoggedIn}");
//bool isLoggedIn = false;
//bool hasAccount = false;
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
_hasAccount = hasAccount;
_isLoggedIn = isLoggedIn;
});
}
@override
Widget build(BuildContext context) {
if (_hasAccount! && _isLoggedIn!) {
return MaterialApp(home: MainSessionWidget());
} else {
return MaterialApp(home: RegisterWidget());
}
}
}
class RegisterWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() => RegisterState();
}
class Util {
static Future<String?> tokenRequest (String clientId, String username, String type, String? payload) async {
logger.log("token request");
var response = await http.post(Uri.parse("https://tokendemo.pd-dev.awstest.loginid.io/token"),
headers: <String, String>{ 'Content-Type': 'application/json; charset=UTF-8'},
body: convert.jsonEncode({'client_id': secureClientId, 'username':username,'type':type, 'payload':payload}));
logger.log('response: ${clientId} ${response.body}');
if (response.statusCode == 200) {
return response.body;
} else {
return null;
}
}
}
class RegisterState extends State<RegisterWidget> {
bool? _hasAccount = false;
@override
void initState() {
super.initState();
initialize();
}
Future<void> initialize() async {
bool? hasAccount = await FPLoginApi.hasAccount();
setState(() {
_hasAccount = hasAccount;
});
}
final usernameController = TextEditingController();
final codeController = TextEditingController();
final passwordController = TextEditingController();
final passwordConfirmationController = TextEditingController();
@override
void dispose() {
// Clean up the controller when the widget is disposed.
usernameController.dispose();
super.dispose();
}
Future<void> _register(BuildContext context) async {
try {
String username = usernameController.text.toString();
logger.log("register ..." + username);
late RegistrationOptions options;
String? authToken = await Util.tokenRequest( secureClientId, username, "auth.register", null);
if (authToken != null ) {
options = RegistrationOptions.buildAuth(authToken);
}
final RegisterResponse response =
await FPLoginApi.registerWithFido2(username,options);
logger.log("register done ..." + username);
if (response.success == true) {
//example handling success register case
print('Success: ${response.jwt}');
Navigator.push(context,
MaterialPageRoute(builder: (context) => MainSessionWidget()));
} else {
final snackBar = SnackBar(content: Text('${response.errorMessage}'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
print('Error: ${response.errorMessage}');
}
} on PlatformException catch (e) {
print(e.message);
logger.log(e.message!);
}
}
Future<void> _addCredential(BuildContext context) async {
try {
String username = usernameController.text.toString();
String code = codeController.text.toString();
logger.log("add credential ..." + username);
late AddCredentialOptions options;
String? authToken = await Util.tokenRequest( secureClientId, username, "credentials.add", null);
if (authToken != null ) {
options = AddCredentialOptions.buildAuth(authToken);
}
final AddCredentialResponse response =
await FPLoginApi.addFido2Credential(username,code,options);
if (response.success == true) {
//example handling success register case
print('Success: ${response.jwt}');
Navigator.push(context,
MaterialPageRoute(builder: (context) => MainSessionWidget()));
} else {
final snackBar = SnackBar(content: Text('${response.errorMessage}'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
print('Error: ${response.errorMessage}');
}
} on PlatformException catch (e) {
print(e.message);
logger.log(e.message!);
}
}
Future<void> _registerPassword(BuildContext context) async {
try {
String username = usernameController.text.toString();
String password = passwordController.text.toString();
String passwordConfirmation = passwordConfirmationController.text.toString();
late RegistrationOptions options;
String? authToken = await Util.tokenRequest( secureClientId, username, "auth.register", null);
if (authToken != null ) {
options = RegistrationOptions.buildAuth(authToken);
}
final RegisterResponse response =
await FPLoginApi.registerWithPassword(username,password, passwordConfirmation, options);
if (response.success == true) {
//example handling success register case
print('Success: ${response.jwt}');
Navigator.push(context,
MaterialPageRoute(builder: (context) => MainSessionWidget()));
} else {
final snackBar = SnackBar(content: Text('${response.errorMessage}'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
print('Error: ${response.errorMessage}');
}
} on PlatformException catch (e) {
print(e.message);
}
}
Future<void> _login(BuildContext context) async {
try {
String username = usernameController.text.toString();
late AuthenticationOptions options;
String? authToken = await Util.tokenRequest( secureClientId, username, "auth.login", null);
if (authToken != null ) {
options = AuthenticationOptions.buildAuth(authToken);
}
AuthenticateResponse response;
response = await FPLoginApi.authenticateWithFido2(username,options);
if (response.success == true) {
//example handling success login case
print('Success: ${response.jwt}');
Navigator.push(context,
MaterialPageRoute(builder: (context) => MainSessionWidget()));
} else {
//display error message
final snackBar = SnackBar(content: Text('${response.errorMessage}'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
print('Login Error: ${response.errorMessage}');
}
} on PlatformException catch (e) {
print('Login ex: ${e.message}');
}
}
Future<void> _loginPassword(BuildContext context) async {
try {
String username = usernameController.text.toString();
String password = passwordController.text.toString();
late AuthenticationOptions options;
String? authToken = await Util.tokenRequest( secureClientId, username, "auth.login", null);
if (authToken != null ) {
options = AuthenticationOptions.buildAuth(authToken);
}
AuthenticateResponse response;
response = await FPLoginApi.authenticateWithPassword(username,password, options);
if (response.success == true) {
//example handling success login case
print('Success: ${response.jwt}');
Navigator.push(context,
MaterialPageRoute(builder: (context) => MainSessionWidget()));
} else {
//display error message
final snackBar = SnackBar(content: Text('${response.errorMessage}'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
(snackBar);
print('Login Error: ${response.errorMessage}');
}
} on PlatformException catch (e) {
print('Login ex: ${e.message}');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
// Column is a vertical, linear layout.
appBar: AppBar(
title: Text("Login Page"),
), // Column is a vertical, linear layout.
body: Builder(
builder: (BuildContext context) {
return Column(
children: <Widget>[
TextField(
controller: usernameController,
),
TextField(
controller: codeController,
decoration: InputDecoration( hintText : 'Code'),
),
TextField(
controller: passwordController,
decoration: InputDecoration( hintText : 'Password'),
),
TextField(
controller: passwordConfirmationController,
decoration: InputDecoration (hintText : 'Confirmation Password'),
),
ElevatedButton(
onPressed: () {
_register(context);
},
child: const Text('Register')),
ElevatedButton(
onPressed: () {
_login(context);
},
child: const Text('Login')),
ElevatedButton(
onPressed: () {
_registerPassword(context);
},
child: const Text('Register With Password')),
ElevatedButton(
onPressed: () {
_loginPassword(context);
},
child: const Text('Login With Password')),
ElevatedButton(
onPressed: () {
_addCredential(context);
},
child: const Text('Add Credential')),
],
);
},
),
);
}
}
class MainSessionWidget extends StatefulWidget {
@override
MainSessionState createState() => MainSessionState();
}
class MainSessionState extends State<MainSessionWidget> {
String? username = "";
@override
void initState() {
super.initState();
initialize();
}
void initialize() async {
String? aUsername = await FPLoginApi.getCurrentUsername();
setState(() {
username = aUsername;
});
}
Future<void> _transactionConfirmation(BuildContext context) async {
try {
String? username = await FPLoginApi.getCurrentUsername() ;
if (username == null) {
return;
}
String txMessage = "transaction message";
late TransactionOptions options;
String? authToken = await Util.tokenRequest( secureClientId, username, "tx.create", txMessage);
logger.log('auth token: ${authToken}');
if (authToken != null ) {
options = TransactionOptions.buildAuth(authToken);
}
TransactionPayload payload = TransactionPayload.build("nonce", txMessage);
final TransactionResponse response =
await FPLoginApi.transactionConfirmation(username, payload, options);
//print (response);
if (response.success == true) {
logger.log('Success code: ${response.jwt}');
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Your code is : ${response.jwt}"),
));
} else {
print('Error: ${response.errorMessage}');
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Error : ${response.errorMessage}"),
));
}
} on PlatformException catch (e) {
print(e.message);
}
}
// logout handler when clicking on logout button
Future<void> _logout(BuildContext context) async {
await FPLoginApi.logout();
Navigator.push(
context, MaterialPageRoute(builder: (context) => RegisterWidget()));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Welcome Page"),
), // Column is a vertical, linear layout.
body: Builder(
builder: (BuildContext context) {
return Column(
children: <Widget>[
Text('Welcome :' + username!),
ElevatedButton(
onPressed: () {
_transactionConfirmation(context);
},
child: const Text('Transaction Confirmation')),
ElevatedButton(
onPressed: () {
_logout(context);
},
child: const Text('Logout')),
],
);
},
),
);
}
}