Ios Developer
Ios Developer

Reputation: 888

Error while doing phone number verification using twilio in swift

I want to verify phone number by getting one time password. But I am getting some error. Please look into the code bellow and help me to resolve it. I am using Twilio for mobile verification. And Alamofire for API request. But the error I am getting like:-

Authentication Error - No credentials provided.
The data couldn’t be read because it isn’t in the correct format

My code is:-

Here is my model class: -

...struct SendVerificationCode: Codable {
let status: String?
let payee: String?
let dateUpdated: Date?
let sendCodeAttempts: [SendCodeAttempt]?
let accountSid, to: String?
let amount: Int?
let valid: Bool?
let lookup: Lookup?
let url: String?
let sid: String?
let dateCreated: Date?
let serviceSid, channel: String?

enum CodingKeys: String, CodingKey {
    case status, payee
    case dateUpdated = "date_updated"
    case sendCodeAttempts = "send_code_attempts"
    case accountSid = "account_sid"
    case to, amount, valid, lookup, url, sid
    case dateCreated = "date_created"
    case serviceSid = "service_sid"
    case channel
}
}


struct Lookup: Codable {
let carrier: Carrier?
}


struct Carrier: Codable {
let mobileCountryCode, type: String?
let errorCode: String?
let mobileNetworkCode, name: String?

enum CodingKeys: String, CodingKey {
    case mobileCountryCode = "mobile_country_code"
    case type
    case errorCode = "error_code"
    case mobileNetworkCode = "mobile_network_code"
    case name
}
}


 struct SendCodeAttempt: Codable {
let channel, time: String?
}...

Api Request:-

...func sendcode(mobileWithCode: String, completion: @escaping sendTwillioVerificationCodeCompletion) {

    let url = URL(string: SEND_TWILIO_VERIFICATION_CODE)
   var urlRequest = URLRequest(url: url!)
   urlRequest.httpMethod = HTTPMethod.post.rawValue
   urlRequest.addValue(userNameData, forHTTPHeaderField: "Username")
    urlRequest.addValue(PasswordData, forHTTPHeaderField: "Password")
    urlRequest.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")


   Alamofire.request(urlRequest).responseJSON { (response) in
       if let error = response.result.error {
           debugPrint(error.localizedDescription)
           completion(nil)
           return
       }

       guard let data = response.data else { return completion(nil)}

       Common.sharedInstance().printRequestOutput(data: data)

       let jsonDecoder = JSONDecoder()
       do {
           let clear = try jsonDecoder.decode(SendVerificationCode.self, from: data)
           completion(clear)
       } catch {
           debugPrint(error.localizedDescription)
           completion(nil)
       }
   }
}...

But i am getting error:-

   {"code": 20003, "detail": "Your AccountSid or AuthToken was incorrect.", "message": "Authentication Error - No credentials provided", "more_info": "https://www.twilio.com/docs/errors/20003", "status": 401}
   "The data couldn’t be read because it isn’t in the correct format."

Also i have tried the following code:-

import Foundation
semaphore = DispatchSemaphore (value: 0)

let parameters = "To=+919778882332&Channel=sms"
let postData =  parameters.data(using: .utf8)

var request = URLRequest(url: URL(string:  myUrl)!,timeoutInterval: Double.infinity)
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.addValue(requestData, forHTTPHeaderField: "Authorization")

request.httpMethod = "POST"
request.httpBody = postData

let task = URLSession.shared.dataTask(with: request) { data, response, error in 
guard let data = data else {
print(String(describing: error))
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}

task.resume()
semaphore.wait()

But i am getting error like

"Invalid parameter"

Upvotes: 0

Views: 968

Answers (2)

philnash
philnash

Reputation: 73029

Twilio developer evangelist here.

It looks as though your code is trying to call the Twilio API directly from the device and that you weren't setting your Account SID or Auth Token in that.

The issue here is that you should not store or access your auth token from within your application. That would make your account sid and auth token vulnerable to be stolen and then used to abuse your account.

Instead, you should create a server side application that talks to the Twilio API and then call that from your application.

As Jamil pointed out, there is a blog post you can follow on performing phone verification in iOS with Twilio Verify and Swift and I recommend you go through that. It includes an example server side application to call the Twilio Verify API built in Python, but you could build your own too.

Upvotes: 2

Jamil Hasnine Tamim
Jamil Hasnine Tamim

Reputation: 4448

Here is sample code:

import UIKit

class ViewController: UIViewController {

    static let path = Bundle.main.path(forResource: "Config", ofType: "plist")
    static let config = NSDictionary(contentsOfFile: path!)
    private static let baseURLString = config!["serverUrl"] as! String

    @IBOutlet var countryCodeField: UITextField! = UITextField()
    @IBOutlet var phoneNumberField: UITextField! = UITextField()
    @IBAction func sendVerification() {
        if let phoneNumber = phoneNumberField.text,
            let countryCode = countryCodeField.text {
            ViewController.sendVerificationCode(countryCode, phoneNumber)
        }
    }

    static func sendVerificationCode(_ countryCode: String, _ phoneNumber: String) {

        let parameters = [
            "via": "sms",
            "country_code": countryCode,
            "phone_number": phoneNumber
        ]

        let path = "start"
        let method = "POST"

        let urlPath = "\(baseURLString)/\(path)"
        var components = URLComponents(string: urlPath)!

        var queryItems = [URLQueryItem]()

        for (key, value) in parameters {
            let item = URLQueryItem(name: key, value: value)
            queryItems.append(item)
        }

        components.queryItems = queryItems

        let url = components.url!

        var request = URLRequest(url: url)
        request.httpMethod = method

        let session: URLSession = {
            let config = URLSessionConfiguration.default
            return URLSession(configuration: config)
        }()

        let task = session.dataTask(with: request) {
            (data, response, error) in
            if let data = data {
                do {
                    let jsonSerialized = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]

                    print(jsonSerialized!)
                }  catch let error as NSError {
                    print(error.localizedDescription)
                }
            } else if let error = error {
                print(error.localizedDescription)
            }
        }
        task.resume()
    }
}

For more please check this link: Link.

Upvotes: 1

Related Questions