mirror of
https://github.com/ente-io/ente.git
synced 2025-08-12 01:04:48 +00:00
[auth] Enable login via totp when both passkey & totp are enabled
This commit is contained in:
parent
08160f251a
commit
14fe9bcb72
@ -156,6 +156,7 @@
|
|||||||
"twoFactorAuthTitle": "Two-factor authentication",
|
"twoFactorAuthTitle": "Two-factor authentication",
|
||||||
"passkeyAuthTitle": "Passkey verification",
|
"passkeyAuthTitle": "Passkey verification",
|
||||||
"verifyPasskey": "Verify passkey",
|
"verifyPasskey": "Verify passkey",
|
||||||
|
"loginWithTOTP": "Login with TOTP",
|
||||||
"recoverAccount": "Recover account",
|
"recoverAccount": "Recover account",
|
||||||
"enterRecoveryKeyHint": "Enter your recovery key",
|
"enterRecoveryKeyHint": "Enter your recovery key",
|
||||||
"recover": "Recover",
|
"recover": "Recover",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:ente_auth/core/network.dart';
|
import 'package:ente_auth/core/network.dart';
|
||||||
import 'package:ente_auth/utils/dialog_util.dart';
|
import 'package:ente_auth/utils/dialog_util.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
@ -24,6 +25,10 @@ class PasskeyService {
|
|||||||
return response.data!["isPasskeyRecoveryEnabled"] as bool;
|
return response.data!["isPasskeyRecoveryEnabled"] as bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get accountsUrl {
|
||||||
|
return kDebugMode ? "http://localhost:3001" : "https://accounts.ente.io";
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> configurePasskeyRecovery(
|
Future<void> configurePasskeyRecovery(
|
||||||
String secret,
|
String secret,
|
||||||
String userEncryptedSecret,
|
String userEncryptedSecret,
|
||||||
@ -42,7 +47,7 @@ class PasskeyService {
|
|||||||
Future<void> openPasskeyPage(BuildContext context) async {
|
Future<void> openPasskeyPage(BuildContext context) async {
|
||||||
try {
|
try {
|
||||||
final jwtToken = await getJwtToken();
|
final jwtToken = await getJwtToken();
|
||||||
final url = "https://accounts.ente.io/passkeys?token=$jwtToken";
|
final url = "$accountsUrl/passkeys?token=$jwtToken";
|
||||||
await launchUrlString(
|
await launchUrlString(
|
||||||
url,
|
url,
|
||||||
mode: LaunchMode.externalApplication,
|
mode: LaunchMode.externalApplication,
|
||||||
|
@ -379,11 +379,17 @@ class UserService {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
Widget page;
|
Widget page;
|
||||||
final String passkeySessionID = response.data["passkeySessionID"];
|
final String passkeySessionID = response.data["passkeySessionID"];
|
||||||
final String twoFASessionID = response.data["twoFactorSessionID"];
|
String twoFASessionID = response.data["twoFactorSessionID"];
|
||||||
if (twoFASessionID.isNotEmpty) {
|
if (twoFASessionID.isEmpty) {
|
||||||
|
twoFASessionID = response.data["twoFactorSessionIDV2"];
|
||||||
|
}
|
||||||
|
if (passkeySessionID.isNotEmpty) {
|
||||||
|
page = PasskeyPage(
|
||||||
|
passkeySessionID,
|
||||||
|
totp2FASessionID: twoFASessionID,
|
||||||
|
);
|
||||||
|
} else if (twoFASessionID.isNotEmpty) {
|
||||||
page = TwoFactorAuthenticationPage(twoFASessionID);
|
page = TwoFactorAuthenticationPage(twoFASessionID);
|
||||||
} else if (passkeySessionID.isNotEmpty) {
|
|
||||||
page = PasskeyPage(passkeySessionID);
|
|
||||||
} else {
|
} else {
|
||||||
await _saveConfiguration(response);
|
await _saveConfiguration(response);
|
||||||
if (Configuration.instance.getEncryptedToken() != null) {
|
if (Configuration.instance.getEncryptedToken() != null) {
|
||||||
@ -685,13 +691,18 @@ class UserService {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
Widget? page;
|
Widget? page;
|
||||||
final String passkeySessionID = response.data["passkeySessionID"];
|
final String passkeySessionID = response.data["passkeySessionID"];
|
||||||
final String twoFASessionID = response.data["twoFactorSessionID"];
|
String twoFASessionID = response.data["twoFactorSessionID"];
|
||||||
|
if (twoFASessionID.isEmpty) {
|
||||||
|
twoFASessionID = response.data["twoFactorSessionIDV2"];
|
||||||
|
}
|
||||||
Configuration.instance.setVolatilePassword(userPassword);
|
Configuration.instance.setVolatilePassword(userPassword);
|
||||||
|
if (passkeySessionID.isNotEmpty) {
|
||||||
if (twoFASessionID.isNotEmpty) {
|
page = PasskeyPage(
|
||||||
|
passkeySessionID,
|
||||||
|
totp2FASessionID: twoFASessionID,
|
||||||
|
);
|
||||||
|
} else if (twoFASessionID.isNotEmpty) {
|
||||||
page = TwoFactorAuthenticationPage(twoFASessionID);
|
page = TwoFactorAuthenticationPage(twoFASessionID);
|
||||||
} else if (passkeySessionID.isNotEmpty) {
|
|
||||||
page = PasskeyPage(passkeySessionID);
|
|
||||||
} else {
|
} else {
|
||||||
await _saveConfiguration(response);
|
await _saveConfiguration(response);
|
||||||
if (Configuration.instance.getEncryptedToken() != null) {
|
if (Configuration.instance.getEncryptedToken() != null) {
|
||||||
|
@ -5,10 +5,13 @@ import 'package:ente_auth/core/configuration.dart';
|
|||||||
import 'package:ente_auth/core/errors.dart';
|
import 'package:ente_auth/core/errors.dart';
|
||||||
import 'package:ente_auth/l10n/l10n.dart';
|
import 'package:ente_auth/l10n/l10n.dart';
|
||||||
import 'package:ente_auth/models/account/two_factor.dart';
|
import 'package:ente_auth/models/account/two_factor.dart';
|
||||||
|
import 'package:ente_auth/services/passkey_service.dart';
|
||||||
import 'package:ente_auth/services/user_service.dart';
|
import 'package:ente_auth/services/user_service.dart';
|
||||||
import 'package:ente_auth/ui/components/buttons/button_widget.dart';
|
import 'package:ente_auth/ui/components/buttons/button_widget.dart';
|
||||||
import 'package:ente_auth/ui/components/models/button_type.dart';
|
import 'package:ente_auth/ui/components/models/button_type.dart';
|
||||||
|
import 'package:ente_auth/ui/two_factor_authentication_page.dart';
|
||||||
import 'package:ente_auth/utils/dialog_util.dart';
|
import 'package:ente_auth/utils/dialog_util.dart';
|
||||||
|
import 'package:ente_auth/utils/navigation_util.dart';
|
||||||
import 'package:ente_auth/utils/toast_util.dart';
|
import 'package:ente_auth/utils/toast_util.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
@ -16,9 +19,11 @@ import 'package:url_launcher/url_launcher_string.dart';
|
|||||||
|
|
||||||
class PasskeyPage extends StatefulWidget {
|
class PasskeyPage extends StatefulWidget {
|
||||||
final String sessionID;
|
final String sessionID;
|
||||||
|
final String totp2FASessionID;
|
||||||
|
|
||||||
const PasskeyPage(
|
const PasskeyPage(
|
||||||
this.sessionID, {
|
this.sessionID, {
|
||||||
|
required this.totp2FASessionID,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -42,8 +47,9 @@ class _PasskeyPageState extends State<PasskeyPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> launchPasskey() async {
|
Future<void> launchPasskey() async {
|
||||||
|
final String accountsUrl = PasskeyService.instance.accountsUrl;
|
||||||
await launchUrlString(
|
await launchUrlString(
|
||||||
"https://accounts.ente.io/passkeys/verify?"
|
"$accountsUrl/passkeys/verify?"
|
||||||
"passkeySessionID=${widget.sessionID}"
|
"passkeySessionID=${widget.sessionID}"
|
||||||
"&redirect=enteauth://passkey"
|
"&redirect=enteauth://passkey"
|
||||||
"&clientPackage=io.ente.auth",
|
"&clientPackage=io.ente.auth",
|
||||||
@ -175,6 +181,30 @@ class _PasskeyPageState extends State<PasskeyPage> {
|
|||||||
shouldSurfaceExecutionStates: true,
|
shouldSurfaceExecutionStates: true,
|
||||||
),
|
),
|
||||||
const Padding(padding: EdgeInsets.all(30)),
|
const Padding(padding: EdgeInsets.all(30)),
|
||||||
|
if (widget.totp2FASessionID.isNotEmpty)
|
||||||
|
GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTap: () {
|
||||||
|
routeToPage(
|
||||||
|
context,
|
||||||
|
TwoFactorAuthenticationPage(
|
||||||
|
widget.totp2FASessionID,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
context.l10n.loginWithTOTP,
|
||||||
|
style: const TextStyle(
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user