Flutter Pin/Password/Pattern Integration - flutter

I have went through the local_auth package and it works fine, but it does not have an option to authenticate with password or pin. Help appreciated!
String _authorized = 'Not Authorized';//Start
Future<Null> _authenticate() async {
final LocalAuthentication auth = new LocalAuthentication();
bool authenticated = false;
try {
authenticated = await auth.authenticateWithBiometrics(
localizedReason: 'Scan your fingerprint to authenticate',
useErrorDialogs: true,
stickyAuth: false);
authenticated = await auth.authenticateWithBiometrics(localizedReason: 'Authenticate');
} on PlatformException catch (e) {
print(e);
}
if (!mounted) return;
setState(() {
_authorized = authenticated ? 'Authorized' : 'Not Authorized';
});
}//End
So this is the example code and you can use biometric authentication but what about the default Pin/Password authentication that is also present with fingerprint.

For security reason, mobile (iOS/Android) will only authenticate user by biometrics, not system password/pin. If you want to let user authenticate by other methods than biometrics, the app itself must store and process (encrypted) credential which is totally separated from system password/pin.
You can see this behavior (to use system-biometrics AND app-specific credential) in many bank/financial related app, such as https://play.google.com/store/apps/details?id=com.konylabs.capitalone&hl=en

Related

The named parameter '~' isn't defined

I'm flutter beginner. I'm using local-auth for making Bio auth function. but error like below, I don't get the error why it occurs. Could you advice for this? why is it doesn't work in authenticate(), useErrorDialogs, stickyAuth, biometricOnly those three objects occurs error?
class AuthService {
static Future<bool> authenticate({
String localizedReason,
bool useErrorDialogs,
bool stickyAuth,
bool biometricOnly ,
}) {
// TODO: implement authenticate
throw UnimplementedError();
}
static Future<bool> authenticateUser() async {
//initialize Local Authentication plugin.
final LocalAuthentication _localAuthentication = LocalAuthentication();
//status of authentication.
bool isAuthenticated = false;
//check if device supports biometrics authentication.
bool isBiometricSupported = await _localAuthentication.isDeviceSupported();
//check if user has enabled biometrics.
//check
bool canCheckBiometrics = await _localAuthentication.canCheckBiometrics;
//if device supports biometrics and user has enabled biometrics, then authenticate.
if (isBiometricSupported && canCheckBiometrics) {
try {
isAuthenticated = await _localAuthentication.authenticate(
localizedReason: 'Scan your fingerprint to authenticate',
useErrorDialogs: true,
stickyAuth: true,
biometricOnly: true,
);
} on PlatformException catch (e) {
print(e);
}
}
return isAuthenticated;
}
}

linkWithCredential and Flutter Web with Apple

I have a use case where a user, on Flutter Web, needs to link an Apple auth with their existing account, and the email may not match.
However, the only available method for Flutter Web Apple Authentication is signInWithPopUp. If the user's apple email is different from the User firebase account email, a new firebase account is created, and a user is returned, short circuiting the process of linking, this creates a new account in firebase, and I'm unable to linkWithCredential.
My method to try to link accounts is as follows:
Future<String> linkWithAppleWeb() async {
try {
final User user = _auth.currentUser!;
final provider = OAuthProvider("apple.com")
..addScope('email')
..addScope('name');
await _auth.signInWithPopup(provider).then((appleCredential) async {
final authCredential = appleCredential.credential;
await user.linkWithCredential(authCredential!).then((result) {
DatabaseService().updateUserSocialAuth(user.uid, 'apple');
return 'Success';
}).catchError((e) {
return 'Error: $e';
});
});
} catch (e) {
return 'Error: $e';
}
return 'Success';
}
As you would expect, my project starts with Streaming a User Object, and when the pop up signs in, it returns the new user, which rebuilds the entire project. Is there a way to authenticate an apple user without returning a new user? I can link a google or phone authorization method fine. It's apple that is problematic. I don't fully understand why Google doesn't break in the same way, other than Firebase put in the work to ensure the functionality of linking for GoogleSignIn().signIn() I'm not using other social auth methods, and I don't use password/email.
This method is not documented in the Flutter Fire Docs, but works perfectly:
Future<String> linkWithAppleWeb() async {
try {
final User user = _auth.currentUser!;
final provider = OAuthProvider("apple.com")
..addScope('email')
..addScope('name');
await user.linkWithPopup(provider).then((result) {
DatabaseService().updateUserSocialAuth(user.uid, 'apple');
return 'Success';
}).catchError((e) {
return 'Error: $e';
});
} catch (e) {
debugPrint('auth linkWithGoogle error: ${e.toString()}');
return 'Error: $e';
}
return 'Success';
}

Google Auth Page always shown, how to Auth only first time

