Wir glauben daran,
das Internet sicherer
und geschützter zu machen. Für alle.

Die Open-Source- und Source-available-Apps von 2FAS sind ein zentraler Teil unserer Mission, die Sicherheitsstandards zum Schutz von Online-Konten zu revolutionieren.


                      import UIKit
                      import Common
                      
                      final class TokensViewController: UIViewController {
                          var presenter: TokensPresenter!
                          var addButton: UIBarButtonItem? {
                              navigationItem.rightBarButtonItem
                          }
                          private(set) var gridView: GridView!
                          private(set) var gridLayout: UICollectionViewFlowLayout!
                          private(set) var dataSource: UICollectionViewDiffableDataSource<GridSection, GridCell>!
                          
                          let headerHeight: CGFloat = 50
                          let emptySearchScreenView = GridViewEmptySearchScreen()
                          let emptyListScreenView = GridViewEmptyListScreen()
                          
                          private var configuredWidth: CGFloat = 0
                          var searchBarAdded = false
                          
                          let searchController = CommonSearchController()
                          
                          override func loadView() {
                              gridLayout = UICollectionViewFlowLayout()
                              gridView = GridView(frame: .zero, collectionViewLayout: gridLayout)
                              self.view = gridView
                              gridView.configure()
                          }
                          
                          override func viewDidLoad() {
                              super.viewDidLoad()
                              
                              setupView()
                              setupEmptyScreensLayout()
                              setupEmptyScreensEvents()
                              setupDelegates()
                              setupDataSource()
                              setupDragAndDrop()
                              setupNotificationsListeners()
                          }
                          
                          // MARK: - App events
                          
                          override func viewWillLayoutSubviews() {
                              super.viewWillLayoutSubviews()
                              configureLayout()
                          }
                          
                          override func viewWillAppear(_ animated: Bool) {
                              super.viewWillAppear(animated)
                              presenter.viewWillAppear()
                              startSafeAreaKeyboardAdjustment()
                          }
                          
                          override func viewWillDisappear(_ animated: Bool) {
                              super.viewWillDisappear(animated)
                              stopSafeAreaKeyboardAdjustment()
                          }
                          
                          deinit {
                              NotificationCenter.default.removeObserver(self)
                          }
                      }
                      
                      private extension TokensViewController {
                          func setupView() {
                              extendedLayoutIncludesOpaqueBars = true
                              view.backgroundColor = Theme.Colors.Fill.background
                              title = T.Commons.tokens
                              accessibilityTraits = .header
                          }
                          
                          func setupDelegates() {
                              searchController.searchBarDelegate = self
                              gridView.delegate = self
                          }
                          
                          func setupDataSource() {
                              dataSource = UICollectionViewDiffableDataSource(
                                  collectionView: gridView,
                                  cellProvider: { collectionView, indexPath, item in
                                      if item.cellType == .serviceTOTP {
                                          if collectionView.isEditing {
                                              let cell = collectionView.dequeueReusableCell(
                                                  withReuseIdentifier: GridViewEditItemCell.reuseIdentifier,
                                                  for: indexPath
                                              ) as? GridViewEditItemCell
                                              cell?.update(
                                                  name: item.name,
                                                  additionalInfo: item.additionalInfo,
                                                  serviceTypeName: item.serviceTypeName,
                                                  iconType: item.iconType,
                                                  category: item.category,
                                                  canBeDragged: item.canBeDragged
                                              )
                                              return cell
                                          } else {
                                              let cell = collectionView.dequeueReusableCell(
                                                  withReuseIdentifier: GridViewItemCell.reuseIdentifier,
                                                  for: indexPath
                                              ) as? GridViewItemCell
                                              cell?.update(
                                                  name: item.name,
                                                  secret: item.secret,
                                                  serviceTypeName: item.serviceTypeName,
                                                  additionalInfo: item.additionalInfo,
                                                  iconType: item.iconType,
                                                  category: item.category,
                                                  useNextToken: item.useNextToken
                                              )
                                              return cell
                                          }
                                      } else if item.cellType == .serviceHOTP {
                                          if collectionView.isEditing {
                                              let cell = collectionView.dequeueReusableCell(
                                                  withReuseIdentifier: GridViewEditItemCell.reuseIdentifier,
                                                  for: indexPath
                                              ) as? GridViewEditItemCell
                                              cell?.update(
                                                  name: item.name,
                                                  additionalInfo: item.additionalInfo,
                                                  serviceTypeName: item.serviceTypeName,
                                                  iconType: item.iconType,
                                                  category: item.category,
                                                  canBeDragged: item.canBeDragged
                                              )
                                              return cell
                                          } else {
                                              let cell = collectionView.dequeueReusableCell(
                                                  withReuseIdentifier: GridViewCounterItemCell.reuseIdentifier,
                                                  for: indexPath
                                              ) as? GridViewCounterItemCell
                                              cell?.update(
                                                  name: item.name,
                                                  secret: item.secret,
                                                  serviceTypeName: item.serviceTypeName,
                                                  additionalInfo: item.additionalInfo,
                                                  iconType: item.iconType,
                                                  category: item.category
                                              )
                                              return cell
                                          }
                                      }
                                      let cell = collectionView.dequeueReusableCell(
                                          withReuseIdentifier: GridEmptyCollectionViewCell.reuseIdentifier,
                                          for: indexPath
                                      ) as? GridEmptyCollectionViewCell
                                      return cell
                                  })
                              dataSource.supplementaryViewProvider = { [weak self] collectionView, kind, indexPath
                                  -> UICollectionReusableView? in
                                  let header = collectionView.dequeueReusableSupplementaryView(
                                      ofKind: kind,
                                      withReuseIdentifier: GridSectionHeader.reuseIdentifier,
                                      for: indexPath
                                  ) as? GridSectionHeader
                                  header?.setIsEditing(collectionView.isEditing)
                                  header?.dataSource = self
                                  if let data = self?.dataSource.snapshot().sectionIdentifiers[indexPath.section] {
                                      header?.setConfiguration(data)
                                  }
                                  return header
                              }
                          }
                          
                          func setupDragAndDrop() {
                              gridView.dragDelegate = self
                              gridView.dropDelegate = self
                              gridView.dragInteractionEnabled = presenter.enableDragAndDropOnStart
                          }
                          
                          func setupEmptyScreensLayout() {
                              view.addSubview(emptySearchScreenView, with: [
                                  emptySearchScreenView.leadingAnchor.constraint(equalTo: gridView.frameLayoutGuide.leadingAnchor),
                                  emptySearchScreenView.trailingAnchor.constraint(equalTo: gridView.frameLayoutGuide.trailingAnchor),
                                  emptySearchScreenView.topAnchor.constraint(equalTo: gridView.frameLayoutGuide.topAnchor),
                                  emptySearchScreenView.bottomAnchor.constraint(equalTo: gridView.frameLayoutGuide.bottomAnchor)
                              ])
                              emptySearchScreenView.isHidden = true
                              emptySearchScreenView.alpha = 0
                              
                              view.addSubview(emptyListScreenView, with: [
                                  emptyListScreenView.leadingAnchor.constraint(equalTo: gridView.frameLayoutGuide.leadingAnchor),
                                  emptyListScreenView.trailingAnchor.constraint(equalTo: gridView.frameLayoutGuide.trailingAnchor),
                                  emptyListScreenView.topAnchor.constraint(equalTo: gridView.safeTopAnchor),
                                  emptyListScreenView.bottomAnchor.constraint(equalTo: gridView.safeBottomAnchor)
                              ])
                              emptyListScreenView.isHidden = true
                              emptyListScreenView.alpha = 0
                          }
                          
                          func configureLayout() {
                              guard let screenWidth = UIApplication.keyWindow?.bounds.size.width,
                                    configuredWidth != screenWidth else { return }
                              
                              configuredWidth = screenWidth
                              
                              let cellHeight = Theme.Metrics.servicesCellHeight
                              
                              let minimumCellWidth: CGFloat = Theme.Metrics.pageWidth
                              let itemsInRow = Int(screenWidth / minimumCellWidth)
                              let margin: CGFloat = 0
                              
                              let marginsWidth = margin * CGFloat(itemsInRow - 1)
                              let screenWidthWithoutMargins = screenWidth - marginsWidth
                              let elementWidth = floor(screenWidthWithoutMargins / CGFloat(itemsInRow))
                              
                              gridLayout.itemSize = CGSize(width: elementWidth, height: cellHeight)
                              gridLayout.minimumInteritemSpacing = margin
                              
                              gridLayout.headerReferenceSize = CGSize(width: 100, height: headerHeight)
                              
                              gridLayout.minimumLineSpacing = 0
                          }
                          
                          func setupEmptyScreensEvents() {
                              emptyListScreenView.pairNewService = { [weak self] in self?.presenter.handleShowCamera() }
                              emptyListScreenView.import2FAS = { [weak self] in
                                  AnalyticsLog(.onboardingBackupFile)
                                  self?.presenter.handleImport2FAS()
                              }
                              emptyListScreenView.importGA = { [weak self] in
                                  AnalyticsLog(.onboardingGA)
                                  self?.presenter.handleImportGA()
                              }
                              emptyListScreenView.help = { [weak self] in self?.presenter.handleShowHelp() }
                          }
                          
                          func setupNotificationsListeners() {
                              let center = NotificationCenter.default
                              center.addObserver(
                                  self, selector: #selector(notificationServicesWereUpdated), name: .servicesWereUpdated, object: nil
                              )
                              center.addObserver(
                                  self, selector: #selector(notificationSectionsWereUpdated), name: .sectionsWereUpdated, object: nil
                              )
                              center.addObserver(
                                  self,
                                  selector: #selector(notificationAppDidBecomeActive),
                                  name: UIApplication.didBecomeActiveNotification,
                                  object: nil
                              )
                              center.addObserver(
                                  self,
                                  selector: #selector(notificationAppDidBecomeInactive),
                                  name: UIApplication.willResignActiveNotification,
                                  object: nil
                              )
                              center.addObserver(
                                  self,
                                  selector: #selector(notificationAppDidBecomeInactive),
                                  name: UIApplication.didEnterBackgroundNotification,
                                  object: nil
                              )
                          }
                      }
                      import UIKit
                      import Common
                      
                      final class TokensViewController: UIViewController {
                          var presenter: TokensPresenter!
                          var addButton: UIBarButtonItem? {
                              navigationItem.rightBarButtonItem
                          }
                          private(set) var gridView: GridView!
                          private(set) var gridLayout: UICollectionViewFlowLayout!
                          private(set) var dataSource: UICollectionViewDiffableDataSource<GridSection, GridCell>!
                          
                          let headerHeight: CGFloat = 50
                          let emptySearchScreenView = GridViewEmptySearchScreen()
                          let emptyListScreenView = GridViewEmptyListScreen()
                          
                          private var configuredWidth: CGFloat = 0
                          var searchBarAdded = false
                          
                          let searchController = CommonSearchController()
                          
                          override func loadView() {
                              gridLayout = UICollectionViewFlowLayout()
                              gridView = GridView(frame: .zero, collectionViewLayout: gridLayout)
                              self.view = gridView
                              gridView.configure()
                          }
                          
                          override func viewDidLoad() {
                              super.viewDidLoad()
                              
                              setupView()
                              setupEmptyScreensLayout()
                              setupEmptyScreensEvents()
                              setupDelegates()
                              setupDataSource()
                              setupDragAndDrop()
                              setupNotificationsListeners()
                          }
                          
                          // MARK: - App events
                          
                          override func viewWillLayoutSubviews() {
                              super.viewWillLayoutSubviews()
                              configureLayout()
                          }
                          
                          override func viewWillAppear(_ animated: Bool) {
                              super.viewWillAppear(animated)
                              presenter.viewWillAppear()
                              startSafeAreaKeyboardAdjustment()
                          }
                          
                          override func viewWillDisappear(_ animated: Bool) {
                              super.viewWillDisappear(animated)
                              stopSafeAreaKeyboardAdjustment()
                          }
                          
                          deinit {
                              NotificationCenter.default.removeObserver(self)
                          }
                      }
                      
                      private extension TokensViewController {
                          func setupView() {
                              extendedLayoutIncludesOpaqueBars = true
                              view.backgroundColor = Theme.Colors.Fill.background
                              title = T.Commons.tokens
                              accessibilityTraits = .header
                          }
                          
                          func setupDelegates() {
                              searchController.searchBarDelegate = self
                              gridView.delegate = self
                          }
                          
                          func setupDataSource() {
                              dataSource = UICollectionViewDiffableDataSource(
                                  collectionView: gridView,
                                  cellProvider: { collectionView, indexPath, item in
                                      if item.cellType == .serviceTOTP {
                                          if collectionView.isEditing {
                                              let cell = collectionView.dequeueReusableCell(
                                                  withReuseIdentifier: GridViewEditItemCell.reuseIdentifier,
                                                  for: indexPath
                                              ) as? GridViewEditItemCell
                                              cell?.update(
                                                  name: item.name,
                                                  additionalInfo: item.additionalInfo,
                                                  serviceTypeName: item.serviceTypeName,
                                                  iconType: item.iconType,
                                                  category: item.category,
                                                  canBeDragged: item.canBeDragged
                                              )
                                              return cell
                                          } else {
                                              let cell = collectionView.dequeueReusableCell(
                                                  withReuseIdentifier: GridViewItemCell.reuseIdentifier,
                                                  for: indexPath
                                              ) as? GridViewItemCell
                                              cell?.update(
                                                  name: item.name,
                                                  secret: item.secret,
                                                  serviceTypeName: item.serviceTypeName,
                                                  additionalInfo: item.additionalInfo,
                                                  iconType: item.iconType,
                                                  category: item.category,
                                                  useNextToken: item.useNextToken
                                              )
                                              return cell
                                          }
                                      } else if item.cellType == .serviceHOTP {
                                          if collectionView.isEditing {
                                              let cell = collectionView.dequeueReusableCell(
                                                  withReuseIdentifier: GridViewEditItemCell.reuseIdentifier,
                                                  for: indexPath
                                              ) as? GridViewEditItemCell
                                              cell?.update(
                                                  name: item.name,
                                                  additionalInfo: item.additionalInfo,
                                                  serviceTypeName: item.serviceTypeName,
                                                  iconType: item.iconType,
                                                  category: item.category,
                                                  canBeDragged: item.canBeDragged
                                              )
                                              return cell
                                          } else {
                                              let cell = collectionView.dequeueReusableCell(
                                                  withReuseIdentifier: GridViewCounterItemCell.reuseIdentifier,
                                                  for: indexPath
                                              ) as? GridViewCounterItemCell
                                              cell?.update(
                                                  name: item.name,
                                                  secret: item.secret,
                                                  serviceTypeName: item.serviceTypeName,
                                                  additionalInfo: item.additionalInfo,
                                                  iconType: item.iconType,
                                                  category: item.category
                                              )
                                              return cell
                                          }
                                      }
                                      let cell = collectionView.dequeueReusableCell(
                                          withReuseIdentifier: GridEmptyCollectionViewCell.reuseIdentifier,
                                          for: indexPath
                                      ) as? GridEmptyCollectionViewCell
                                      return cell
                                  })
                              dataSource.supplementaryViewProvider = { [weak self] collectionView, kind, indexPath
                                  -> UICollectionReusableView? in
                                  let header = collectionView.dequeueReusableSupplementaryView(
                                      ofKind: kind,
                                      withReuseIdentifier: GridSectionHeader.reuseIdentifier,
                                      for: indexPath
                                  ) as? GridSectionHeader
                                  header?.setIsEditing(collectionView.isEditing)
                                  header?.dataSource = self
                                  if let data = self?.dataSource.snapshot().sectionIdentifiers[indexPath.section] {
                                      header?.setConfiguration(data)
                                  }
                                  return header
                              }
                          }
                          
                          func setupDragAndDrop() {
                              gridView.dragDelegate = self
                              gridView.dropDelegate = self
                              gridView.dragInteractionEnabled = presenter.enableDragAndDropOnStart
                          }
                          
                          func setupEmptyScreensLayout() {
                              view.addSubview(emptySearchScreenView, with: [
                                  emptySearchScreenView.leadingAnchor.constraint(equalTo: gridView.frameLayoutGuide.leadingAnchor),
                                  emptySearchScreenView.trailingAnchor.constraint(equalTo: gridView.frameLayoutGuide.trailingAnchor),
                                  emptySearchScreenView.topAnchor.constraint(equalTo: gridView.frameLayoutGuide.topAnchor),
                                  emptySearchScreenView.bottomAnchor.constraint(equalTo: gridView.frameLayoutGuide.bottomAnchor)
                              ])
                              emptySearchScreenView.isHidden = true
                              emptySearchScreenView.alpha = 0
                              
                              view.addSubview(emptyListScreenView, with: [
                                  emptyListScreenView.leadingAnchor.constraint(equalTo: gridView.frameLayoutGuide.leadingAnchor),
                                  emptyListScreenView.trailingAnchor.constraint(equalTo: gridView.frameLayoutGuide.trailingAnchor),
                                  emptyListScreenView.topAnchor.constraint(equalTo: gridView.safeTopAnchor),
                                  emptyListScreenView.bottomAnchor.constraint(equalTo: gridView.safeBottomAnchor)
                              ])
                              emptyListScreenView.isHidden = true
                              emptyListScreenView.alpha = 0
                          }
                          
                          func configureLayout() {
                              guard let screenWidth = UIApplication.keyWindow?.bounds.size.width,
                                    configuredWidth != screenWidth else { return }
                              
                              configuredWidth = screenWidth
                              
                              let cellHeight = Theme.Metrics.servicesCellHeight
                              
                              let minimumCellWidth: CGFloat = Theme.Metrics.pageWidth
                              let itemsInRow = Int(screenWidth / minimumCellWidth)
                              let margin: CGFloat = 0
                              
                              let marginsWidth = margin * CGFloat(itemsInRow - 1)
                              let screenWidthWithoutMargins = screenWidth - marginsWidth
                              let elementWidth = floor(screenWidthWithoutMargins / CGFloat(itemsInRow))
                              
                              gridLayout.itemSize = CGSize(width: elementWidth, height: cellHeight)
                              gridLayout.minimumInteritemSpacing = margin
                              
                              gridLayout.headerReferenceSize = CGSize(width: 100, height: headerHeight)
                              
                              gridLayout.minimumLineSpacing = 0
                          }
                          
                          func setupEmptyScreensEvents() {
                              emptyListScreenView.pairNewService = { [weak self] in self?.presenter.handleShowCamera() }
                              emptyListScreenView.import2FAS = { [weak self] in
                                  AnalyticsLog(.onboardingBackupFile)
                                  self?.presenter.handleImport2FAS()
                              }
                              emptyListScreenView.importGA = { [weak self] in
                                  AnalyticsLog(.onboardingGA)
                                  self?.presenter.handleImportGA()
                              }
                              emptyListScreenView.help = { [weak self] in self?.presenter.handleShowHelp() }
                          }
                          
                          func setupNotificationsListeners() {
                              let center = NotificationCenter.default
                              center.addObserver(
                                  self, selector: #selector(notificationServicesWereUpdated), name: .servicesWereUpdated, object: nil
                              )
                              center.addObserver(
                                  self, selector: #selector(notificationSectionsWereUpdated), name: .sectionsWereUpdated, object: nil
                              )
                              center.addObserver(
                                  self,
                                  selector: #selector(notificationAppDidBecomeActive),
                                  name: UIApplication.didBecomeActiveNotification,
                                  object: nil
                              )
                              center.addObserver(
                                  self,
                                  selector: #selector(notificationAppDidBecomeInactive),
                                  name: UIApplication.willResignActiveNotification,
                                  object: nil
                              )
                              center.addObserver(
                                  self,
                                  selector: #selector(notificationAppDidBecomeInactive),
                                  name: UIApplication.didEnterBackgroundNotification,
                                  object: nil
                              )
                          }
                      }
                    

