req.user is undefined in passportjs even when credentials is included - reactjs

I'm trying to send user information from front end after being google authenticated to the backend. However, even when I included credentials, the user information is not being sent to the backend which is strange. I'm thinking this might be a same site issue but I'm not totally sure and am not even sure of how to go about fixing that problem. If somebody can help me I would appreciate it.
This is the request being sent from the frontend:
export const checkLogin = createAsyncThunk(
"user/checkLogin",
// function has empty argument parameter
async () => {
const url = "http://localhost:3001/auth/profile";
const user = await fetch(url, {
credentials: "include",
}).then((response) => response.json());
return user;
}
);
This is the code in the backend for google authentication. But the problem is that in the /profile route we are not getting any information related to the user. It is only "undefined" which I'm not sure why.
authRouter.get("/profile", (req, res) => {
console.log(req.user);
if (req.user) {
res.send({
redirectLink: "http://127.0.0.1:5173",
user: req.user,
});
} else {
res.send({
redirectLink: "http://127.0.0.1:5173",
user: null,
});
}
});
authRouter.get(
"/google",
passport.authenticate("google", {
scope: ["profile"],
})
); // passport knows to authenticate with google
authRouter.get(
"/google/redirect",
passport.authenticate("google"),
(req, res) => {
// in this step google send back the info with a code that can then be used
// by the application to pull data from the user on google
console.log(req.user);
res.redirect("http://127.0.0.1:5173"); // go back to the home page
}
);

Nevermind! I got it. I solved this by changing the Vite configuration for the hosting. Instead of hosting it using 127.0.0.1, I changed it to verbatim, which is then localhost. I guess this is like same-site cookie problem.
If anyone runs into this problem you can change this in the vite.config file. The link to do this is here:
https://vitejs.dev/config/server-options.html#server-host

Related

Github Rest API not fetching results on hosting

I am supposed to use GITHUB REST API to fetch details such as username and repositories of a user. I am getting the results on localhost and when I deploy this project using VERCEL the project is hosted fine. The problem is that in the hosted URL the I am not able to see the results that were supposed to be fetched by the API. This is the error in the console:
GEThttps://api.github.com/users/Xaid-vfx/repos?page=1&per_page=8 [HTTP/2 401 Unauthorized 581ms]
Uncaught (in promise) HttpError: Bad credentials
What I understood is that my Authorisation key is not working whenever I am trying to deploy using vercel.
Here's the code that I am using to make API calls
const octokit = new Octokit({
auth: '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'
});
useEffect(() => {
async function get() {
setloading(true);
const req1 = await octokit.request('GET /users/{username}/repos?page=1&per_page=1000', {
username: username
})
setsize(req1.data.length)
console.log(req1.data.size);
const details = await octokit.request('GET /users/{username}', {
username: username
})
// console.log(details);
setloading(false)
return [details.data]
}
if (username != '') {
get().then(function (res) {
// setrep(res[0]);
console.log(res[0]);
setname(res[0].login);
seturl(res[0].avatar_url);
setbio(res[0].bio);
setlink(res[0].html_url)
})
}
}, [count])
This code is working fine on localhost and giving the results . When I deploy using vercel from GitHub, it does not fetch results on localhost as well as the deployed url. This has something to do with authorisation token

How to fetch data from a REST API by using an API-Token

