Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

iOS Build a Restaurant Reviews App Authorization With Third Party Libraries Saving to the Keychain

Radu Albastroiu
Radu Albastroiu
17,498 Points

Hi, yelp api doesn't use Oauth for authentication anymore. How should I authenticate my app ?

Since march 2018 Yelp doesn't use Oauth for authentication. They say it is easier now but i'm kind of lost. How should I authenticate now?

Have the same question

Hello Radu,

I would have to read the documents in Yelp about the new way of authorizing, and to be honest I have never worked with Yelp before or its API.

I will do some research and get back to you with an answer.

I also feel that this question Pasan Premaratne may have a concrete answer.

1 Answer

Pasan Premaratne
STAFF
Pasan Premaratne
Treehouse Teacher

Hey everyone,

I'm working on refreshing this course at the moment because of the API change. With the updates to Yelp Fusion API< you don't need to authorize yourself anymore. Once you get the API key all you have to do is sign each request with the api key by including a Authorization header.

Here's an example. Try this out and let me know if you have any follow up questions

let apiKey = "your_api_key"
var url = URL(string: "https://api.yelp.com/v3/businesses/search?term=delis&latitude=37.786882&longitude=-122.399972")!
var request = URLRequest(url: url)
request.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")

So if I understand correctly, I can delete the whole authorization code and the UI button. Add my apiKey to the request URL and everything will work fine right?

Pasan Premaratne
Pasan Premaratne
Treehouse Teacher

Yep! You will still have to register an app and all that with Yelp but you can get rid of all of the rest

Sean Alves
Sean Alves
841 Points

So do I delete everything from this video and add the above code to the project? I'm having trouble figuring out where it goes.

Pasan Premaratne
Pasan Premaratne
Treehouse Teacher

Hey Sean,

You essentially have to do this for every single request you send to the API. You can either do it like the example above and add the API key to the Authorization header of every single request as shown above; the key part there is this line

request.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")

What I would do though is to modify the Endpoint type and the client. Here's a brief example:

import Foundation

protocol Endpoint {
    var base: String { get }
    var path: String { get }
    var queryItems: [URLQueryItem] { get }
}

extension Endpoint {
    var urlComponents: URLComponents {
        var components = URLComponents(string: base)!
        components.path = path
        components.queryItems = queryItems
        return components
    }

    // Note here that instead of a computed property that returns a request, we're
    // defining a function in the protocol extension that takes the apiKey and adds it to the
    // header
    func request(withApiKey key: String) -> URLRequest {
        let url = urlComponents.url!
        var request = URLRequest(url: url)
        request.addValue("Bearer \(key)", forHTTPHeaderField: "Authorization")

        return request
    }
}


enum Yelp {
    case business(id: String)
}

extension Yelp: Endpoint {
    var base: String {
        return "https://api.yelp.com"
    }

    var path: String {
        switch self {
        case .business(let id): return "/v3/businesses/\(id)"
        }
    }

    var queryItems: [URLQueryItem] {
        switch self {
        case .business: return []
        }
    }
}

class YelpAPIClient {
    var apiKey: String {
        // ideally fetched from keychain or somewhere secure
        return "sample_key"
    }

    let session: URLSession

    init(session: URLSession) {
        self.session = session
    }

    func searchBusinesses() {
        let endpoint = Yelp.business(id: "abcdefg")
        // Inside the client, when we retrieve the request object from the endpoint, we're
        // passing in the apiKey
        let request = endpoint.request(withApiKey: apiKey)

        // Do the usual stuff!
    }
}
Sean Alves
Sean Alves
841 Points

Thanks! So would I be able to copy the below example? If so, would that go into the Permissions.Swift or the YelpAccount

Sean Alves
Sean Alves
841 Points

Sorry to bother, was there any updates on this section? Let me know when you get a chance

Pasan Premaratne
Pasan Premaratne
Treehouse Teacher

Hey Sean,

It doesn't really matter where you put it. All the code is eventually compiled down to one source ultimately. For organization purposes I would put the endpoint bits in Endpoint.swift and the remaining inside either the client file or the Yelp API file

Deysha Rivera
Deysha Rivera
5,088 Points

Pasan Premaratne Any idea when the update to this course will be released?

Pasan Premaratne
Pasan Premaratne
Treehouse Teacher

Deysha Rivera,

I don't work at Treehouse anymore and can't provide any info on updates I'm afraid :/

cc Dave McFarland