What the user sees
Autheris never adds a code just because a link arrived. Since 2.8, a setup link opens a review that shows the code’s name and account and waits for the user to tap Import. If App Lock is on, the review waits until they unlock. Nothing is saved if they cancel.
So the issuer and account you send are exactly what the user is asked to approve. Use the name people know your service by, and the email or username they signed in with.
Requirements
- iOS 15, macOS 12 or visionOS 1, and Swift 6.
- The
autheris://addlink needs Autheris 3.0 or later. Anyone on an older version gets the standardotpauth://link instead (see below).
Install
In Xcode, choose File › Add Package Dependencies… and enter:
https://github.com/Nerdykidtech/AutherisKit
Or add it to Package.swift:
.package(url: "https://github.com/Nerdykidtech/AutherisKit", from: "1.0.0")
Add the button
Your server generates the secret when the user turns on two-factor authentication, as it would for a QR code. Pass it in with your service’s name and the user’s account:
import AutherisKit
let setup = AutherisSetup(
issuer: "My App",
account: user.email,
secret: totpSecret // Base32, from your server
)
AddToAutherisButton(setup: setup) { result in
switch result {
case .openedAutheris, .openedOtherAuthenticator:
break // now ask for a code (step 3 below)
case .noAuthenticator:
showSetupKey = true
case .invalidSetup(let problem):
assertionFailure("\(problem)")
}
}
When the user taps it:
- AutherisKit opens Autheris with the code. Autheris shows it for review.
- If Autheris isn’t installed, it opens the standard
otpauth://link instead, which goes to whichever authenticator app the user has. If they have none, you get.noAuthenticator, so you can show the setup key. - Then ask the user to type a code from the app, and check it on your server before you turn on 2FA. Opening the app doesn’t prove the code was saved: the user can cancel the review. Your check is the only proof.
Have your own button design? AutherisLauncher.open(_:with:onResult:)
does the same open-and-fall-back with your openURL action, and
setup.autherisURL() and setup.otpauthURL() give you the
links on their own. Use otpauthURL() for the QR code you show people
setting up on another device.
The link format
You don’t need AutherisKit. Any platform can build the link, including a web page opened in Safari:
autheris://add?uri=<percent-encoded otpauth:// link>
uri is a standard
Key URI Format
link for one time-based code. Percent-encode all of it, leaving only
A–Z a–z 0–9 - . _ ~ as they are. For example, in JavaScript:
const otpauth =
`otpauth://totp/${encodeURIComponent(issuer)}:${encodeURIComponent(account)}` +
`?secret=${secret}&issuer=${encodeURIComponent(issuer)}`;
const link = `autheris://add?uri=${encodeURIComponent(otpauth)}`;
Autheris reads secret, issuer, algorithm
(SHA1, SHA256 or SHA512), digits
and period, with the usual defaults of SHA1, 6 digits and 30
seconds. A link that isn’t a valid otpauth:// link with a Base32
secret shows the user an error, and nothing is added.
Before you ship
- Verify a code before turning 2FA on. Opening the link doesn’t prove the code was saved.
- Keep the link out of logs and analytics. It contains the secret, just like the QR code does.
- Always offer the setup key or a QR code as well, for people setting up on another device or using a different app.
- Use a name people recognise. It’s what they approve in the review, and what they’ll look for later.
Questions
Open an issue on GitHub, or email support@autheris.app. If you find a way for a link to add a code without the user approving it, please email security@autheris.app first, rather than opening a public issue.