From c193377640f9a48f166dfaf5eb70f8964be5e461 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Thu, 13 Jun 2024 13:54:31 +0530 Subject: [PATCH] [auth] Add endpoint to check passkey status --- auth/lib/core/errors.dart | 4 ++++ auth/lib/services/user_service.dart | 25 +++++++++++++++++++++++++ auth/lib/ui/passkey_page.dart | 26 ++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/auth/lib/core/errors.dart b/auth/lib/core/errors.dart index ba1310b6ca..9e36301907 100644 --- a/auth/lib/core/errors.dart +++ b/auth/lib/core/errors.dart @@ -42,3 +42,7 @@ class InvalidStateError extends AssertionError { class SrpSetupNotCompleteError extends Error {} class AuthenticatorKeyNotFound extends Error {} + +class PassKeySessionNotVerifiedError extends Error {} + +class PassKeySessionExpiredError extends Error {} diff --git a/auth/lib/services/user_service.dart b/auth/lib/services/user_service.dart index bd411da47b..4f58c670b1 100644 --- a/auth/lib/services/user_service.dart +++ b/auth/lib/services/user_service.dart @@ -266,6 +266,31 @@ class UserService { } } + Future getTokenForPasskeySession(String sessionID) async { + try { + final response = await _dio.get( + "${_config.getHttpEndpoint()}/users/two-factor/passkeys/get-token", + queryParameters: { + "sessionID": sessionID, + }, + ); + return response.data; + } on DioException catch (e) { + if (e.response != null) { + if (e.response!.statusCode == 404 || e.response!.statusCode == 410) { + throw PassKeySessionExpiredError(); + } + if (e.response!.statusCode == 400) { + throw PassKeySessionNotVerifiedError(); + } + } + rethrow; + } catch (e, s) { + _logger.severe("unexpected error", e, s); + rethrow; + } + } + Future onPassKeyVerified(BuildContext context, Map response) async { final ProgressDialog dialog = createProgressDialog(context, context.l10n.pleaseWait); diff --git a/auth/lib/ui/passkey_page.dart b/auth/lib/ui/passkey_page.dart index 93caa2eba9..d91ad6f2ea 100644 --- a/auth/lib/ui/passkey_page.dart +++ b/auth/lib/ui/passkey_page.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:app_links/app_links.dart'; import 'package:ente_auth/core/configuration.dart'; +import 'package:ente_auth/core/errors.dart'; import 'package:ente_auth/l10n/l10n.dart'; import 'package:ente_auth/models/account/two_factor.dart'; import 'package:ente_auth/services/user_service.dart'; @@ -51,6 +52,24 @@ class _PasskeyPageState extends State { ); } + Future checkStatus() async { + late dynamic response; + try { + response = await UserService.instance + .getTokenForPasskeySession(widget.sessionID); + } on PassKeySessionNotVerifiedError catch (e) { + showToast(context, "Verification is still pending."); + } on PassKeySessionExpiredError catch (e) { + showToast(context, "Passkey session expired. Please try again."); + return; + } catch (e, s) { + _logger.severe("failed to check status", e, s); + showGenericErrorDialog(context: context).ignore(); + return; + } + await UserService.instance.onPassKeyVerified(context, response); + } + Future _handleDeeplink(String? link) async { if (!context.mounted || Configuration.instance.hasConfiguredAccount() || @@ -129,6 +148,13 @@ class _PasskeyPageState extends State { labelText: context.l10n.tryAgain, onTap: () => launchPasskey(), ), + const SizedBox(height: 16), + ButtonWidget( + buttonType: ButtonType.neutral, + labelText: context.l10n.checkForUpdates, + onTap: checkStatus, + shouldSurfaceExecutionStates: true, + ), const Padding(padding: EdgeInsets.all(30)), GestureDetector( behavior: HitTestBehavior.opaque,