Search code examples
iosswiftone-time-password

Automatic OTP verification in iOS: OTP not appearing on the keyboard toolbar


I am trying to implement automatic OTP verification in my Xcode project. I have written the following code, but the OTP value doesn't appear on the keyboard toolbar as expected. I have also added the "Autofill Credential Provider" under the Xcode Capability section. My testing device is running on iOS 16, and I have set the keyboard type under the text input trait to "Number Pad." I have also tried with the default keyboard type, but it didn't work either. AutoFill Password is enabled on my device settings

Here is the code snippet I have used:

override func viewDidLoad() {
    super.viewDidLoad()

    if #available(iOS 12.0, *) {
        otp1.textContentType = .oneTimeCode
        otp2.textContentType = .oneTimeCode
        otp3.textContentType = .oneTimeCode
        otp4.textContentType = .oneTimeCode
    }

    otp1.addTarget(self, action: #selector(didEdited), for: .editingChanged)
    otp2.addTarget(self, action: #selector(didEdited), for: .editingChanged)
    otp3.addTarget(self, action: #selector(didEdited), for: .editingChanged)
    otp4.addTarget(self, action: #selector(didEdited), for: .editingChanged)
    otp1.becomeFirstResponder()
}

And I defined didEdited method in viewController

@objc func didEdited(textField: UITextField) {
    let text = textField.text

    if text?.count == 1 {
        switch textField {
        case otp1:
            otp2.becomeFirstResponder()
        case otp2:
            otp3.becomeFirstResponder()
        case otp3:
            otp4.becomeFirstResponder()
        case otp4:
            otp4.resignFirstResponder()
        default:
            break
        }
    }

    if text?.count == 0 {
        switch textField {
        case otp1:
            otp1.becomeFirstResponder()
        case otp2:
            otp2.text = ""
            otp1.becomeFirstResponder()
        case otp3:
            otp3.text = ""
            otp2.becomeFirstResponder()
        case otp4:
            otp4.text = ""
            otp3.becomeFirstResponder()
        default:
            break
        }
    }
}

The OTP message format I am receiving is as follows: "Your OTP to register/access [App Name] is 1654".

I appreciate any insights or suggestions to resolve this issue.


Solution

  • You need to play around with your SMS text. iOS does recognise OTP codes only if it matched with some format.

    First of all be sure that Autofill passwords is turned on in your settings.

    Secondary, play with sms text. Make sure otp message phrase has "code" or "passcode" or "password" and message is copyable.

    Examples, that work:

    1. Some text about and SMS-code: 12345 - correct
    2. Some text about and Your code: 1234 - correct
    3. Some text about and SMS-code: 12345 correct
    4. Some text about and Your password: 1234 correct

    Also, take care about localisations. If your device has different localisation, that comes in sms - autofill can fail. And security code only work with System keyboard. Avoid using custom keyboard.