Email/SMS Authentication

Register or login a user using One-Time Passcodes or Magic Links on iOS

As of this writing, your Passage app will default to One-Time Passcodes, but you can also choose to use Magic Links instead. Both One-Time Passcodes and Magic Links can be sent via email or phone (depending on what kind of identifier your user provides).

Passage highly recommends using One-Time Passcodes over Magic Links, as they are easier to implement, more secure, and a better user experience.

One-Time Passcode (OTP)

Activate OTP

If passage.register or passage.login returns a OneTimePasscode, it will contain an id you'll use to finish the authentication process.

When the user inputs their OTP into your app, you'll send their input string along with the OTP id through passage.oneTimePasscodeActivate.

func authenticateOTPUser(userInput: String, otpId: String) async {
    do {
        let authToken = try await passage
            .oneTimePasscodeActivate(otp: userInput, otpId: otpId)
            .authToken
        // Do authenticated stuff
    } catch {
        // Handle error
    }
}

If the user opens the Magic Link from the same iOS device and you've setup app links correctly, that link will open your iOS app and you can grab the magic link string from your SceneDelegate (see example here). Then you can call passage.magicLinkActivate(userMagicLink) to authenticate the user.

func authenticateMagicLinkUser(userMagicLink: String) async {
    do {
        let authToken = try await passage
            .magicLinkActivate(userMagicLink: userMagicLink)
            .authToken
        // Do authenticated stuff
    } catch {
        // Handle errors
    }
}

If the user opens the Magic Link on a different device or you have not setup app links, it is up to your web front end to handle and activate the Magic Link. In this case, you’ll need to continually check the status of the link in your Android app. Once the Magic Link has been activated by the web front end, passage.getMagicLinkStatus will return a PassageAuthResult and your user will be authenticated.

func checkMagicLinkStatus() async {
    guard let token = try? await passage.getMagicLinkStatus(id: magicLinkId).authToken else {
        // Magic link not activated yet, check again later.
        return
    }
    // Magic link activated! Do authenticated stuff
}

Last updated