ConnectyCube / connectycube-reactnative-samples

Chat and Video Chat code samples for React Native, ConnectyCube
https://connectycube.com
Apache License 2.0
125 stars 111 forks source link

Initialize ConnectyCube with existing token #80

Closed whenmoon closed 4 years ago

whenmoon commented 4 years ago

I am looking for a way to implement initialising ConnectyCube with an existing token so I do not have to expose ConnectyCube API keys in the front end. A solution I would like to try is passing a token down from Firebase servers using Firebase Cloud Functions and initialising the SDK with the token.

The problem is is that in my workflow, the session token is aways created after initialising the SDK and an exception is thrown if you try and obtain a session token before initialisation:

TypeError: Cannot read property 'createSession' of undefined

If it is to be initialised with an existing ConnectyCube session token, where does this token come from?

I am authenticating users using Firebase phone number auth.

How can I achieve this and do you have any other recommended ways of obscuring your API keys ?

Many thanks.

DaveLomber commented 4 years ago

If it is to be initialised with an existing ConnectyCube session token, where does this token come from?

Correct. The idea behind this is the following: 1) a developer calls some external API to authenticate. This API creates a ConnectyCube session token inside and passes it in a response 2) Then this token is used in

const CREDENTIALS = {
  appId: 21,
  token: "5a7bc95d85c0eb2bf052be3d29d3df523081e80y"
};

ConnectyCube.init(CREDENTIALS);

So there is no need to init ConnectyCube SDK before a token obtained.

I'm not fully got your flow, but the above explanation should help to better understand it.

Feel free to post more details about your flow like 1 2 3, happy to help

whenmoon commented 4 years ago

Hi @DaveLomber, thanks for the quick response. So here's my current / normal auth flow:

 ConnectyCube.init(...config);
  const user = await loggedInToFirebase(); // returns firebase user object
  if (user) {
    const accessToken = await user.getIdToken(); // returns firebase auth token
    const userCredentials = {
      provider: 'firebase_phone',
      "firebase_phone": {
        "project_id": "xyz",
        "access_token": accessToken
      }
    };
    try {
      const connectyCubeSession = await createConnectyCubeSession();
      const connectyCubeUserProfile = await logInToConnectycube(userCredentials);

      await connectToChat(connectyCubeSession, connectyCubeUserProfile)
      dispatch(userData({ connectyCubeUserProfile }));

...
export const loggedInToFirebase = () =>
  new Promise((resolve, reject) => {
    firebase.auth().onAuthStateChanged(user => {
      user ? resolve(user) : resolve(undefined)
    })
  })
...
export const createConnectyCubeSession = () => {
  return ConnectyCube.createSession()
    .then(session => session)
    .catch(error => logger.error(error, 'platform authorization'));
}

export const logInToConnectycube = userCredentials => {
  return ConnectyCube.login(userCredentials)
    .then(user => user)
    .catch(error => logger.error(error, 'platform authorization'));
}
...

So I can easily move parts of this inside AWS Lambda / Firebase Cloud Functions. With respect to this:

a developer calls some external API to authenticate. This API creates a ConnectyCube session token inside and passes it in a response

How can an external API / server create a session token without calling ConnectyCube.init() if it can't be done on the front end?

Are there any examples of code that can be used on a server to create a session token that I can pass to the app?

Appreciate the help.

DaveLomber commented 4 years ago

How can an external API / server create a session token without calling ConnectyCube.init() if it can't be done on the front end?

Here I meant either REST API https://developers.connectycube.com/server/auth?id=create-session , e.g. there are Python and PHP examples re how to create a session:

Or you also can use ConnectyCube Node.js SDK at the backend if your backend is written in Node.js (in fact, ConnectyCube Node.js is the same ConnectyCube JS SDK)

In both cases, the ConnectyCube credentials are hidden at backend side

whenmoon commented 4 years ago

Ok thanks @DaveLomber understood - I'm trying to use ConnectyCube JS SDK v3.0.6 in a Node v8 server environment and running in to problems:

SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at HTTPProxy.processAjaxError (/srv/node_modules/connectycube/lib/cubeProxy.js:213:54)
    at fetchImpl.then.then.catch.error (/srv/node_modules/connectycube/lib/cubeProxy.js:196:16)
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:229:7) 

Is that SDK compatible with Node v8?

Update

I've tried downgrading to ConnectyCube JS SDK v1.8.1 on the server and am getting a new error which is:

TypeError: Cannot read property 'user_id' of undefined
    at /srv/node_modules/connectycube/src/cubeAuth.js:59:47
    at _requestCallback (/srv/node_modules/connectycube/src/cubeProxy.js:246:6)
    at /srv/node_modules/connectycube/src/cubeProxy.js:141:6
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:229:7) 