Missionsgetrieben

Online-Sicherheit ist entscheidend für die Privatsphäre jedes Menschen – online wie offline. Kontoübernahmen führen zu Lecks persönlicher Daten, zum Verlust wertvoller und sensibler Informationen, zu Identitätsmissbrauch in sozialen Medien und verursachen jedes Jahr Schäden in Milliardenhöhe.

Woher weißt du, welche Sicherheitslösung die beste für dich ist? Solltest du Tools allein nach Vertrauen oder Markenruf bewerten – oder anhand verlässlicher Informationen, einschließlich des Quellcodes?

Deshalb haben wir das 2FAS-Projekt ins Leben gerufen – eine Initiative, die für Transparenz, Privatsphäre und Sicherheit steht. Die 2FAS-Apps sind für die Bedürfnisse aller entwickelt und bleiben dabei kostenlos, zugänglich und einfach zu bedienen.
11

Jahre sorgfältige Entwicklung und kontinuierliche Verbesserungen

4.7

durchschnittliche Rezensionen bei Google Play und im App Store

6+

Millionen Downloads weltweit

Wie alles begann und wo wir heute stehen

2015
Mark

Mark gründet 2FAS.

2016

Wir arbeiten an R&D-Projekten rund um Internetsicherheit und 2FA.

2017

