I currently have a web application that uses React frontend + Express sessions backend for authentication and authorization. I'm wondering if I can use the same or similar workflow for authenticating mobile users. This is how I authenticate users in my web application:
req.session.user = { id: user.rows[0].id }; // Set session cookie with user's ID
res.status(200).json({status: "success", message: "Login successful"});
It's very simple. If the passed login credentials are correct - I create a session with the user's ID that comes from the database and return a success to the front end.
Can I do something similar when using React Native as front end? I'm new to mobile development, but does the mobile client even have a cookie storage similar to a web browser? Very thankful for any input :)
Yes you can use cookies for authentication, I recommend to use fetch function to do http request. You need to pass access-control-allow-credentials header to share the cookies between server and client.
Example:
var params = {
method: "POST",
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'access-control-allow-credentials': 'true'
}
}
params.body = JSON.stringify(body)
const response = await fetch(url, params)
const json = await response.json()
Call the exact same function from react native as it is from react and persist data using this library react-native-async-storage.
Related
My React Native app needs to use sessions for when users are signed in, but I'm not sure how to implement it. At first I thought I'd need AsyncStorage to store the session ID and attach it to each request to the server, but now I'm wondering if any additional code is required on the client side.
For example, I believe express-session sets a cookie automatically in the browser which means you just have to send the cookie. Is this the same for React Native/mobile applications? In other words, if I send a response that contains a cookie will that cookie automatically be attached to each future request, or do I need to store it somehow?
Have you tried axios ?, it automatically set the cookie it receive to client when you specify the option withCredentials: true.
example:
axios({
method: 'post',
url: '/api/auth/login',
data: {
username: username,
hashpass: hash(password)
},
withCredentials: true
}).then(res => console.log('login success'))
.catch(res => {
console.log('error')
})
I am trying to add a Sign in with Twitter option on my Chrome extension with this code:
// Send request to our backend, which calls
// https://api.twitter.com/oauth/request_token to get the OAuth token
const response = await postData({
url: '/auth/twitter/reverse',
headers: { 'Content-Type': 'application/json' }
});
const authUrl = new URL('https://api.twitter.com/oauth/authenticate');
authUrl.searchParams.set('oauth_token', response.data.oauth_token);
authUrl.searchParams.set('force_login', 'false');
chrome.identity.launchWebAuthFlow({ url: authUrl.href, interactive: true }, (responseUrl) => {
// responseUrl is undefined
});
The OAuth dialog appears, and I can sign into Twitter successfully. When the window closes, it shows this error message in the console: Unchecked runtime.lastError: Authorization page could not be loaded.
My OAuth flow works fine on a website. I realize the Chrome Identity API is made for OAuth 2, so I'm not sure if there's a way to make Twitter OAuth 1.0a work with it.
How can I further debug and fix this issue?
I fixed it! I was using a different callback URL than the https://<app_id>.chromiumapp.org/ one.
Here's the updated code for making a request to my backend:
// Send request to our backend, which calls
// https://api.twitter.com/oauth/request_token to get the OAuth token
const response = await postData({
url: '/auth/twitter/reverse',
data: {
callbackUrl: chrome.identity.getRedirectURL()
},
headers: { 'Content-Type': 'application/json' }
});
...
My backend had the callback URL hardcoded, so I made it use the one passed in the request body.
Next, on the Twitter Developer Portal, I added my https://<app_id>.chromiumapp.org/ URL to the Callback URI / Redirect URL section.
Remember, of course, to replace app_id with the name of your Chrome Extension app ID.
I Have My Backend (nodejs) running on another Port And My Frontend (React) Running On Another Port...So After After Sending Credentials To Backend And Authentication...How Can I Redirect To Front End ?
res.writeHead(302, {
Location: 'http://front-end.com:8888/some/path'
});
res.end();
If you specify the full url you can redirect to another port using NodeJS.
You may use a web API (Express JS) in nodejs to build web api and frontend any plainJS or modren libaries that will send HTTP request to backend. It will help more.
In your case, you'd better auth request through Ajax, that way you can return some kind of jwt token if you're using it, or trigger any other session related action on frontend on successful login.
From the frontend, on click of login button, you can create a function called login() something like below and redirect based on the response received from the backend
App.tsx
login() {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: 'test', password: 'password' })
};
fetch('http://localhost:5000', requestOptions)
.then(response => response.json())
.then(data => history.push('/someRoute'))
.catch(err => history.push('/login'));
}
in my case, I was handling the verifyEmail on the backend of a nest.js server.
How I was able to redirect to the frontend after handling the request, was to use the res.redirect from express.
#Get('verify/:token')
async verifyUser(#Param('token') token, #Res() response: Response): Promise<any> {
const redirectUrl = await this.authService.verifyUserEmail(token);
response.redirect(redirectUrl);
return {redirectUrl};
}
And, it worked like a charm.
I am working on a nodejs express application. I used Passport's JSON web token for authentication. I have successfully created a JSON web token and it's working fine in Postman and also verifies when token passes into authorization. But I stuck on front-end side.
app.get('/profile',passport.authenticate('jwt',{session:false}),function(req,res){
// res.json({user:user.req});
// console.log(req.query.token);
res.json('bingo u cant see this without token')
});
How do I send the token in the headers like I did in Postman to this (/profile) route, i.e how to implement token on front end side so that it first checks token?
It depends on the kind what you are using to make your request at the frontend
if you are using ajax, do something like this
$.ajax({
type: 'POST',
url: url,
headers: {
"authToken":"your token" //you could save it in localstorage when recieved
}
//OR
//beforeSend: function(xhr) {
// xhr.setRequestHeader("My-First-Header", "first value");
// xhr.setRequestHeader("My-Second-Header", "second value");
//}
})
and if it's axios try doing it like this
post(url, {
headers: { authToken: token }
})
In my NodeJS Express app (built with feathers); I'm trying to work with cookies with client-side fetch from client javascript. I have Express using the cooke-parser middleware.
I have tried setting the credentials header to same-origin, but that has stopped working (it worked fine yesterday, and a few times today... but I've been trying to build up the cookie to what I need and it just doesn't seem to reliably work).
This is my test express route:
app.post('/setjwt', (req, res, next) => {
res.cookie('acokie', 'lol');
res.status(200);
res.send();
});
I'm using fetch in chrome dev tools console to test sending requests like so:
fetch('/setjwt', { method: 'POST', headers: { credentials: 'same-origin' } } );
These are the headers:
But there is no cookie listed in the Application tab nor available in document.cookie.
The reason I have this route is two fold:
Understand how cookies work and interop with Express.
Get rid of this hacky route altogether and get the headers/environment set up correctly so my feathers authentication service's Set-Cookie response header is respected by the browser.
The feathers client on the login page is set up with fetch as its rest implementation, and I can set
fetch('/setjwt', { method: 'POST', headers: { credentials: 'same-origin' } } ); won't work.
The credentials property cannot be specified like that with fetch. The correct code is:
fetch(
'/setjwt',
{
method: 'POST',
credentials: 'same-origin',
headers: { whatever: 'somevalue' }
});
As for setting it up so that the feathers authentication service would work, again, it's not a normal header so brushing up on the documentation hopefully might yield something useful, but I don't think the feathers-rest wrapper over fetch supports passing non header options.