Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting tokens in Spotify iOS app disables login callback

Tags:

ios

swift

spotify

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)
        }
    }
}
like image 591
PoKoBros Avatar asked Feb 29 '16 03:02

PoKoBros


2 Answers

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.

like image 124
Jimmy Prime Avatar answered Nov 15 '22 10:11

Jimmy Prime


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)
like image 25
Ramis Avatar answered Nov 15 '22 09:11

Ramis