I am making a calendar app with flutter using googleApi library.
but, When you turn off the app, need to auth again in web site.
i want auth only first time.
is it possible?
// mycode
get _SCOPES => [CalendarApi.CalendarScope];
await clientViaUserConsent(_clientID, _SCOPES, prompt)
.then((AuthClient client) async {
CalendarClient.calendar = CalendarApi(client);
calendarId = await CalendarClient.calendar.calendarList
.list()
.then((value) => value.items[0].id);
});
void saveData(AccessCredentials credentials) {
GetStorage().write(credetialKey, {
"accessTokenData": credentials.accessToken.data,
"accessTokenExpiry": credentials.accessToken.expiry.toString(),
"refreshToken": credentials.refreshToken,
"scopes": credentials.scopes,
"idToken": credentials.idToken
});
}
AccessCredentials getCredetial() {
try {
var map = GetStorage().read(credetialKey);
return AccessCredentials(
AccessToken("Bearer", map["accessTokenData"] as String,
DateTime.parse(map["accessTokenExpiry"])),
map["refreshToken"],
map["scopes"].cast<String>(),
idToken: map["idToken"] as String);
} catch (e) {
return null;
}
}
Client cli = Client();
var c = await refreshCredentials(_clientID, getCredetial(), cli)
.catchError((e) {
print(e);
});
authenticatedClient(cli, c);
error :
DetailedApiRequestError(status: 401, message: Request is missing required authentication credential. Expected OAuth 2 access tok
You can save user session using for example sharedPreferences. Each time the user launch the app your must first check if the session is saved so you can skip the auth process, otherwise you initiate the authentication
i solved it.
save AccessCredentials,
and use autoRefreshingClient;
Client cli = Client();
var c = await refreshCredentials(_clientID, getCredetial(), cli)
.catchError((e) {
print(e);
});
cli = autoRefreshingClient(_clientID, c, cli);

Flutter local_auth dialog closes if authentication fails

I am using https://pub.dev/packages/local_auth library to implement local_auth in my app.
I am using the following code to authenticate.
Future<void> _authenticate() async {
bool authenticated = false;
try {
authenticated = await auth.authenticateWithBiometrics(
localizedReason: 'Scan your fingerprint to authenticate');
print('Authentitcated: $authenticated');
} on PlatformException catch (e) {
print(e);
}
}
If authentication is success it shows Authenticated: true but it does not show anything if authentication fails. Also, the authentication dialogue closes automatically if authentication fails.
How do I return the authentication false status also keep the dialogue open even after authentication is failed?

Auth0-How to use with Flutter

I need use Auth0 with Flutter but there is no such SDK in Auth0 site.
Auth0 works to create such SDK for Flutter.
Did anyone use Auth0 with Flutter or what can you advise?
Its very simple to get started with flutter auth0
Have a class for auth0 and call this at the places you need them. But also be sure to set the constants AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_REDIRECT_URI, AUTH0_ISSUER
class Auth0 {
final FlutterAppAuth appAuth = FlutterAppAuth();
Map<String, Object> parseIdToken(String idToken) {
final List<String> parts = idToken.split('.');
assert(parts.length == 3);
return jsonDecode(
utf8.decode(base64Url.decode(base64Url.normalize(parts[1]))));
}
Future<Map<String, Object>> getUserDetails(String accessToken) async {
const String url = 'https://$AUTH0_DOMAIN/userinfo';
final http.Response response = await http.get(
url,
headers: <String, String>{'Authorization': 'Bearer $accessToken'},
);
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to get user details');
}
}
Future<void> loginAction() async {
isBusy = true;
errorMessage = 'Error! - ';
try {
final AuthorizationTokenResponse result =
await appAuth.authorizeAndExchangeCode(
AuthorizationTokenRequest(
AUTH0_CLIENT_ID,
AUTH0_REDIRECT_URI,
issuer: 'https://$AUTH0_DOMAIN',
scopes: <String>['openid', 'email', 'profile', 'offline_access'],
promptValues: ['login']
),
);
final Map<String, Object> idToken = parseIdToken(result.idToken);
final Map<String, Object> profile =
await getUserDetails(result.accessToken);
isBusy = false;
name = idToken['name'];
email = profile['email'];
picture = profile['picture'];
} on Exception catch (e, s) {
print('login error: $e - stack: $s');
isBusy = false;
errorMessage = e.toString();
}
}
Instead of using a boolean for checking isLoggedIn try saving the token in the localstorage and that will set the state as is.
There's an auth0 package for flutter to use Auth0 API provides login, logout and access APIs for authentication in your App. However, you need to make changes inside android and ios files in your flutter project. You need to configure your callbacks and application settings for that, The author has their example on github that you should check out.
I would advise you to follow the blog post provided by the Auth0 team -
Get Started with Flutter Authentication
For Flutter Web App, I am making a wrapper around Auth0 JS SPA SDK.
GitHub: https://github.com/anthonychwong/auth0-flutter-web
Pub.dev: https://pub.dev/packages/auth0_flutter_web
import 'package:auth0_flutter_web/auth0_flutter_web.dart';
Auth0 auth0 = await createAuth0Client(
Auth0CreateOptions(
domain: '-- domain of the universal login page --',
client_id: '-- id of your app --',
)
);
String token = await auth0.getTokenWithPopup();
It is in very early stage and PRs are welcome.