When to refresh token in socket.io? - javascript

Where should i call a refresh token request in websocket app (i'm using socket.io)?
Is there a way to re-emit particular socket.io event if server sent 'not authorized' error in response to the first attempt? Something like axios.interceptors for websockets?
Thank you!

Related

Node.js — Google OAuth 2.0 for Web Server Applications -> How to use the token event

I'm trying to figure out how to use the token event as specified in Google's OAuth 2.0 documentation for server side applications (using Node.js):
Here's the code for the token event:
oauth2Client.on('tokens', (tokens) => {
if (tokens.refresh_token) {
// store the refresh_token in your secure persistent database
console.log(tokens.refresh_token);
}
console.log(tokens.access_token);
});
I actually get this event to fire, but am unsure about when to check for a valid token. If I do this one every request (let's say Google Docs API request), the token event fires after I'm requesting the API, so credentials are not set correctly.
How would you go about making sure that the correct access token is set BEFORE making a request?
Google says "Once the client has a refresh token, access tokens will be acquired and refreshed automatically in the next call to the API.", which is also kind of the case, but too late.
So my question once again: How do I, in my call, wait for the token event to finish updating my access token in order to set credentials BEFORE making the request?
Thank you!

Get response headers from websocket handshake

I'm trying to get a client to read the error message given when a connection to a WebSocket is failed.
The client attempts to connect to the socket with
this.socket = new WebSocket(url);
and the server handles this by listening for
server.on('upgrade', function upgrade(request, socket, head) {...})
If the client doesn't have the proper authentication, the server sends socket.write with a 401 error and a custom header containing a message saying why the connection failed, and then doing a socket.destroy(). After this, the client's this.socket is set to null as it isn't opened.
My question is, how can I get the client to read that custom error message so that I can display it to the user? If this isn't possible, what would be the best approach to communicate this error?

Is it correct to send a 401 error before the user tries to login?

In a REST Api i'm developing, someone told me to directly send a request to the "get current user (/me)" url without checking if there is a session token and simply redirect him to the login page when receiving a 401 response.
Is this correct? I thought that the browser should not receive a 4xx response unless the user does something he is not supposed to.
I thought that the browser should not receive a 4xx response unless the user does something he is not supposed to.
That's more restrictive than described by the standard, see RFC 7231
The 4xx (Client Error) class of status code indicates that the client seems to have erred.
The server can't distinguish errors by the user from errors by the user agent - there's just a single HTTP request, that has to be judged of itself.
Another way of expressing the same idea: REST's uniform interface constraint implies that clients with human users should be getting the same self descriptive responses as clients without human users.
We do exactly this. We basically send a HTTP request, and if it comes back as a 401, we know we need to log the user in.
We also send a Link header to tell the client where the user should go for log in:
HTTP/1.1 401 Unauthorized
Link: </login>; rel="authenticate"

res.send token and then redirect

I have an express app that upon calling a get request immediately returns a string token, then runs a python code. The python code after some time creates a json file that I need to send in another post request.
This python code may be called by different users that's why i need to assign them a token a soon as the app is called.
In the post request i'll also be modifying the json file and then sending it back
I'm trying to do res.send the token and then res.redirect to the post request, but i know it's impossible. Is there any other way i could send the token or redirect to the post request?
app.get('/', (req, res) =>{
res.send(token())
runPython((code)=>{
*takes around 10 sec*
res.redirect('/post')}}
app.post('/post', (req, res)=>{
*do stuff to file*
res.sendFile()
You cannot send multiple responses back to the client separated in time. You get ONE http response. So, once you've done res.send(token()), then that http request is done. You can't send any more data as part of that http request.
As you describe things, here are some of your options:
Combine both into one response. Wait to send the token until you have the python response too and then send them both in one JSON response. You won't be able to do a res.redirect() if you're also sending data back. So, you could send the redirect location back in the JSON and have the client manually do the redirect (by just setting window.location to a new URL). Presumably, there is client-side Javascript on the receiving end of this anyway since some form of code has to receive the token anyway to do something useful with it.
Use websocket/socket.io connection for subsequent server-initiated communication. Have the client connect a webSocket or socket.io connection. You can then response with the token and then later when the python has finished, you can send additional data over the websocket or socket.io connection. This will require additional code to be able to associate a particular websocket/socket.io connection with the client that made this request so you can tell which websocket/socket.io connection for this request to send a notification over.
Client-side polling for completion of python operation. Have the server send back the token and also send it some sort of request ID and then the client can poll the server every few seconds to ask the server if that python operation for that request ID is now done. When it gets a response from the server that the python is now done, then the client can manually redirect itself to /post to fetch the final data.

Node.js/Express - how to access session data through method(using sockets)?

I've stored some Oauth data in session, and now I'd like to access it again, so I created a local API endpoint to feed that access token. It appears that if I make that request via a method though, it doesn't contain the request body, so it can't actually get the req.session.access_token.
Visiting this endpoint provides the right data if typed into the address bar, but the response is undefined when requested through a method. The method is being called through a socket, if that helps inform the advice.
//This is the endpoint
app.get('/instagram/accesstoken', function(req,res){
console.log("/instagram/accesstoken: ", req.session.access_token, ", req: ", req);
res.json({access_token: req.session.access_token});
});
//This is the method calling the endpoint
function getAccessToken(callback){
request({url: 'http://localhost:3000/instagram/accesstoken', method: "GET"}, function(err, resp, data){
console.log("getAccessToken: ", data);
if(err) { return callback(err); }
callback(null, data);
});
//Sockets
io.listen(server);
io.on('connection', function(socket){
...
getAccessToken(function(err, token){...}
...
});
I'm open to alternative solutions as well. How can I feasibly get access to the session data? Thanks for your patience, and for taking a look.
Used express and socket.io for just a few days but here's a bit thought:
1. You're having problem getting req.session, which is picked up by the server from its session storage. The server does this with the help of sessionid(usually named sessionid or sid) stored in the browser cookie, which is sent in the headers of every request. So you should probably check the request headers(on the requests made after the socket connection) to see if the cookie is correctly sent and whether it is including the sessionid we want.
2. You're telling the client to request the accesstoken on your site when the socket connects so the server can get the Oauth access_token to request or send infomation to other apps(if I understand correctly). This is a bit of an overhead(one too many request) since you may just get the session id from socket request's header and then get this user's session data with it. However this may need a little tweak since the framework's session functionality can't check the session id from the req object automatically. This can be a bit difficult if the session functionality doesn't provide relevant functions so you'll have to dive in the framework. But it's an alternate if plan 1 doesn't work out(and is also more elegant since it saves one request :) (but may be harder as well :( ))
To access session data via sockets you need to use a plugin like https://www.npmjs.com/package/express-socket.io-session
With this you can access session data via socket calls.

Categories

Resources