13

I am trying to set up the login for my iOS app using Spotify's SDK. I have the login working, but only without tokens. Once I add these two lines of code:

SPTAuth.defaultInstance().tokenSwapURL = NSURL(string: kTokenSwapURL)
SPTAuth.defaultInstance().tokenRefreshURL = NSURL(string: kTokenRefreshServiceURL)

The login does not work. This is my code for the login.

AppDelegate.swift

let kClientID = "my-client-id"
let kCallbackURL = "my-callback-url"
let kTokenSwapURL = "my-token-swap-url"
let kTokenRefreshServiceURL = "my-token-refresh-url"

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.

    // Override point for customization after application launch.
    SPTAuth.defaultInstance().clientID = kClientID
    SPTAuth.defaultInstance().redirectURL = NSURL(string: kCallbackURL)
    SPTAuth.defaultInstance().requestedScopes = [SPTAuthStreamingScope, SPTAuthUserReadPrivateScope, SPTAuthPlaylistReadPrivateScope]
    SPTAuth.defaultInstance().sessionUserDefaultsKey = "SpotifySession"

    window = UIWindow(frame: UIScreen.mainScreen().bounds)

    let loginViewController = LoginViewController(nibName: "LogInViewController", bundle: nil)
    let navigationController = UINavigationController(rootViewController: loginViewController)

    window?.rootViewController = navigationController
    window?.makeKeyAndVisible()

    return true
}

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
    let authCallback : SPTAuthCallback = { error, session in
        // This is the callback that'll be triggered when auth is completed (or fails).

        if (error != nil) {
            print(error);
            return;
        }

        let userDefaults = NSUserDefaults.standardUserDefaults()
        let sessionData = NSKeyedArchiver.archivedDataWithRootObject(session)
        userDefaults.setObject(sessionData, forKey: SPTAuth.defaultInstance().sessionUserDefaultsKey)
        userDefaults.synchronize()

        AuthHandler.sharedHandler.loginWithSession(session)
    };

    if SPTAuth.defaultInstance().canHandleURL(url) {
        SPTAuth.defaultInstance().handleAuthCallbackWithTriggeredAuthURL(url, callback:authCallback)
        return true
    }

    return false;
}

LoginViewController.swift

class LoginViewController: UIViewController {

    let kClientID = "my-client-id"
    let kCallbackURL = "my-callback-url"
    let kTokenSwapURL = "my-token-swap-url"
    let kTokenRefreshServiceURL = "my-token-refresh-url"


    var session: SPTSession!

    var logIn: UIButton!

    var auth : SPTAuthViewController?

    override func viewWillAppear(animated: Bool) {
        // set login callback for what happens when session is got
        AuthHandler.sharedHandler.setLoginCallback({ success in
            if (success) {
                self.transitionToPlaylistScreen()
            }
        })

        // if session is still valid, login
        let userDefaults = NSUserDefaults.standardUserDefaults()

        if let sessionObj:AnyObject = userDefaults.objectForKey("SpotifySession") { // session available
            let sessionDataObj = sessionObj as! NSData

            let session = NSKeyedUnarchiver.unarchiveObjectWithData(sessionDataObj) as! SPTSession

            if !session.isValid() {
                SPTAuth.defaultInstance().renewSession(session, callback: { (error:NSError!, renewdSession:SPTSession!) -> Void in
                    if error == nil {
                        let sessionData = NSKeyedArchiver.archivedDataWithRootObject(session)
                        userDefaults.setObject(sessionData, forKey: SPTAuth.defaultInstance().sessionUserDefaultsKey)
                        userDefaults.synchronize()

                        self.session = renewdSession
                        AuthHandler.sharedHandler.loginWithSession(self.session!)
                    } else {
                        print(error.localizedDescription)
                    }
                })
            } else {
                self.session = session
                AuthHandler.sharedHandler.loginWithSession(self.session!)
            }
        }
    }

    override func viewDidLoad() {
        // add observer for login success
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("transitionToPlaylistScreen"), name: "loginSuccess", object: nil)

       // code to set up the login button
    }

    func transitionToPlaylistScreen() {
        if (self.auth != nil) {
            self.dismissViewControllerAnimated(true, completion: nil)
            self.auth = nil
        }
        let playlistScreen = PlaylistViewController()
        let navigation = UINavigationController(rootViewController: playlistScreen)
        dispatch_async(dispatch_get_main_queue(), {
            self.presentViewController(navigation, animated: true, completion: nil)
        })
    }

    func loginToSpotify() {
        // if session isn't valid, login within app
        dispatch_async(dispatch_get_main_queue(), {
            self.auth = SPTAuthViewController.authenticationViewController()
            self.auth?.delegate = AuthHandler.sharedHandler
            self.auth!.modalPresentationStyle = .OverCurrentContext
            self.auth!.modalTransitionStyle = .CrossDissolve
            self.modalPresentationStyle = .CurrentContext
            self.definesPresentationContext = true
            self.auth!.clearCookies({
                dispatch_async(dispatch_get_main_queue(), {
                    self.presentViewController(self.auth!, animated: false, completion: nil)
                })
            })
        })
    }
}

AuthHandler.swift

class AuthHandler: NSObject, SPTAuthViewDelegate {
    static let sharedHandler = AuthHandler()

    var session: SPTSession?

    var callback: (Bool -> Void)?

    func setLoginCallback(callback: (Bool -> Void)) {
        self.callback = callback
    }

    func authenticationViewController(authenticationViewController: SPTAuthViewController!, didFailToLogin error: NSError!) {
        if let function = callback {
            function(false)
        }
    }

    func authenticationViewController(authenticationViewController: SPTAuthViewController!, didLoginWithSession session: SPTSession!) {
        self.loginWithSession(session)
    }

    func authenticationViewControllerDidCancelLogin(authenticationViewController: SPTAuthViewController!) {
        if let function = callback {
            function(false)
        }
    }

    func loginWithSession(session: SPTSession) {
        self.session = session
        SPTAuth.defaultInstance().session = session
        if let function = callback {
            function(true)
        }
    }
}
PoKoBros
  • 701
  • 3
  • 9
  • 25

2 Answers2

2

I guess that your backend (swap/refresh) server is not set up properly, because a not working server will cause log in to fail.

I recommend this repository, which you can set up a simple server on heroku.

Jimmy Prime
  • 66
  • 1
  • 3
  • does this still work for you? i have tried to set it up so badly, but no chance – David Seek Nov 29 '16 at 00:54
  • Yes it is still working for me. I rebuilt my old obj-c project. – Jimmy Prime Dec 02 '16 at 04:50
  • crap... my code is perfect... but my heroku server with this ruby script gives: http://stackoverflow.com/questions/40813928/how-to-properly-handle-token-refresh-with-spotify-sdk-and-swift-3-error-code-38 – David Seek Dec 02 '16 at 08:23
1

What I would recomed you to try several things:

  1. Could you please post what is in yours URL Types Identifier and URL Schemes?
  2. I do not know is it important, but in my case Redirect URI and URL Schemes is the same. Redirect URI can be found here under My Applications.
  3. Try to write second app which is opening your app using URL Scheme. If it will not work then here is problem in URL schemas.

As code snapshot is here:

let kCallbackURL = "myWhosampled://"
let url = NSURL(string: kCallbackURL)
UIApplication.sharedApplication().openURL(url!)

When generating files for tokens using spotify_token_swap.rb file you would need to set correct values for this:

CLIENT_ID = "e6695c6d22214e0f832006889566df9c"
CLIENT_SECRET = "29eb02041ba646179a1189dccac112c7"
ENCRYPTION_SECRET = "cFJLyifeUJUBFWdHzVbykfDmPHtLKLGzViHW9aHGmyTLD8hGXC" 
CLIENT_CALLBACK_URL = "spotifyiossdkexample://"
AUTH_HEADER = "Basic " + Base64.strict_encode64(CLIENT_ID + ":" + CLIENT_SECRET)
SPOTIFY_ACCOUNTS_ENDPOINT = URI.parse("https://accounts.spotify.com")

set :port, 1234 # The port to bind to.
set :bind, '0.0.0.0' # IP address of the interface to listen on (all)
Emzor
  • 1,380
  • 17
  • 28
Ramis
  • 13,985
  • 7
  • 81
  • 100
  • My Redirect URI and URL Schemes are the same. When I take out the two lines I wrote above setting the token refresh URL, the login works fine and openURL is called. – PoKoBros Mar 05 '16 at 03:27
  • have you had success with logging in with Spotify and Swift?? – PoKoBros Mar 05 '16 at 03:28
  • I did use objective-c to integrate Spotify, but I do not think that here is a problem. – Ramis Mar 07 '16 at 07:25
  • As well I want to notice that during integration using tokens we had some problems in the backend. Can be that problem is not only in iOS platform, but in backend. How to test backend I do not know. – Ramis Mar 07 '16 at 07:27
  • Some values in spotify_token_swap.rb file should be change. Did you change them? – Ramis Mar 07 '16 at 07:34
  • I did change the values in the rb file. Does my code look fine?? – PoKoBros Mar 07 '16 at 11:46
  • The code it self looks ok. As I and 李昇輯 mentioned problem can be in the back end. – Ramis Mar 07 '16 at 12:16
  • Ok. For the line that sets the port to 1234 in the rb file, do I need to change that to anything if I'm using heroku? – PoKoBros Mar 07 '16 at 12:53
  • Sorry, but I do not know. Did you find out port number? And is it working? – Ramis Mar 08 '16 at 08:01
  • No I have not. I have looked through the Spotify documentation and there is nothing there to help, so I contacted the developer of the SpotifyTokenSwap Github repo to see if he could help. Once I figure out a solution I will post it here. – PoKoBros Mar 08 '16 at 12:07
  • does this still work for you? i have tried to set it up so badly, but no chance – David Seek Nov 29 '16 at 00:55
  • I did use it in the iOS WhoSampled app. I did check now and still works fine. – Ramis Nov 29 '16 at 07:25