I'm trying to fetch data from the Jira Rest API in my React application by using the Axios library for http requests. An API token is necessary, in order to access data via the Jira API. I generated an API token in my Jira account settings, but I can't figure out, how to include it in my http request to gain access.
This is the endpoint provided by the Jira documentation for getting an issue from the Jira board:
curl -u admin:admin http://localhost:8080/jira/rest/api/2/issue/TEST-10 | python -mjson.tool
This is the React state hook for setting the data to the fetched data:
const [jiraTicket, setJiraTicket] = useState([]);
This is the fetch function for the API request (${} will be filled with user input):
function getJiraTicket() {
axios.get(`${username}:${apiToken}#Content-Type:application/json/https:/${jiraSiteName}.atlassian.net/rest/api/2/issue/${projectKey}-${ticketId}`)
.then((res) => {
const data = res.data;
setJiraTicket(data);
})
}
The button inside the react component return should invoke the fetch function:
return(
<Container>
<Button onClick{getJiraTicket()}>Fetch Jira Ticket</Button>
</Container>
);
This is the error I'm currently getting, because the authorization is not working the way I did it
(I replaced the provided username, API token etc. for this example):
GET http://localhost:3000/username:apitoken#https:/sitename.atlassian.net/rest/api/2/issue/projectkey-ticketid 404 (not found)
Edit:
My current approach:
function getJiraTicket() {
axios.get(`${userName}:${apiToken}#https://${siteName}.atlassian.net/rest/api/2/issue/${projectId}-${ticketId}`,{
auth: {
username: userName,
password: apiToken,
},
withCredentials: true
})
.then((res) => {
const data = res.data;
console.log(data);
setJiraTicket(data);
})
.catch(err => {
// This error means: The request was made and the server responded with a status code
if(err.res) {
console.log(err.res.data);
console.log(err.res.status);
console.log(err.res.headers);
console.log("request was made and server responded with status");
// The request was made but no response was received
} else if (err.request) {
console.log(err.request);
console.log("request was made, but no response was received");
// Something happened in setting up the request that triggered an error
} else {
console.log("Error", err.message);
console.log("request is note set up correctly");
}
console.log(err.config);
})
Current error, which I defined accordingly to the axios doc: "request was made, but no response was received"
Endpoint that works well in Postman (Basic auth is provided in Postman):
https://sitename.atlassian.net/rest/api/2/issue/projectid-ticketid
Update: CORS access isn't allowed, when an application tries to access the Jira API endpoints directly. This restriction takes place in order to prevent random authenticated requests to the specific Jira site, because the access is based on session based authentication. However the API endpoints can be accessed, if OAuth 2.0 is used instead of Basic auth, because the application will redirect the user to the Jira auth itself via this link:
https://auth.atlassian.com/authorize? audience=api.atlassian.com&
client_id=YOUR_CLIENT_ID&
scope=REQUESTED_SCOPE_ONE%20REQUESTED_SCOPE_TWO&
redirect_uri=https://YOUR_APP_CALLBACK_URL&
state=YOUR_USER_BOUND_VALUE& response_type=code& prompt=consent
Source: https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/#known-issues
Axios uses a headers config for get/post so you should not include them in your URL. Here is a general example of how you should construct the URL and apply headers:
let axiosUrl = `https://${jiraSiteName}.atlassian.net/rest/api/2/issue/${projectKey}-${ticketId}`
axios({
baseURL: axiosUrl,
method: 'get',
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin", "*"
},
//timeout: 2000,
auth: {
username: userName,
password: apiToken,
}
})
.then((res) => {
setJiraTicket(res.data);
})
.catch(function (error) {
console.log(error);
});

Understanding Next.JS with-iron-sessions requirements for use in own environment

I am trying to get some of the examples located in the with-ireon-sessions github account to work with my own back-end: https://github.com/vercel/next.js/tree/canary/examples/with-iron-session
I can sign in using const { user, mutateUser } = useUser(); with useUser() being from the example: https://github.com/vercel/next.js/blob/canary/examples/with-iron-session/lib/useUser.js
My sign-in method looks like this;
const signIn = async ({ email, password, remember_me }) => {
try {
await mutateUser(
fetchJson(`${API.baseURL}/${API.signIn}`, {
method: "POST",
headers: {
"Accept": 'application/json',
"Content-Type": "application/json"
},
body: JSON.stringify({
email,
password
})
})
);
} catch (error) {
console.error("An unexpected error happened:", error);
setErrorMessage((<p className="error">{error.data.message}</p>));
}
};
I can see my user change, but I still have the following issues:
I don't see any cookies get created. Does with-iron-sessions require the site to be deployed to the vercel cloud in order for cookies to get added, or am I right in thinking I can use my own server and API endpoints?
What's the pattern for using the /api/user endpoint in useUser.js; does the endpoint look for the cookies (that are not getting created for me) and do it's own validation, or is there validation I need to do in my version of that endpoint? Is there an example of what that endpoint looks like server-side you might be able to point me to?
Is there a way to refresh the cookie (once I get them to appear) so they are X days since last using the site instead of X days from first login so it's a sliding cookie lifespan, or does that happen automatically?
When I sign out my sign_out endpoint returns a 204 status code but the UI doesn't change like it does when I sign in. Any tips for me there?
Thank you!

Fetching 301 Redirect Data In server.js (Express/NextJS)

