i'm trying to use NextAuthJS for authentication in my NextJS app..
I'm using this following code from documentation
authorize: async(credentials, req)=>{
const res = await fetch("http://localhost:3000/api/userverify",{
method: 'POST',
credentials: "include",
body: JSON.stringify(credentials),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
})
const user = await res.json()
if(res.ok && user){
return user
}
return null
}
the problem is the actual fetching, in the userverify.js i have this code:
export default async function verify(res, req){
const credentials = req.body
console.log(credentials)
const user = await findUser(credentials.email)
if(user){
if(await argon2.verify(req.body.password, user.password)){
res.status(200).send(user)
return user
}
else{
res.status(401).send("Credentials Incorrect")
}
}
}
req.body in this file is undefined, im not using express only nextjs built in api routes..
What can i do?
I think it is the order of arguments. did you try logging req and res. First argument is request and second is response:
export default async function verify(req, res){
Docs
Related
I make a POST request from my browser client:
const post = async (url, body) => {
try {
const response = await fetch(url, {
method: `POST`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body
});
return response.json();
} catch (error) {
console.log(error.stack);
}
}
const data = await post(`http://localhost:4050/analyze`, { text });
And I handle it on Express server with this setup:
app.use(express.urlencoded({ extended: true }));
This is my route:
router.post(`/`, errorHandler(async (req, res, next) => {
const { text } = req.body;
console.log(req.body)
const value = await analyze(text);
res.json({ rephrased });
}));
The console.log shows me this:
{ 'object Object': '' }
Why fetch method gives me Object instead of text property?
UPDATE:
When I do Stringify:
method: `POST`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: JSON.stringify(body)
The body became like this and console.log shows:
{ '{"text":"asdfasdf"}': '' }
You are passing fetch a plain object for the body and it doesn't know what to do with it, so it calls .toString() and gives you nothing useful.
Pass it a URLSearchParams object instead. (Here I assume text is a string)
const body = new URLSearchParams();
body.append("text", text);
This will convert to a application/x-www-form-urlencoded string.
(You can also omit the headers as fetch can infer the correct Content-Type from the URLSearchParams object.)
Re edit: JSON.stringify will encode the data as JSON. JSON is not application/x-www-form-urlencoded.
So i been trying to get access to the reddit api.
I registered to reddit. verified my mail. opened an app and got my credentials.
Followed this official documentation and also came across to this tutorial
All my efforts have failed and don't get any respond.
I am using nodejs. but also tried in postman and failed.
Tried 2 options using fetch and using axios:
const axios = require('axios');
const fetch = require('node-fetch')
const { URLSearchParams } = require('url')
class RedditApi {
clientId2 = "get ur own credentials by opening an app here https://www.reddit.com/prefs/apps";
clientSecret2 = "get ur own credentials by opening an app here https://www.reddit.com/prefs/apps";
authenticationUrl = `https://www.reddit.com/api/v1/access_token`;
BASE_URL = 'https://www.reddit.com/';
tokenAuth = null;
tokenExpirationTime = null;
currencyObj = null;
constructor(currencyObj) {
this.currencyObj = currencyObj;
console.log("constructor service")
}
async getAuthToken() {
const bodyParams = new URLSearchParams({
grant_type: "https://oauth.reddit.com/grants/installed_client",
device_id: "DO_NOT_TRACK_THIS_DEVICE"
});
console.log(this.clientId2, 'this.clientId');
debugger;
const headersObj = {
'Authorization': `Basic ${Buffer.from(`${this.clientId2}:`).toString('base64')}`,
'Content-Type': 'application/x-www-form-urlencoded',
};
let response = null;
try {
response = await axios.post(this.authenticationUrl,
bodyParams,
{
headers: headersObj
});
debugger;
} catch (error) {
debugger;
console.error(error);
console.log(error.stack);
return null;
}
}
async getAuthToken2() {
try {
// Creating Body for the POST request which are URL encoded
const params = new URLSearchParams()
params.append('grant_type', 'https://www.reddit.com/api/v1/access_token')
params.append('device_id', 'DO_NOT_TRACK_THIS_DEVICE')
// Trigger POST to get the access token
const tokenData = await fetch('https://oauth.reddit.com/grants/installed_client', {
method: 'POST',
body: params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${Buffer.from(`${this.clientId2}:`).toString('base64')}` // Put password as empty
}
}).then(res => {
debugger;
return res.text()
})
debugger;
if (!tokenData.error) {
debugger;
res.send(trendingResult)
}
res.status(tokenData.error).send(tokenData.message)
} catch (error) {
debugger;
console.log(error)
}
}
}
module.exports = RedditApi;
when using axios i get this respond: "Request failed with status code 401"
When using fetch i get this respond: "'403 Forbidden\nRequest forbidden by administrative rules.\n\n'"
Anybody knows what is the problem and how can i fix it?
Many thanks!
I'm setting up an authentication flow with JWT with my strapi backend and a next.js frontend.
Testing the backend with postman works as expected. I get back a user object and a JWT token.
But calling my backend from my frontend results in a statuscode 500 - internal server error.
I honestly don't see where I'm wrong and I tried to rewrite those calls from scratch again and again. Does anyone see where I have been wrong?
Here's my register.js where the call to my backend happens:
import cookie from 'cookie'
import { API_URL } from '#/config/index'
export default async (req, res) => {
if (req.method === 'POST') {
const { username, email, password } = req.body
const strapiRes = await fetch(`${API_URL}/auth/local/register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username,
email,
password,
}),
})
const data = await strapiRes.json()
if (strapiRes.ok) {
// Set Cookie
res.setHeader(
'Set-Cookie',
cookie.serialize('token', data.jwt, {
httpOnly: true,
secure: process.env.NODE_ENV !== 'development',
maxAge: 60 * 60 * 24 * 7, // 1 week
sameSite: 'strict',
path: '/',
})
)
res.status(200).json({ user: data.user })
} else {
res
.status(data.statusCode)
.json({ message: data.message[0].messages[0].message })
}
} else {
res.setHeader('Allow', ['POST'])
res.status(405).json({ message: `Method ${req.method} not allowed` })
}
This is my register function in my context
const register = async (user) => {
const res = await fetch(`${NEXT_CLIENT_URL}/api/register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(user),
})
const data = await res.json()
if (res.ok) {
setUser(data.user)
router.push('/account/dashboard')
} else {
setError(data.message)
setError(null)
}
}
This is how I call the context function in my next frontend
const handleSubmit = (e) => {
e.preventDefault()
if (password !== password2) {
toast.error('Passwords do not match!')
return
}
register({ username, email, password })
}
Glad for every piece of advice! Logging in works as expected in the same app.
How do I pass down parameters to a fetch request? I have this api call to fetch the logged in users username. How do I pass the returned results to the other fetch request route as it's request parameter?
//Gets logged in user's username
async function getProfile(){
try {
const response = await fetch(`${SUMMIT_API}/users/myprofile`,{
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${myToken}`
},
})
const data = await response.json();
console.log(data)
return data.profile
} catch (error) {
console.log('Oops Something Went Wrong! Could not get that user profile.');
}
}
Results from above fetch:
//Request parameters is the logged in user's username in the route retrieved from above fetch request
async function userChannel(){
try {
const response = await fetch(`${SUMMIT_API}/users/myprofile/**${username}**/channel`,{
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${myToken}`
}
})
const data = await response.json();
console.log(data)
return data.profile;
} catch (error) {
console.log('Oops Something Went Wrong! Could not render userChannel');
}
}
How do I get the information from first request passed to the second?
Since the information you want seems to be supplied by your async function getProfile, it seems like you simply need to await getProfile() and pull the necessary information out:
var profile = await getProfile();
var username = profile[0].username;
I have set up JWT to be set in localstorage whenever someone logins or registers. And it works, I can see the token in localstorage. But when I set the token in the headers with axios, node.js in the backend can`t find the token. Like it does not exists. I have checked it in the front end, I get logs of the token in the headers. And also when I request from postman it works. Here is the code.
setAuthToken function = {
const instance = axios.create({
baseURL: "https://localhost:5000",
});
if (token) {
instance.defaults.headers.common["x-auth-token"] = `${token}`;
console.log(instance.defaults.headers.common["x-auth-token"]);
} else {
delete instance.defaults.headers.common["x-auth-token"];
}
}
const loadUser = async () => {
if (localStorage.token) setAuthToken(localStorage.token);
console.log(localStorage.token);
try {
const res = await axios.get("/api/users");
console.log(res);
dispatch({ type: USER_LOADED, payload: res.data });
} catch (err) {
console.log(err.response.data.msg);
dispatch({ type: AUTH_ERROR });
}
The request comes to the await axios statement and goes to catch so error is in the request.
Here is the backend code
// Get current user
router.get("/", auth, async (req, res) => {
try {
const user = await User.findById(req.user.id);
res.status(200).json({ user });
} catch (err) {
console.log(err);
res.status(500).json({ msg: `Server Error` });
}
});
auth middleware function here = {
const token = req.headers["x-auth-token"];
console.log(token, "token in auth.js");
console.log(req.headers, "req.header");
if (!token) {
return res.status(401).json({ msg: `Access denied.` });
}
try {
const decoded = jwt.verify(token, config.get("jwtSecret"));
req.user = decoded.user;
next();
} catch (err) {
res.status(401).json({ msg: `Token is not valid` });
}
}
I`m new to backend develoment and axios. Can someone help me please. Thank you
Here are the console.logs
Logs
Logs
Little update, it looks like there is a problem with proxy, I am using my own backend api, and also movie data base api. So maybe thats why I cant set headers? Here are new logs:
config: Object { url: "/api/users", method: "get", timeout: 0, … }
data: "Proxy error: Could not proxy request /api/users from localhost:3000 to http://localhost:5000/ (ECONNREFUSED)."
headers: Object { connection: "keep-alive", date: "Wed, 05 May 2021 13:18:05 GMT", "keep-alive": "timeout=5", … }
request: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
status: 500
statusText: "Internal Server Error
I think the issue is because you are setting you are setting up your instance wrongly
set up your instance in a new file config.js -
import Axios from 'axios';
const baseURL = "http://localhost:5000";
const axiosInstance = Axios.create({
baseURL: baseURL,
});
axiosInstance.interceptors.request.use(
function (config) {
const token = localStorage.getItem('token');
if (token) {
config.headers['Authorization'] = 'Bearer ' + token;
}
return config;
},
function (error) {
return Promise.reject(error);
}
);
export default axiosInstance;
now when making any api request instead of using axios use axiosInstance eg-
axiosInstance.get('/something').then(res => console.log(res)).catch(err => console.log(err))