Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Socket.connect() is not consistent when using connectParams with JWT

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?

like image 832
sinusGob Avatar asked Aug 29 '17 09:08

sinusGob


1 Answers

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.

like image 54
Farhad Avatar answered Oct 22 '22 00:10

Farhad