Search code examples
iosjsonswiftbasic-authentication

Basic authentication with JSON


The JSON page I'm requesting requires a password and username both of type string. The Username and password belong to the developer... By the way it is able to reach the page I just can't get past the authentication.

This is the api url: https://api.intrinio.com/prices?identifier=AAPL

If I've left out some information or code let me know and I'll provide it.

class ViewController: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {

    //MARK: - Outlets
    @IBOutlet weak var labelTwo: UILabel!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var tickerTextField: UITextField!

    //MARK: - Properties
    let userPasswordString = ""
    let userPassword = ""

    //MARK: - View Did Load
    override func viewDidLoad() {
        tickerTextField.textColor = UIColor.lightGray
        tickerTextField.text = "Search Ticker"
        tickerTextField.delegate = self

        let jsonUrlString = "https://api.intrinio.com/prices?identifier=\(ticker)"
        print(jsonUrlString)
        guard let url = URL(string: jsonUrlString) else { return }
        URLSession.shared.dataTask(with: url) { (data, response, err) in
            let dataAsString = String(data: data!, encoding: .utf8)
            print(dataAsString!)
            guard let data = data else { return }
            do {
                let jsonDecoder = JSONDecoder()
                let tickerPrice = try jsonDecoder.decode(TickerPrice.self, from: data)
                DispatchQueue.main.async {
                   print(tickerPrice.name)
                }
            } catch let jsonErr {
                print("Error serielaising jason", jsonErr)
            }
            }.resume()

    }

Solution

  • From the documentation:

    Private To authorize your access to the Intrinio API:

    // With shell, you must include the username and 
    // password header
    curl "https://api.intrinio.com/data_point?identifier=AAPL&item=close_price"
      -u "API_USERNAME:API_PASSWORD"
    
    // With the '-u' option in curl, it will automatically
    // convert the username and password into the 
    // appropriate header. If you do not use this 
    // option or it is not available to you, you must 
    // include a header with the basic auth credentials 
    // included as base64 encoded.
    curl "https://api.intrinio.com/data_point?identifier=AAPL&item=close_price"
      -H "Authorization: Basic $BASE64_ENCODED(API_USERNAME:API_PASSWORD)"
    

    For private/trusted environments, use Basic Authentication over HTTPS.

    You can find your API Username and API Password on your Account page. You must include these credentials with every request in order to receive access to the API.

    To include the credentials in your HTTPS request, specify an Authorization header, with the value Basic (key), replacing (key) with the Base-64 encoded string API_USERNAME:API_PASSWORD.

    If your credentials are not authorized, a status code of 401 will be returned.

    You must replace API_USERNAME and API_PASSWORD with your API keys found on your API Admin Dashboard.

    So to do that, you need to use a URLRequest and not only a URL:

    //Create URLRequest
    var request = URLRequest.init(url: url!)
    
    //Create Header according to the documentation
    let userName = "API_USERNAME" //Need to be replaced with correct value
    let password = "API_PASSWORD" //Need to be replaced with correct value
    let toEncode = "\(userName):\(password)" //Form the String to be encoded
    let encoded = toEncode.data(using: .utf8)?.base64EncodedString()
    
    //Add the header value
    request.addValue("Basic \(encoded!)", forHTTPHeaderField: "Authorization")
    
    //Perform the task with the request instead of previously the URL
    URLSession.shared.dataTask(with: request){//The rest of your code}
    

    Side note, I didn't do guard let or if let, I ugly unwrapped when needed. It's to show the main logic and the CocoaTouch API rather than anything else, especially since I'm not a Swift developer.