Last updated on: May 27, 2023
Today, I’m going to show you how to add the Spotify Login Button to your iOS easily using a ViewController with a WebView and making an HTTP request.
You don’t need any 3rd party library from Spotify to implement this.
Contents
Lets get started!
First, go to developer.spotify.com/dashboard and login with your Spotify account. (You don’t need Spotify Premium to have access to Spotify for Developers.)
Next, create a new app by pressing the box.
In the new window, fill in all the requirement fields, like app name, description e.t.c., and press NEXT.
… next step, choose if it’s a commercial app or not. In this example, the answer is NO.
Check the boxes and press SUBMIT.
Once you get to the dashboard of your app, go to EDIT SETTINGS.
In the new window, add your website (if you have one), as Redirect URIs add the name of your app and at the end add :// , for this example is spotifysigninexample://, and lastly, in Bundle IDs add your Bundle Bundle Identifier and press SAVE
Creating the Spofity Login Button
First, create an UIButton in your ViewController and make an Outlet and an Action connection to your swift file. In this example, we called it spotifyLoginBtn and spotifyLoginBtnAction.
Create a new swift file to put the Constants.
Paste the following code inside.
struct SpotifyConstants {
static let CLIENT_ID = "MY_CLIENT_ID"
static let SESSION_KEY = "spotifySessionKey"
static let REDIRECT_URI = "MY_REDIRECT_URI"
static let SCOPE = "user-read-email"
}
Code language: Swift (swift)
Replace the Client ID and Redirect URI with yours.
Here, we use the scope user-read-email to get the user’s email address. You can see more about other scopes, here.
Next, create a ViewController with a WebView.
Here, the user puts the email and password and gives access to the app.
@IBAction func spotifyLoginBtnAction(_ sender: UIButton) {
spotifyAuthVC()
}
var webView = WKWebView()
func spotifyAuthVC() {
// Create Spotify Auth ViewController
let spotifyVC = UIViewController()
// Create WebView
let webView = WKWebView()
webView.navigationDelegate = self
spotifyVC.view.addSubview(webView)
webView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
webView.topAnchor.constraint(equalTo: spotifyVC.view.topAnchor),
webView.leadingAnchor.constraint(equalTo: spotifyVC.view.leadingAnchor),
webView.bottomAnchor.constraint(equalTo: spotifyVC.view.bottomAnchor),
webView.trailingAnchor.constraint(equalTo: spotifyVC.view.trailingAnchor)
])
let authURLFull = "https://accounts.spotify.com/authorize?response_type=token&client_id=" + SpotifyConstants.CLIENT_ID + "&scope=" + SpotifyConstants.SCOPE + "&redirect_uri=" + SpotifyConstants.REDIRECT_URI + "&show_dialog=false"
let urlRequest = URLRequest.init(url: URL.init(string: authURLFull)!)
webView.load(urlRequest)
// Create Navigation Controller
let navController = UINavigationController(rootViewController: spotifyVC)
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(self.cancelAction))
spotifyVC.navigationItem.leftBarButtonItem = cancelButton
let refreshButton = UIBarButtonItem(barButtonSystemItem: .refresh, target: self, action: #selector(self.refreshAction))
spotifyVC.navigationItem.rightBarButtonItem = refreshButton
let textAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
navController.navigationBar.titleTextAttributes = textAttributes
spotifyVC.navigationItem.title = "spotify.com"
navController.navigationBar.isTranslucent = false
navController.navigationBar.tintColor = UIColor.white
navController.navigationBar.barTintColor = UIColor.black
navController.modalPresentationStyle = UIModalPresentationStyle.overFullScreen
navController.modalTransitionStyle = .coverVertical
self.present(navController, animated: true, completion: nil)
}
@objc func cancelAction() {
self.dismiss(animated: true, completion: nil)
}
@objc func refreshAction() {
self.webView.reload()
}
Code language: Swift (swift)
After giving access, the webView gets the URL request, using the method decidePolicyFor from the WKNavigationDelegate.
Then, from the URL request, get the access token using the .range method.
extension LoginViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
RequestForCallbackURL(request: navigationAction.request)
decisionHandler(.allow)
}
func RequestForCallbackURL(request: URLRequest) {
// Get the access token string after the '#access_token=' and before '&token_type='
let requestURLString = (request.url?.absoluteString)! as String
if requestURLString.hasPrefix(SpotifyConstants.REDIRECT_URI) {
if requestURLString.contains("#access_token=") {
if let range = requestURLString.range(of: "=") {
let spotifAcTok = requestURLString[range.upperBound...]
if let range = spotifAcTok.range(of: "&token_type=") {
let spotifAcTokFinal = spotifAcTok[..<range.lowerBound]
handleAuth(spotifyAccessToken: String(spotifAcTokFinal))
}
}
}
}
}
}
Code language: Swift (swift)
Finally, close the ViewController with the WebView and use the access token to get the user’s ID, username, email and profile pic URL using HTTP request.
func handleAuth(spotifyAccessToken: String) {
fetchSpotifyProfile(accessToken: spotifyAccessToken)
// Close Spotify Auth ViewController after getting Access Token
self.dismiss(animated: true, completion: nil)
}
func fetchSpotifyProfile(accessToken: String) {
let tokenURLFull = "https://api.spotify.com/v1/me"
let verify: NSURL = NSURL(string: tokenURLFull)!
let request: NSMutableURLRequest = NSMutableURLRequest(url: verify as URL)
request.addValue("Bearer " + accessToken, forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
if error == nil {
let result = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [AnyHashable: Any]
//AccessToken
print("Spotify Access Token: \(accessToken)")
//Spotify Handle
let spotifyId: String! = (result?["id"] as! String)
print("Spotify Id: \(spotifyId ?? "")")
//Spotify Display Name
let spotifyDisplayName: String! = (result?["display_name"] as! String)
print("Spotify Display Name: \(spotifyDisplayName ?? "")")
//Spotify Email
let spotifyEmail: String! = (result?["email"] as! String)
print("Spotify Email: \(spotifyEmail ?? "")")
//Spotify Profile Avatar URL
let spotifyAvatarURL: String!
let spotifyProfilePicArray = result?["images"] as? [AnyObject]
if (spotifyProfilePicArray?.count)! > 0 {
spotifyAvatarURL = spotifyProfilePicArray![0]["url"] as? String
} else {
spotifyAvatarURL = "Not exists"
}
print("Spotify Profile Avatar URL: \(spotifyAvatarURL ?? "")")
}
}
task.resume()
}
Code language: Swift (swift)
That’s it! Done!
You can find the final project here
If you have any questions feel free to DM me on Twitter @johncodeos or leave a comment below!