2FAS Auth erscheint im App Store und bei Google Play.

2018

2FAS Auth erreicht die ersten 100.000 Downloads.

2019

2FAS Auth wird nach neuen UI-Richtlinien neu gestaltet.

2020

2FAS Auth erreicht 1 Million Downloads.

2021

2FAS Auth erhält Backups und erreicht 2,5 Millionen Downloads.

2022

Wir starten einen Discord-Server und eine eigene Browser-Erweiterung. 2FAS Auth erreicht 5 Millionen Downloads und wird zu einem Open-Source-Projekt.

2023

Wir fügen 2FAS Auth mehrere neue Sprachen hinzu und erreichen 6 Millionen Downloads.

2024

Wir beginnen mit einem neuen Projekt – 2FAS Pass, einem Local-first-Passwortmanager. 2FAS Auth erreicht 8 Millionen Downloads.

2025

2FAS Pass erscheint im App Store und bei Google Play.

Weiter

Unser TEAM

Wir begeistern uns für Sicherheit, Design und Open Source, sind immer neugierig und bereit, Online-Sicherheit neu zu denken.

Kernteam

Mark
Gründer, CEO
Mark
Greg
CTO
Greg
Andrew
CMO
Andrew
Paul
CDO, UX
Paul
Raphael
Entwicklung
Raphael
Zibi
Entwicklung
Zibi
Matt
Entwicklung
Matt
Tobias
Entwicklung
Tobias
Chris
Entwicklung
Chris
Matt
Design
Matt
Dominic
Design
Dominic
Kate
Design
Kate
Olga
Design
Olga
Irena
Brand Relations Manager
Irena
Rafael
Leitender-Übersetzer, QA
Rafael
Leo
Community Leiter
Leo
Matt
Sicherheitsbeauftragter
Matt
Mitwirkende

