[FIX] Handle Steam host (#1539)
## Description It is same as Totp with 5 digits. Related: https://github.com/ente-io/ente/discussions/1038
This commit is contained in:
commit
dc1d2c5b7b
8 changed files with 43 additions and 19 deletions
|
@ -20,7 +20,6 @@
|
|||
"codeIssuerHint": "Issuer",
|
||||
"codeSecretKeyHint": "Secret Key",
|
||||
"codeAccountHint": "Account (you@domain.com)",
|
||||
"accountKeyType": "Type of key",
|
||||
"sessionExpired": "Session expired",
|
||||
"@sessionExpired": {
|
||||
"description": "Title of the dialog when the users current session is invalid/expired"
|
||||
|
|
|
@ -37,6 +37,7 @@ import 'package:window_manager/window_manager.dart';
|
|||
final _logger = Logger("main");
|
||||
|
||||
Future<void> initSystemTray() async {
|
||||
if (PlatformUtil.isMobile()) return;
|
||||
String path = Platform.isWindows
|
||||
? 'assets/icons/auth-icon.ico'
|
||||
: 'assets/icons/auth-icon.png';
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:ente_auth/utils/totp_util.dart';
|
|||
|
||||
class Code {
|
||||
static const defaultDigits = 6;
|
||||
static const steamDigits = 5;
|
||||
static const defaultPeriod = 30;
|
||||
|
||||
int? generatedID;
|
||||
|
@ -57,36 +58,42 @@ class Code {
|
|||
updatedAlgo,
|
||||
updatedType,
|
||||
updatedCounter,
|
||||
"otpauth://${updatedType.name}/$updateIssuer:$updateAccount?algorithm=${updatedAlgo.name}&digits=$updatedDigits&issuer=$updateIssuer&period=$updatePeriod&secret=$updatedSecret${updatedType == Type.hotp ? "&counter=$updatedCounter" : ""}",
|
||||
"otpauth://${updatedType.name}/$updateIssuer:$updateAccount?algorithm=${updatedAlgo.name}"
|
||||
"&digits=$updatedDigits&issuer=$updateIssuer"
|
||||
"&period=$updatePeriod&secret=$updatedSecret${updatedType == Type.hotp ? "&counter=$updatedCounter" : ""}",
|
||||
generatedID: generatedID,
|
||||
);
|
||||
}
|
||||
|
||||
static Code fromAccountAndSecret(
|
||||
Type type,
|
||||
String account,
|
||||
String issuer,
|
||||
String secret,
|
||||
int digits,
|
||||
) {
|
||||
return Code(
|
||||
account,
|
||||
issuer,
|
||||
defaultDigits,
|
||||
digits,
|
||||
defaultPeriod,
|
||||
secret,
|
||||
Algorithm.sha1,
|
||||
Type.totp,
|
||||
type,
|
||||
0,
|
||||
"otpauth://totp/$issuer:$account?algorithm=SHA1&digits=6&issuer=$issuer&period=30&secret=$secret",
|
||||
"otpauth://${type.name}/$issuer:$account?algorithm=SHA1&digits=$digits&issuer=$issuer&period=30&secret=$secret",
|
||||
);
|
||||
}
|
||||
|
||||
static Code fromRawData(String rawData) {
|
||||
Uri uri = Uri.parse(rawData);
|
||||
final issuer = _getIssuer(uri);
|
||||
|
||||
try {
|
||||
return Code(
|
||||
_getAccount(uri),
|
||||
_getIssuer(uri),
|
||||
_getDigits(uri),
|
||||
issuer,
|
||||
_getDigits(uri, issuer),
|
||||
_getPeriod(uri),
|
||||
getSanitizedSecret(uri.queryParameters['secret']!),
|
||||
_getAlgorithm(uri),
|
||||
|
@ -140,10 +147,13 @@ class Code {
|
|||
}
|
||||
}
|
||||
|
||||
static int _getDigits(Uri uri) {
|
||||
static int _getDigits(Uri uri, String issuer) {
|
||||
try {
|
||||
return int.parse(uri.queryParameters['digits']!);
|
||||
} catch (e) {
|
||||
if (issuer.toLowerCase() == "steam") {
|
||||
return steamDigits;
|
||||
}
|
||||
return defaultDigits;
|
||||
}
|
||||
}
|
||||
|
@ -186,6 +196,8 @@ class Code {
|
|||
static Type _getType(Uri uri) {
|
||||
if (uri.host == "totp") {
|
||||
return Type.totp;
|
||||
} else if (uri.host == "steam") {
|
||||
return Type.steam;
|
||||
} else if (uri.host == "hotp") {
|
||||
return Type.hotp;
|
||||
}
|
||||
|
@ -223,6 +235,9 @@ class Code {
|
|||
enum Type {
|
||||
totp,
|
||||
hotp,
|
||||
steam;
|
||||
|
||||
bool get isTOTPCompatible => this == totp || this == steam;
|
||||
}
|
||||
|
||||
enum Algorithm {
|
||||
|
|
|
@ -61,6 +61,8 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
|||
},
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.codeIssuerHint,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.auto,
|
||||
labelText: l10n.codeIssuerHint,
|
||||
),
|
||||
controller: _issuerController,
|
||||
autofocus: true,
|
||||
|
@ -78,6 +80,8 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
|||
},
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.codeSecretKeyHint,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.auto,
|
||||
labelText: l10n.codeSecretKeyHint,
|
||||
suffixIcon: IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
|
@ -105,12 +109,12 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
|||
},
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.codeAccountHint,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.auto,
|
||||
labelText: l10n.codeAccountHint,
|
||||
),
|
||||
controller: _accountController,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
const SizedBox(height: 40),
|
||||
SizedBox(
|
||||
width: 400,
|
||||
child: OutlinedButton(
|
||||
|
@ -152,6 +156,7 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
|||
final account = _accountController.text.trim();
|
||||
final issuer = _issuerController.text.trim();
|
||||
final secret = _secretController.text.trim().replaceAll(' ', '');
|
||||
final isStreamCode = issuer.toLowerCase() == "steam";
|
||||
if (widget.code != null && widget.code!.secret != secret) {
|
||||
ButtonResult? result = await showChoiceActionSheet(
|
||||
context,
|
||||
|
@ -168,9 +173,11 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
|||
}
|
||||
final Code newCode = widget.code == null
|
||||
? Code.fromAccountAndSecret(
|
||||
isStreamCode ? Type.steam : Type.totp,
|
||||
account,
|
||||
issuer,
|
||||
secret,
|
||||
isStreamCode ? Code.steamDigits : Code.defaultDigits,
|
||||
)
|
||||
: widget.code!.copyWith(
|
||||
account: account,
|
||||
|
|
|
@ -53,7 +53,7 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
String newCode = _getCurrentOTP();
|
||||
if (newCode != _currentCode.value) {
|
||||
_currentCode.value = newCode;
|
||||
if (widget.code.type == Type.totp) {
|
||||
if (widget.code.type.isTOTPCompatible) {
|
||||
_nextCode.value = _getNextTotp();
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
_shouldShowLargeIcon = PreferenceService.instance.shouldShowLargeIcons();
|
||||
if (!_isInitialized) {
|
||||
_currentCode.value = _getCurrentOTP();
|
||||
if (widget.code.type == Type.totp) {
|
||||
if (widget.code.type.isTOTPCompatible) {
|
||||
_nextCode.value = _getNextTotp();
|
||||
}
|
||||
_isInitialized = true;
|
||||
|
@ -213,7 +213,7 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (widget.code.type == Type.totp)
|
||||
if (widget.code.type.isTOTPCompatible)
|
||||
CodeTimerProgress(
|
||||
period: widget.code.period,
|
||||
),
|
||||
|
@ -263,7 +263,7 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
},
|
||||
),
|
||||
),
|
||||
widget.code.type == Type.totp
|
||||
widget.code.type.isTOTPCompatible
|
||||
? GestureDetector(
|
||||
onTap: () {
|
||||
_copyNextToClipboard();
|
||||
|
@ -481,7 +481,7 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
|
||||
String _getNextTotp() {
|
||||
try {
|
||||
assert(widget.code.type == Type.totp);
|
||||
assert(widget.code.type.isTOTPCompatible);
|
||||
return getNextTotp(widget.code);
|
||||
} catch (e) {
|
||||
return context.l10n.error;
|
||||
|
|
|
@ -92,9 +92,11 @@ Future<int?> _processBitwardenExportFile(
|
|||
var account = item['login']['username'];
|
||||
|
||||
code = Code.fromAccountAndSecret(
|
||||
Type.totp,
|
||||
account,
|
||||
issuer,
|
||||
totp,
|
||||
Code.defaultDigits,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:otp/otp.dart' as otp;
|
||||
|
||||
String getOTP(Code code) {
|
||||
if(code.type == Type.hotp) {
|
||||
if (code.type == Type.hotp) {
|
||||
return _getHOTPCode(code);
|
||||
}
|
||||
return otp.OTP.generateTOTPCodeString(
|
||||
|
@ -60,4 +60,4 @@ String safeDecode(String value) {
|
|||
debugPrint("Failed to decode $e");
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: ente_auth
|
||||
description: ente two-factor authenticator
|
||||
version: 2.0.56+256
|
||||
version: 2.0.57+257
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
|
|
Loading…
Add table
Reference in a new issue