17

I'm using https://github.com/auth0/socketio-jwt to connect the user to my node.js/socket.io server and I'm using one round trip

My problem right now is that whenever user logs in on the IOS part, the socket.connect() is not consistent, my theory is that the token is not yet ready even before the socket.connect() gets invoked.

I'm using Singleton design for my Socket.io class as many people pointed that out.

Here's the code on the SocketManager.swift part

import SocketIO

class SocketIOManager: NSObject {

    static let sharedInstance = SocketIOManager()
    var socket = SocketIOClient(socketURL: URL(string: mainURL)!, config: [.log(false), .compress, .connectParams(["token": getToken()])]) // getToken() I got it from other file which is Constant.Swift

    func establishConnection() {
        socket.connect()
    }

    func closeConnection() {
        socket.disconnect()
    }       
}

I'm using KeychainAccess to store the token and Constant.Swift file store all the global variables and functions so that I could call it on any Swift files.

Constant.Swift

import Foundation
import KeychainAccess

let keychain = Keychain(server: "www.example.com", protocolType: .https)

func getToken() -> String {
    if let token = keychain["token"] {
        return token
    }
    return ""
}

LoginViewController.swift

@IBAction func facebookButtonClicked(_ sender: UIButton) {
       Alamofire.request("/login", method: .post, parameters: parameters, encoding: JSONEncoding.default)
            .responseJSON { response in
                if let value = response.result.value {
                    let json = JSON(value)

                    self.keychain["token"] = String(describing: json["token"])
                    SocketIOManager.sharedInstance.establishConnection() 
                    self.segueToAnotherVC() // Segue to another screen, to simplify things i put it in a function
                }
        }
}

So technically what is happening in this controller is, when the user logs in, I will store the token into KeychainAccess (it is equivalent to NSUserDefaults), then only I will make a socket connection because the socket connection needs a token beforehand.

What should I do to make the connection consistent all the time, whenever user logs in? Any methods that I could use?

Farhad
  • 4,119
  • 8
  • 43
  • 66
sinusGob
  • 4,053
  • 12
  • 46
  • 82
  • Does it work fine if you use NSUserDefaults instead of Keychain access? Have you tried it already? Also, I would suggest you to check if getToken method is returning the correct token. – Mohnish Hirudkar Sep 01 '17 at 11:37
  • Additionally, I think you should use keychain like this: `https://stackoverflow.com/questions/24324285/adding-items-to-and-querying-the-ios-keychain-with-swift` Rest of the code looks fine to me, But for KeyChain I'm not sure if you are using it right way – Mohnish Hirudkar Sep 01 '17 at 11:43
  • @MohnishHirudkar it does return the correct token I already check it, because when I establish the connection in `app.delegate` it works, I believe the creation of the token time is the problem here. – sinusGob Sep 01 '17 at 13:23
  • @sinusGob have you tried switching `.log(false)` to `.log(true)` to see if any additional debug information is printed? To me, this could also *possibly* be due to the `Alamofire` async callback being in a non-main thread, and `SocketIO` I *think* needs to be on the main thread. LMK if either of those things help :) – BHendricks Sep 06 '17 at 07:01
  • Are you opening up this socket connection on the same `URL` that alamofire is connecting to? – NSGangster Sep 22 '17 at 19:03

1 Answers1

1

I suggest you to use keychain like this:

let keychain = KeychainSwift()
keychain.set("string", forKey: "key")
keychain.get("key")
keychain.delete("key")

keychain Usage:

let saveBool: Bool = KeychainWrapper.setString("String", forKey: "key")  
let retrievedString: String? = KeychainWrapper.stringForKey("key")
let removeBool: Bool = KeychainWrapper.removeObjectForKey("key")

And make sure that your token is set when calling establish connection, if not, don't try and connect.

References:

https://github.com/socketio/socket.io-client-swift/issues/788

https://github.com/marketplacer/keychain-swift

https://github.com/jrendel/SwiftKeychainWrapper

More info:

JSON Web Token is a JSON-based open standard for creating access tokens that assert some number of claims.

Farhad
  • 4,119
  • 8
  • 43
  • 66