Das Projekt wächst mit der Unterstützung einer großartigen Community, die regelmäßig den Code und die Inhalte der 2FAS-Apps verbessert und die 2FAS-Community weiter ausbaut.

Dhavan Bhayani@‌Dhavan Bhayani

Yurashi

AndJustice4All

Leonardo@Spluffity

Vijay Pondini@vijaypondini

Chris@Bravo_six

Justin Reitmeier

Fluffy

Jan Tennert

Noah@noah

Pedro Monteiro

SrHallowen_

SadBeats

Syun

Emp

NΞОИ

ThePokyx

Artem@Globart

Samuel Rollón del Río

Rosanna @roclahy

pmtz

Skyglitch

Davide Fiorini@fiorins

ΛMNESIΛ

Bruce

Kyriakos Parmakelis@Talos

Alexander K

polygon0323/ぽりごん

ROCKTAKEY

Mikuqwq

Xiaohuli_zi

Yoru.kot

Ceviz

Arsquid

Nifty

xfoxx

gabrielebonini99

Möchtest du zum 2FAS-Projekt beitragen?

Wir stellen die 2FAS-Apps der ganzen Welt völlig kostenlos zur Verfügung. Wenn du daran glaubst, das Internet für alle sicher, offen und geschützt zu halten, schätzen wir deinen Beitrag sehr!