I've tested this with a code sandbox and it works absolutely fine with valid API keys:

https://codesandbox.io/s/vigorous-hermann-cgi0v?file=/src/index.js

whenmoon commented 4 years ago

Actually this was my fault - I was on a free Firebase plan and outward network connections from Firebase cloud functions do not work unless you upgrade to a paid plan.

Thanks for your help.

DaveLomber commented 4 years ago

@whenmoon great it finally works!

whenmoon commented 4 years ago

Yeah this is awesome, thanks for your help! I'll close the issue.

SuyambuLakshmanan commented 3 years ago

DEFINE('APPLICATION_ID', 416); DEFINE('AUTH_KEY', "OxWCrCBOsXR"); DEFINE('AUTH_SECRET', "7YtCAf-HTPr"); DEFINE('CB_API_ENDPOINT', "https://api.connectycube.com"); DEFINE('CB_PATH_SESSION', "session.json"); DEFINE('CB_PATH_SIGNUP', "users.json"); DEFINE('CB_PATH_LOGIN', "login.json"); DEFINE('USER_EMAIL', "Aishu@gmail.com"); DEFINE('USER_LOGIN', "bobson12"); DEFINE('USER_PASSWORD', "qweqwesd"); $nonce = rand(); $timestamp = time(); $signature_string = "application_id=".APPLICATION_ID."&auth_key=".AUTH_KEY."&nonce=".$nonce."&timestamp=".$timestamp; // $signature_string = "application_id=".APPLICATION_ID."&auth_key=".AUTH_KEY."&nonce=".$nonce."&timestamp=".$timestamp."&user[login]=".USER_LOGIN."&user[password]=".USER_PASSWORD; $signature = hash_hmac('sha1', $signature_string , AUTH_SECRET); $post_body = http_build_query(array( 'application_id' => APPLICATION_ID, 'auth_key' => AUTH_KEY, 'timestamp' => $timestamp, 'nonce' => $nonce, 'signature' => $signature, )); $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, CB_API_ENDPOINT . '/' . CB_PATH_SESSION); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $post_body); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $responce = curl_exec($curl); if ($responce) { $data = $responce; $phpObj = json_decode($data); $token = $phpObj->session->token; $post_body1 = http_build_query(array( 'login' => USER_LOGIN, 'password' => USER_PASSWORD, 'keys[token]' => $token, ));

            //echo  $token; exit;              
            $curl1 = curl_init();
            $headers = array();
            $headers[] = 'Content-Type: application/json';
            // $headers[] = 'CB-Token: <'.$token.'>';
            curl_setopt($curl1, CURLOPT_URL, CB_API_ENDPOINT . '/' . CB_PATH_SIGNUP); 
            curl_setopt($curl1, CURLOPT_POST, true); 
            curl_setopt($curl1, CURLOPT_POSTFIELDS, $post_body1); 
            curl_setopt($curl1, CURLOPT_RETURNTRANSFER, true); 
            curl_setopt($ch, CURLOPT_HTTPHEADER,$headers); 
            $responce1 = curl_exec($curl1);

                if ($responce1) { echo   $responce1; } else { $error1 = curl_error($curl1). '(' .curl_errno($curl1). ')'; echo $error1; }
    } else { $error = curl_error($curl). '(' .curl_errno($curl). ')'; echo $error; }
    curl_close($curl);
    curl_close($curl1);

Result: Trying to create new user via api. I get token "04ebc206eb8f78212eee3eeece72e58260001046". But getting "{"errors":["Token is required"]}" when trying to create new user.

How can I create new user using php api. Please help

DaveLomber commented 3 years ago

@SuyambuLakshmanan replied here https://github.com/ConnectyCube/connectycube-reactnative-samples/issues/205#issuecomment-772367686