{"id":21515665,"url":"https://github.com/sqreen/twofa","last_synced_at":"2025-04-09T20:12:27.576Z","repository":{"id":49811057,"uuid":"185823497","full_name":"sqreen/twofa","owner":"sqreen","description":"A TouchID-aware 2-factor authenticator for macOS","archived":false,"fork":false,"pushed_at":"2020-06-20T19:15:49.000Z","size":1379,"stargazers_count":147,"open_issues_count":5,"forks_count":10,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-09T20:12:20.308Z","etag":null,"topics":["2fa","2fa-client","authenticator","macos","macosx","security","swift","totp","touchid","touchid-authentication","two-factor-authentication"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sqreen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-05-09T15:15:51.000Z","updated_at":"2025-02-19T18:33:26.000Z","dependencies_parsed_at":"2022-09-10T14:40:29.145Z","dependency_job_id":null,"html_url":"https://github.com/sqreen/twofa","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqreen%2Ftwofa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqreen%2Ftwofa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqreen%2Ftwofa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqreen%2Ftwofa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sqreen","download_url":"https://codeload.github.com/sqreen/twofa/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248103872,"owners_count":21048245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["2fa","2fa-client","authenticator","macos","macosx","security","swift","totp","touchid","touchid-authentication","two-factor-authentication"],"created_at":"2024-11-23T23:56:17.325Z","updated_at":"2025-04-09T20:12:27.548Z","avatar_url":"https://github.com/sqreen.png","language":"Swift","readme":"\u003ch1 align=\"center\"\u003etwofa\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  TouchID-aware 2-factor authentication for macOS\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003csmall\u003eLicenced under an MIT licence.\u003c/small\u003e | Maintainer: \u003ca href=\"mailto:janis@sqreen.com\"\u003eJānis Kiršteins \u0026lt;janis@sqreen.com\u0026gt;\u003c/a\u003e (\u003ca href=\"https://twitter.com/jkirsteins\"\u003e@jkirsteins\u003c/a\u003e)\u003c/p\u003e\n\n\u003cp align=\"center\"\u003eCopyright \u0026copy; 2019 Sqreen\u003c/p\u003e\n\n![Screenshot of twofa asking for authentication](img/get.png)\n\n## Table of Contents\n\n- [Overview](#overview)\n  - [Rationale](#rationale)\n  - [Supported macOS Versions](#supported-macos-versions)\n  - [Info.plist](#infoplist)\n  - [macOS entitlements](#macos-entitlements)\n  - [Platform Support](#platform-support)\n- [Usage](#usage)\n  - [add](#add)\n  - [list](#list)\n  - [rm](#rm)\n  - [test](#test)\n  - [get](#get)\n- [Installation](#installation)\n- [Building from Source](#building-from-source)\n  - [Before Building](#before-building)\n    - [Linux Dependencies](#linux-dependencies)\n  - [swift build](#swift-build)\n  - [Xcode](#xcode)\n- [Testing](#testing)\n- [Contributing](#contributing)\n\n## Overview\n\n`twofa` is written in Swift. It uses the macOS keychain API to store one-time password generation parameters using the [`.userPresence`](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags/1392879-userpresence) and [`.whenPasscodeSetThisDeviceOnly`](https://developer.apple.com/documentation/security/ksecattraccessiblewhenpasscodesetthisdeviceonly) constraints.\n\nThis constraint will require the user's password or TouchID to access the data.\n\n**Note**: It is possible to register both [time-based (TOTP)](https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm) and [HMAC-based (HOTP)](https://en.wikipedia.org/wiki/HMAC-based_One-time_Password_algorithm) accounts, but only TOTP code generation is implemented.\n\n### Rationale\n\nWhile commonly 2FA (2-factor authentication) is used via a smartphone app, for heavy use a computer-based code generation can be more efficient. While there are some existing TOTP (time-based one time password) generating applications for computers, they have one or more drawbacks:\n\n- they require you to enter a password every time you want to use it\n- no command line interface\n\n\u003e **Sidenote**: there probably exist some authenticator apps that store the secrets in plaintext on the filesystem, and do not have the first problem. However, if such a tool existed, it would be far too insecure to use in a serious capacity\n\nIt seems that there are no good solutions available currently that mitigate these, so this application was built to:\n\n- allow (on TouchID-equipped Macs) to use the fingerprint sensor, instead of requiring a password. This provides a much better user experience, especially if you need to generate codes often.\n- be usable from the terminal. This is a subjective point and not a problem perse, but some people prefer the simplicity of `Terminal.app`. While it is not inconceivable that a GUI (graphical user interface) is added to this project down the line, it seems much less likely that a GUI-first project would add a complementary command-line utility down the line.\n\n\u003e **Sidenote**: originally the idea was to have TouchID mandatory, but the macOS keychain API does not support this at the moment. If such an API became available, it could be adopted to gain much stronger security guarantees. The current approach of entangling the secrets with the user's password is likely brute-forceable, whereas a hardware-backed approach would not be (or, at the very least, would make it considerably more difficult to perform an attack).\n\n### Supported macOS Versions\n\nBuilt and tested on macOS Catalina 10.15.5.\n\n### Info.plist\n\nAn Info.plist is embedded into the binary during linking, and the `version` command will read the bundle version from that.\n\n### macOS entitlements\n\nThe macOS keychain API requires the binary to be codesigned and contain appropriate entitlements.\n\nSince this is a command-line utility, some extra work needs to be done to perform a functioning build:\n\n- obtain a valid macOS codesigning key (obtainable from the [Apple Developer website](https://developer.apple.com/account))\n  - install the corresponding provisioning profile locally, or the binary will not run for you\n  - to have the binary work when distributed, you will need to sign with a `Developer ID` app distribution key\n- find out your team ID (e.g. similar to `N2JEMR5FZG`)\n- configure the file `Supporting/twofa.entitlements` to contain:\n  - a valid application identifier\n  - your team identifier\n  - a valid keychain access group\n- codesign the binary after building using `codesign` and embed the entitlements from `Supporting/twofa.entitlements` into it\n\n**NOTE**: codesigning is required even when developing locally, otherwise the keychain API will not work\n\n### Platform Support\n\nOnly macOS is supported and tested.\n\nHowever, it should be possible to add Linux support using a different underlying keychain API.\n\n## Usage\n\n\u003e If you want to test the app with a test account, you can use http://security-totp.appspot.com\n\n![](img/main.png)\n\nWhat you want to do normally is run:\n\n    $ twofa add\n\nAnd then take a screenshot (to the pasteboard, not to a file - i.e. using `Command-Control-Shift-4`) of a QR code containing your OTP (one-time password) seed.\n\nIt should print out that some data was found, and that it is adding an account with the name from the QR code. E.g.:\n\n    Found: test@security-totp.appspot.com\n\nThen, to get the OTP, type:\n\n```bash\n# substitute the last argument with your actual account name\ntwofa get test@security-totp.appspot.com\n```\n\nThe OTP will not be output by default, and instead will be put directly into the pasteboard.\n\n(After the application terminates, the previous pasteboard content will be restored.)\n\n### add\n\n    $ twofa add [--label \u003clabel\u003e --secret \u003csecret\u003e] [--uri \u003cotpauth_uri\u003e] [--debug]\n\nYou can call this with no extra arguments, and the default behaviour will be to wait for a valid screenshot to appear in the pasteboard of your Mac.\n\nHowever, you can also provide the label and secret directly:\n\n```bash\ntwofa add --label account_name --secret LZYSI2TSMRSWOYJSPEYSM5Q\n```\n\nYou can also provide an [`otpauth://` URI](https://github.com/google/google-authenticator/wiki/Key-Uri-Format):\n\n```bash\ntwofa add --uri otpauth://totp/avi-9605?secret=LZYSI2TSMRSWOYJSPEYSM5Q\u0026issuer=SparkPost\n```\n\nFinally, if you add `--debug` then the parsed data will be output to `stdout` so you can see what is being stored in the keychain. **This is not recommended normally, as it will leave sensitive data in your history.**\n\nThis command does not require authentication.\n\n### list\n\n    $ twofa list\n\n`twofa list` will list all the account labels that you have added. It will require authentication (unless there are no accounts added, in which case it will print out nothing and not ask for authentication).\n\n### rm\n\n    $ twofa rm \u003clabel\u003e\n\n`twofa rm account_name` will remove the specified account name from the keychain.\n\nThis will require authentication (although the keychain itself does not require authentication for item removal)\n\n### test\n\n    $ twofa test\n\nThis is a handy method just to check if the entitlements are correct, and the application is authorized to access the keychain.\n\nIt should ask for authentication, and print `OK`.\n\n### get\n\n    $ twofa get \u003clabel\u003e [--stdout]\n\nThis will calculate the current OTP for the specified account, and copy it to the pasteboard.\n\nPasteboard content will be restored once the application closes.\n\nIf the application is not closed, it will automatically terminate in a short while on its own (so you can not forget it running in the background).\n\nBy default, it will not output the codes to `stdout`, however if you pass the `--stdout` flag, then the code will be output in addition to being put into the pasteboard.\n\n## Installation\n\nTo install a pre-built binary, you will need [Homebrew](https://brew.sh):\n\n    $ brew tap sqreen/speakeasy\n    $ brew install twofa\n\n## Building from Source\n\n### Before Building\n\nBefore you build, you must:\n\n- edit `Supporting/Info.plist` (optional)\n- edit `Supporting/twofa.entitlements` (**important**)\n- edit `build_mac.sh` and replace the code sign identity string with the value corresponding to your Apple-issued key that you will use to codesign\n\n#### Linux Dependencies\n\n    $ apt-get install openssl libssl-dev\n\n### swift build\n\n**NOTE**: *Package.resolved* is kept in .gitignore because it gets regenerated when switching Platforms (removing\nMac/Linux specific packages, and adding Linux/Mac specific packages, and vice versa)\n\nIf you want to build using `swift build`, you can use the script `build.sh`. It will:\n\n- build a release version\n- embed the Info.plist into it\n- codesign it with the entitlements file\n\n### Xcode\n\nIf you want to use Xcode, you can use the accompanying `regen.rb` script to generate a valid Xcode project.\n\nIt invokes `swift package generate-xcodeproj` and then applies configuration changes to:\n\n- embed the Info.plist into the binary after building\n- use the correct entitlements file\n- set the correct signing identity\n\n## Testing\n\n    $ swift test\n\n## Contributing\n\nContributions are welcomed and encouraged! Take a look at the [contribution guidelines](CONTRIBUTING).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqreen%2Ftwofa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsqreen%2Ftwofa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqreen%2Ftwofa/lists"}