Möchtest du zum 2FAS-Projekt beitragen?

Es gibt mehrere Möglichkeiten, wie du zum 2FAS-Projekt beitragen kannst:

  • Prüfe den 2FAS-Quellcode.
  • Trage Code-Änderungen bei.
  • Erhöhe die Sicherheit, indem du Schwachstellen findest und behebst.
  • Übersetze die 2FAS-App in neue Sprachen.
  • Mach die 2FAS-App bekannt (Social Media / andere Kanäle).
  • Hilf anderen Nutzern bei Problemen mit 2FA und den 2FAS-Apps auf unserem Discord-Server.
  • Unterstütze andere Nutzer mit Dokumentation und hilf ihnen, Schwierigkeiten zu lösen.
  • Aktualisiere und erweitere die Datenbank der Service-Icons.
  • Spende für das 2FAS-Projekt.

Lust auf ein Treffen?
Lass uns online
oder offline vernetzen!

Wir arbeiten zu 100 % remote. Wenn du an einer Zusammenarbeit interessiert bist, lass uns online sprechen oder auf einen Kaffee in Las Vegas treffen!

Du findest uns im sonnigen Nevada

Two Factor Authentication Service, Inc.

1887 Whitney Mesa Dr #2130

Henderson, Nevada 89014

Lust auf ein Treffen? Lass uns online oder offline vernetzen!Lust auf ein Treffen? Lass uns online oder offline vernetzen!