I’m trying to follow Last.fm’s tutorial to consume their API in an iOS app (using Swift), but I don’t know what’s wrong with my code. They ask to do something called Last.fm method signature which I’m not understanding how to insert into my program. Here is the link to the tutorial I try to follow: https://www.last.fm/api/mobileauth
Here is my current code:
import UIKit
struct LoginRequestBody: Codable {
var username: String
var password: String
var api_key: String
var api_sig: String
}
enum AuthenticationError: Error {
case invalidCredentials
case custom(errorMessage: String)
}
class APIService {
func requestAPI(username: String, password: String, api_key: String, api_sig: String) {
guard let url = URL(string: "http://www.last.fm/api/auth/?api_key=xxx") else {
return
}
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
let body = LoginRequestBody(username: username, password: password, api_key: api_key, api_sig: api_sig)
let bodyStr = [
"username": "(body.username)",
"password": "(body.password)",
"api_key": "(body.api_key)",
"api_sig": "(body.api_sig)"]
urlRequest.httpBody = try? JSONSerialization.data(withJSONObject: bodyStr, options: .fragmentsAllowed)
let task = URLSession.shared.dataTask(with: urlRequest) { data, _, error in
guard let data = data, error == nil else {
return
}
do {
let response = try JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed)
print(response)
} catch {
print(error)
}
}
task.resume()
}
}
2
Answers
You are seeing the error you mentioned in your comments because you try to connect to an endpoint using
http
instead ofhttps
and Apples App Transport Security mechanism blocks you from doing that.You have two options (maybe more :))
https
instead and if they to, then use thathttp
instead. You do so by adding this to yourinfo.plist
Before you do so though, please see also this great answer describing all the risks you take if you use
http
overhttps
You should definitely use the secure
https://ws.audioscrobbler.com/2.0/auth.getMobileSession
endpoint like it is mentioned in the documentation. That is also important because you send sensitive data over the wire like the user’s password.Next you should generate the body of your POST request.
If you struggle to generate the signature, here’s how:
api_key -> your_key
method -> auth.getMobileSession
password -> somebodys_password
username -> somebody
key1value1key2...keyNvalueN
, e.g.api_keyyour_keymethodauth.getMobileSessionpassword...usernamesomebody
apisecret
) to that string (and only that valueapisecret
)api_keyyour_keymethodauth.getMobileSessionpassword...usernamesomebodyapisecret
api_sig
in your requestThis is also the way to generate the signature for other API calls.
Note: when you use the
getMobileSession
approach you won’t redirect the user to a last.fm page where they could allow your app to access their profile. Instead you are sending directly the user’s credentials to last.fm to authenticate.Note: for me the body of such a HTTP POST request was assembled like
key1=value1&key2=value2&...
maybe Swift is doing this internally already.