Skip to content

Commit

Permalink
Add Steam OTP support (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
KatherineInCode authored Apr 27, 2024
1 parent c3510e2 commit b3976de
Show file tree
Hide file tree
Showing 15 changed files with 279 additions and 104 deletions.
9 changes: 7 additions & 2 deletions AuthenticatorShared/Core/Vault/Services/TOTP/TOTPKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,13 @@ enum TOTPKey: Equatable {
/// The issuer for the TOTP code.
/// Only works for `otpAuthUri` types.
var issuer: String? {
guard case let .otpAuthUri(model) = self else { return nil }
return model.issuer
switch self {
case .base32,
.steamUri:
nil
case let .otpAuthUri(model):
model.issuer
}
}

/// The key used for generating the TOTP code.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -910,3 +910,5 @@
"KeyReadError" = "Cannot read key.";
"CannotAddKey" = "Cannot add key?";
"OnceTheKeyIsSuccessfullyEnteredAddCode" = "Once the key is successfully entered,\nselect Add code to store the key safely";
"Steam" = "Steam";
"OtpAuthentication" = "OTP Authentication";
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ struct StepperFieldView<State>: View {
}
.padding(.top, 4)
.accessibilityIdentifier(field.accessibilityId ?? field.id)

Divider()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ class AuthenticatorItemCoordinator: NSObject, Coordinator, HasStackNavigator {
onDismiss?.action()
})
case let .editAuthenticatorItem(authenticatorItemView):
Logger.application.log("Edit item \(authenticatorItemView.id)")
showEditAuthenticatorItem(
for: authenticatorItemView,
delegate: context as? AuthenticatorItemOperationDelegate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ struct AuthenticatorItemState: Equatable {
/// The TOTP key/code state.
var totpState: LoginTOTPState

/// The TOTP type.
var totpType: TotpTypeOptions

// MARK: Initialization

init(
Expand All @@ -77,7 +80,8 @@ struct AuthenticatorItemState: Equatable {
name: String,
period: TotpPeriodOptions,
secret: String,
totpState: LoginTOTPState
totpState: LoginTOTPState,
totpType: TotpTypeOptions
) {
self.accountName = accountName
self.algorithm = algorithm
Expand All @@ -90,23 +94,33 @@ struct AuthenticatorItemState: Equatable {
self.period = period
self.secret = secret
self.totpState = totpState
self.totpType = totpType
}

init?(existing authenticatorItemView: AuthenticatorItemView) {
guard let keyModel = TOTPKeyModel(authenticatorKey: authenticatorItemView.totpKey) else {
return nil
}
let type: TotpTypeOptions
switch keyModel.totpKey {
case .base32, .otpAuthUri:
type = .totp
case .steamUri:
type = .steam
}

self.init(
accountName: keyModel.accountName ?? "",
accountName: keyModel.accountName ?? authenticatorItemView.username ?? "",
algorithm: keyModel.algorithm,
configuration: .existing(authenticatorItemView: authenticatorItemView),
digits: keyModel.digits,
id: authenticatorItemView.id,
issuer: keyModel.issuer ?? "",
issuer: keyModel.issuer ?? authenticatorItemView.name,
name: keyModel.issuer ?? authenticatorItemView.name,
period: TotpPeriodOptions(rawValue: keyModel.period) ?? .thirty,
secret: keyModel.base32Key,
totpState: LoginTOTPState(authenticatorItemView.totpKey)
totpState: LoginTOTPState(authenticatorItemView.totpKey),
totpType: type
)
}
}
Expand Down Expand Up @@ -148,3 +162,17 @@ enum TotpPeriodOptions: Int, Menuable, CaseIterable {
}
}
}

enum TotpTypeOptions: Menuable, CaseIterable {
case steam
case totp

var localizedName: String {
switch self {
case .steam:
Localizations.steam
case .totp:
Localizations.totp
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,7 @@ enum EditAuthenticatorItemAction: Equatable {

/// The toggle secret visibility button was changed.
case toggleSecretVisibilityChanged(Bool)

/// The OTP type was changed.
case totpTypeChanged(TotpTypeOptions)
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ final class EditAuthenticatorItemProcessor: StateProcessor<
state.isSecretVisible = isVisible
case let .toastShown(toast):
state.toast = toast
case let .totpTypeChanged(type):
state.totpType = type
}
}

Expand Down Expand Up @@ -139,22 +141,34 @@ final class EditAuthenticatorItemProcessor: StateProcessor<
return
case let .existing(authenticatorItemView: authenticatorItemView):
guard let secret = state.totpState.authKeyModel?.base32Key else { return }
let newOtpUri = OTPAuthModel(
accountName: state.accountName.nilIfEmpty,
algorithm: state.algorithm,
digits: state.digits,
issuer: state.issuer.nilIfEmpty,
period: state.period.rawValue,
secret: secret
)

let newAuthenticatorItemView = AuthenticatorItemView(
favorite: authenticatorItemView.favorite,
id: authenticatorItemView.id,
name: state.issuer,
totpKey: newOtpUri.otpAuthUri,
username: state.accountName
)
let newAuthenticatorItemView: AuthenticatorItemView
switch state.totpType {
case .steam:
newAuthenticatorItemView = AuthenticatorItemView(
favorite: false,
id: authenticatorItemView.id,
name: state.issuer,
totpKey: "steam://\(secret)",
username: state.accountName
)
case .totp:
let newOtpUri = OTPAuthModel(
accountName: state.accountName.nilIfEmpty,
algorithm: state.algorithm,
digits: state.digits,
issuer: state.issuer.nilIfEmpty,
period: state.period.rawValue,
secret: secret
)

newAuthenticatorItemView = AuthenticatorItemView(
favorite: authenticatorItemView.favorite,
id: authenticatorItemView.id,
name: state.issuer,
totpKey: newOtpUri.otpAuthUri,
username: state.accountName
)
}
try await updateAuthenticatorItem(authenticatorItem: newAuthenticatorItemView)
}
} catch let error as InputValidationError {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import BitwardenSdk
import Foundation

// MARK: - EditAuthenticatorItemState

/// The state of an `EditAuthenticatorItemView`
/// and `EditAdvancedAuthenticatorItemView`
protocol EditAuthenticatorItemState: Sendable {
Expand Down Expand Up @@ -44,4 +46,7 @@ protocol EditAuthenticatorItemState: Sendable {

/// The TOTP key/code state.
var totpState: LoginTOTPState { get set }

/// The currently selected TOTP type.
var totpType: TotpTypeOptions { get set }
}
Loading

0 comments on commit b3976de

Please sign in to comment.