I'm working on a project using express and next js and I've found a great example of how to setup an array of data for your redirects in your server.js file. However, if it is possible I would like to build a plugin within WordPress that will allow a user to submit data for redirects so that it could be managed by someone without technical knowledge. My question is, is it possible to fetch data within my server.js file to replace the data in this example?
const express = require('express')
const next = require('next')
const { join } = require('path')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
//This is the data I want to fetch through the WP Rest API
const redirects = [
{ from: '/old-link-1', to: '/new-link-1' },
{ from: '/old-link-2', to: 'https://externalsite.com/new-link-2' },
]
app.prepare().then(() => {
const server = express()
redirects.forEach(({ from, to, type = 301, method = 'get' }) => {
server[method](from, (req, res) => {
res.redirect(type, to)
})
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, err => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
Yes, I believe it's possible do do something like that.
This library would allow you to make an API request within express: https://github.com/request/request
Executed like so:
var request = require('request');
request('http://www.google.com', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // Print the google web page.
}
})
The next step would be to create an endpoint in wordpress with all of the 301's that you want to create:
function my_custom_endpoint(){
return 'Hey look, its some data';
}
// Register the rest route here.
add_action( 'rest_api_init', function () {
register_rest_route( 'yournamespace/v1', 'my_custom_endpoint',array(
'methods' => 'GET',
'callback' => 'my_custom_endpoint'
));
});
Good luck, and happy coding!
So, just incase anyone else stumbles upon the problem of programmatically adding redirects that originate on a WordPress install this is how it can be done. My tech stack is React, Next.js with an Express server pulling in data from a WordPress install that is living elsewhere in the webs.
WordPress:
1) Create a blank WordPress plugin (Google is your friend)
2) Create an activation hook within your plugin to create a database(Again, Google with 'to_url' and 'from_url' for each entry.
3) Register a Rest Route within plugin (Like described above with Tanner's answer)
This Rest Route should be pulling your info from the database and returning it as an array in this format:
[
{ 'from': '/about', 'to': '/about-us' },
{ 'from': '/test3', 'to': '/banks/testing-page' },
]
4) Create a plugin admin page with a form that allows the users to add entries to this database. As your database grows your response from the rest api will grow and your redirects will seamlessly be included in your project.
5) In your React server.js you're going to need the following setup
const request = require("request");
let redirects;
request('https://yourwebsite.com/wp-json/YOUR-ROUTE/v2/redirects', function (error, response, body) {
if (!error && response.statusCode == 200) {
redirects = JSON.parse(body);
}
})
redirects.forEach(({ from, to, type = 301, method = 'get' }) => {
server[method](from, (req, res) => {
res.redirect(type, to)
})
});
Caveats: Make sure when you're manipulating data with forms in php you're taking proper precautions to sanitize and escape everything.

Ionic + Passport isAuthenticated() returns false

I have my app in angularJs 1.6 built with MEAN stack working well, i'm using passport for authentication.
When I decide to test it with ionic, the app itself works well (files are basically identical) but the authentication with passport is broken
I can register and login a user, but when I want to check if the user is logged by using req.isAuthenticated() on my server, it always answers false.
I think it's because when I make a request from my normal angular app, the request contains a user object with password and email, but when I do from my ionic app, the user is missing
I've spend the day working on it, any help would be great !
EDIT 1:
Sorry for not including code, it's my first experience here
My login route + my function for login
app.post('/api/login', login);
function login(req, res, next) {
//console.log(req);
passport.authenticate('local-login', function(err, user, info) {
if (err) {
return next(err); // will generate a 500 error
}
// Generate a JSON response reflecting signup
if (! user) {
return res.send({success : 'false', message : req.flash('loginMessage') });
}
req.login(user, function(err) {
if (err) { return next(err); }
//console.log(req);
return res.send({success : 'true', message : req.flash('loginMessage') });
});
})(req, res, next);
}
The problem is, req.login is executed and I get a success: true, but with the ionic/cordova app, nothing seems to be memorized
After that, when I try to check if the user is logged with this
app.get('/api/login/loggedin', function(req, res) {
res.send(req.isAuthenticated() ? req.user : '0');
});
I always get '0', I think it is because cordova/ionic app cannot use cookies (the difference between requests is also the lack of cookie from the ionic one), but I can't understand how to manage a solution that works both with my web angular app and it's ionic version (still with passport)
Solution I just found:
In fact, it was a CORS problem because I don't know exactly why but Ionic/cordova didn't put {user:...} informations in the post request
Simply add
var cors = require('cors');
app.use(cors({origin: 'http://localhost:8100', credentials: true}));
to your server, it allows req to contains informations needed
and add
{withCredentials: true}
to all of your requests that are going to be checked with isAuthenticated(). For example:
$http.get('http://localhost:8081/api/todos', {withCredentials: true});
So the request sent contains the {user:...} part
I don't exactly know why you need to authorize it both in client and server side but it works fine

Resources