Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Native: How to send auth token in header? #224

Closed
siddh3sh opened this issue Apr 28, 2023 · 11 comments
Closed

React Native: How to send auth token in header? #224

siddh3sh opened this issue Apr 28, 2023 · 11 comments

Comments

@siddh3sh
Copy link

For web apps we're setting the JWT in cookie and it's getting sent as header during connection request.

Is there any similar way to pass JWT in React Native applications since we do not have access to cookies here.

@FZambia
Copy link
Member

FZambia commented Apr 28, 2023

Hello @siddh3sh

Will this work for your case - https://github.com/centrifugal/centrifuge-js#custom-websocket-constructor ?

@FZambia
Copy link
Member

FZambia commented May 4, 2023

Please reopen if the approach above did not work or you see a better solution.

@FZambia FZambia closed this as completed May 4, 2023
@vinodkuumar
Copy link

vinodkuumar commented May 5, 2023

Hello @FZambia , if we use the above approach we are getting below error.
Error: ws does not work in the browser. Browser clients must use the native WebSocket object
at new module.exports (browser.js:4)
at wsClass._createSuperInternal (websocket initialization file.js))
at new wsClass (websocket initialization file.js)
at WebsocketTransport.initialize (transport_websocket.js:32)
at Centrifuge._initializeTransport (centrifuge.js:661)
at Centrifuge._startReconnecting (centrifuge.js:784)
at Centrifuge._startConnecting (centrifuge.js:1003)
at Centrifuge.connect (centrifuge.js:161).
Is there any way to pass headers other than using this websocket custom constructor ?

@FZambia
Copy link
Member

FZambia commented May 5, 2023

Error: ws does not work in the browser. Browser clients must use the native WebSocket object

The link only shows an example how to achieve this. You can pass any WebSocket client wrapper to Centrifuge - so just pass the correct one. What I do not understand though is why you are running it in the browser where passing headers is impossible at all. Sorry - probably I am missing sth.

@vinodkuumar
Copy link

hello @FZambia, My project is in React Native and my plan is to use centrifuge with websocket transport.
For this i have installed centrifuge with version 3.1.1 and ws with version 8.13.0.
Please find the code for clear understanding the issue:-
const WebSocket = require('ws');
const myWs = function (options) {
return class wsClass extends WebSocket {
constructor(...args) {
super(...[...args, ...[options]])
}
}
}

const centrifuge = new Centrifuge([{
transport: 'websocket',
endpoint: 'ws://localhost:8000/connection/websocket', //websocket url
}], {
debug: true,
token: 'token',
websocket: myWs({ headers: { Authorization: '' } }), //here i need to pass token
})
so if i use above code iam getting ws does not work in the browser error.
is this the right way to pass headers in react native project or do we have any other way ?

@FZambia
Copy link
Member

FZambia commented May 8, 2023

It seems that React Native has native WebSocket object these days. And quick googling showed that it has third parameter to include headers in non-browser environment:

let ws = new WebSocket(url, '', {headers: {'User-Agent': 'ReactNative'}});

So maybe try the following code:

const myWs = function (options) {
    return class wsClass extends WebSocket {
        constructor(...args) {
            super(...[...args, ...[options]])
        }
    }
}

let centrifuge = new Centrifuge('ws://localhost:8000/connection/websocket', {
    websocket: myWs({ headers: { Authorization: '<token or key>' } })
});

I.e. without using ws library at all.

@vinodkuumar
Copy link

I have tried 2 scenarios, still not worked for me. please go through the below details for clear understanding the issue.
case 1:-
const myWs = function (options) {
return class wsClass extends WebSocket {
constructor(...args) {
super(...[...args, ...[options]])
}
}
}

let centrifuge = new Centrifuge('ws://localhost:8000/connection/websocket', {
websocket: myWs({ headers: { 'User-Agent': 'ReactNative','token': token } })
});
and tried with this also
case 2:-
let ws = new WebSocket('ws://localhost:8000/connection/websocket', '', { headers: { 'User-Agent': 'ReactNative', 'token': token } });
let centrifuge = new Centrifuge('ws://localhost:8000/connection/websocket', {
websocket: ws
});
iam getting this error:- Possible Unhandled Promise Rejection (id: 0):
TypeError: Cannot read property 'socketUrl' of null (but iam passing the url correctly and it is not null).

@FZambia
Copy link
Member

FZambia commented May 8, 2023

Let's reopen then, I'll try to check this out soon.. No ready to use React Native environment at the moment.

@FZambia FZambia reopened this May 8, 2023
@FZambia
Copy link
Member

FZambia commented May 8, 2023

@vinodkuumar I tried to start new React Native app:

expo init MyProject

Using blank Javascript template.

cd MyProject
npm install centrifuge
expo start

The content of App.js:

import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import { Centrifuge } from 'centrifuge';

const myWs = function (options) {
  return class wsClass extends WebSocket {
    constructor(...args) {
      if (args.length === 1) {
        super(...[...args, 'centrifuge-json', ...[options]])
      } else {
        super(...[...args, ...[options]])
      }
    }
  }
}

let centrifuge = new Centrifuge('ws://192.168.1.195:8000/connection/websocket', {
  websocket: myWs({ headers: { Authorization: '<token or key>' } })
});

centrifuge.on('connected', function (ctx) {
  console.log("connected", ctx);
});

centrifuge.on('connecting', function (ctx) {
  console.log("connecting", ctx);
});

centrifuge.on('disconnected', function (ctx) {
  console.log("disconnected", ctx);
});

centrifuge.connect();

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

It works and properly connects to Centrifugo (please keep in mind that it's just an example, probably you need to bind Centrifuge lifetime to the component's lifetime - don't have experience with React Native at all).

In this case, for connection from browser I don't see any Authorization header sent to a server - which is expected. In the case of connection from Android app (using Expo Go) I see Authorization header passed to a server.

Could you please check this out? I was not able to reproduce error messages you had, I had another one though - related to subprotocol argument.

@vinodkuumar
Copy link

Hello @FZambia , it worked for me.
Thanks for your help.

@FZambia
Copy link
Member

FZambia commented May 9, 2023

Welcome! Updated readme in this commit - 72723b3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants