After authorization through spotify web api in node I redirect to another page with url: http://localhost:8888/homepage#access_token=....
so I want to take the access token on that page and fetch data but when I use req.query I receive an empty object. Is there something wrong? How can I get that access token?
request.post(authOptions, (error, response, body) => {
if (!error && response.statusCode === 200) {
const access_token = body.access_token;
const refresh_token = body.refresh_token;
const options = {
url: "https://api.spotify.com/v1/me",
headers: { Authorization: `Bearer ${access_token}` },
json: true
};
request.get(options, (error, response, body) => {
console.log(body);
});
res.redirect(
"/homepage#" +
querystring.stringify({
access_token: access_token,
refresh_token: refresh_token
})
);
const express = require("express");
const router = express.Router();
router.get("/", (req, res) => {
res.render("index/welcome");
});
router.get("/homepage", (req, res) => {
res.render("index/homepage");
console.log(req.query);
});
module.exports = router;
You're passing the token via a fragment instead of query parameters, aren't you?
const url = require('url');
res.redirect(url.format({
pathname:"/homepage",
query: {
"access_token": access_token,
"refresh_token": refresh_token
}
}));
Working with fragments is for client side handling only, it should never reach the server.
Related
I'm trying to create a GitHub OAuth login option with Node, but even when I refresh the secrets and clear all tokens it won't work.
Here's my code:
const githubClientId = "***********";
const githubClientSecret = "*********************************";
app.get("/github-oauth", (req, res) => {
res.render("github-oauth/login");
});
app.get("/github-oauth/get", (req, res) => {
res.redirect(`https://github.com/login/oauth/authorize?client_id=${githubClientId}`);
});
app.get("/github-oauth/callback", (req, res) => {
// Sign into or create an account with GitHub
const requestToken = req.query.code;
axios({
method: "post",
url: `https://github.com/login/oauth/access_token?client_id=${githubClientId}&client_secret=${githubClientSecret}&code=${requestToken}`,
headers: { accept: "application/json" }
}).then((response) => {
// Runs other code
res.redirect("/");
});
});
Thanks!
I am a beginner with node js. I want to make an authentication server using jwt (jsonwebtoken).
The problem is when I test my end point "/api/posts?authorisation=Bearer token..." in postman with method POST with the right token, it gives me forbidden.
Here is my code:
const express = require('express')
const jwt = require('jsonwebtoken')
const app = express()
app.get("/api", (req, res) => {
res.json({
message: "Hey there!!!"
})
})
app.post('/api/posts', verifyToken, (req, res) => {
jwt.verify(req.token, "secretkey", (err, authData) => {
if (err) {
res.sendStatus(403) //forbidden
res.send(`<h2>${err}</h2>`)
} else {
res.json({
message: "Post Created...",
authData
})
}
})
})
app.post('/api/login', (req, res) => {
const user = {
id: 1,
username: "John",
email: "john#gmail.com"
}
jwt.sign({ user: user }, "secretkey", (err, token) => {
res.json({
token
})
})
})
function verifyToken(req, res, next) {
const bearerHeader = req.headers["authorization"]
if (typeof bearerHeader !== "undefined") {
const bearerToken = bearerHeader.split(" ")[1]
req.token = bearerToken
next()
} else {
res.sendStatus(403) //forbidden
}
}
app.listen(5000, () => {
console.log("Server is running :)")
})
I expected it to work because I brought it from a tutorial.
Your code works
The problem is in your request invocation:
According to the oauth2 spec, the Authorization token should be a header and your code expect that
So the token should be sent as http header, not as a query param like foo/bar?authorization=Bearer token...".
Here some samples
Postman
Axios (javascript)
let webApiUrl = 'example.com/getStuff';
let tokenStr = 'xxyyzz';
axios.get(webApiUrl,
{ headers: { "Authorization": `Bearer ${tokenStr}` } });
Advice
Read about oauth2 and jwt
Perform the token validation in the middleware to avoid the validation on each route
I have an API in which uses VerifyToken authentication with JWT. This works through postman, however it appears there's an issue passing this through to the frontend to ensure the token is verified.
For one, I have a code block to create verifyToken:
const verifyToken = (req, res, next) => {
const authHeader = req.headers.token;
if (authHeader) {
const token = authHeader.split(" ")[1];
jwt.verify(token, process.env.JWT_SEC, (err, user) => {
if (err) res.status(403).json("Token is not valid!");
req.user = user;
next();
});
} else {
return res.status(401).json("You are not authenticated!");
}
};
If I run the following in Postman, it works all good, header and all.
localhost:5000/api/users/updateUser/62a9be62a8262145b72feee9
This is then handled in requestMethods,
import axios from "axios";
const BASE_URL = "http://localhost:5000/api/";
const user = JSON.parse(localStorage.getItem("persist:root"))?.user;
const currentUser = user && JSON.parse(user).currentUser;
const TOKEN = currentUser?.accessToken;
export const publicRequest = axios.create({
baseURL: BASE_URL,
});
export const userRequest = axios.create({
baseURL: BASE_URL,
bearer: { token: `Bearer ${TOKEN}` },
});
However when I pass this to the frotnend, for example through a request like this,
const updateUser = async () => {
//include all in the state earlier with spread
//update only position, which is input
userRequest.put(`users/updateUser/${user._id}`, userData);
console.log('your data has updated to', userData)
//include the put request here for API
}
I am now getting an error for a 401: Error: Request failed with status code 401
It appears the token isn't being passed to the frontend correctly. What am I doing wrong?
Passing token in headers in Axios is not tuned correctly. Notice the headers config.
export const userRequest = axios.create({
baseURL: BASE_URL,
headers: { token: `Bearer ${TOKEN}` },
});
Another way to pass the token is where you are calling the API:
const updateUser = async () => {
//include all in the state earlier with spread
//update only position, which is input
userRequest.put(`users/updateUser/${user._id}`, userData, {
headers: {token: `Bearer ${TOKEN}`}
});
console.log('your data has updated to', userData)
//include the put request here for API
}
Here is another tip: in your auth middleware by detecting a wrong token, do not go to next and return!
const verifyToken = (req, res, next) => {
const authHeader = req.headers.token;
if (authHeader) {
const token = authHeader.split(' ')[1];
jwt.verify(token, process.env.JWT_SEC, (err, user) => {
if (err) {
res.status(403).json('Token is not valid!');
return;
} else {
req.user = user;
next();
}
});
} else {
return res.status(401).json('You are not authenticated!');
}
};
I created a middleware as below:
const oAuth = (req, res, next) => {
axios.post(tokenEndpoint, "", { params: {
grant_type: process.env.GRANT_TYPE,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
code: process.env.AUTHORIZATION_CODE,
}}).then(response => {
req.oAuth = response.data;
//console.log(response.data);
console.log(req.oAuth);
}).catch(err => {
console.error(err);
})
next();
}
module.exports = oAuth;
the response/result of the oauth function is something like:
{
access_token: '1000.ddf6d96b4f3sadasdasdas55a2450ae13',
refresh_token: '100dasdsadasdsadhgdhgfhdghdfghe427288',
api_domain: 'https://www.oapis.com',
token_type: 'Bearer',
expires_in: 3600
}
now in the "index.js" file I'm trying to destructure the oAuth function response object to access the attribute access_token and put it in the URL to make a post request, but I'm not succeeding. what am I doing wrong?
const express = require("express");
const axios = require("axios");
const oAuth = require("./oAuth.js");
const app = express();
app.use(oAuth);
var port = process.env.PORT || 3001;
const someAPI = "https://www.oapis.com/crm/v2/Leads";
app.get("/", async (req, res) => {
try {
const {access_token} = req.oAuth
const response = await axios({
method: "GET",
url: someAPI,
//timeout: 1000,
headers: { Authorization: `Zoho-oauthtoken ${access_token}` },
});
return res.json(response.data);
} catch (error) {
console.log(error);
if (error.response.status === 401) {
res.status(401).json("Unauthorized to access data");
} else if (error.response.status === 403) {
res.status(403).json("Permission denied");
} else {
res.status(500).json("Whoops. Something went wrong");
}
};
});
I would suggest using async/await here to wait for oauth response and only then modify request object in order to pass it further to the next() callback.
const oAuth = async (req, res, next) => {
try {
const response = axios.post(tokenEndpoint, "", { params: {
grant_type: process.env.GRANT_TYPE,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
code: process.env.AUTHORIZATION_CODE,
}});
console.log(response.data);
req.oAuth = response.data;
} catch (e) {
console.log(e);
}
next();
}
module.exports = oAuth;
I'm trying to get my refresh_token to generate a new access_token. I'm using the request module to make the request, but It's returning an error saying something along the lines of "Could not find page".
var request = require('request');
module.exports = function(callback){
console.log('here');
request('https://googleapis.com/oauth2/v3/token?client_id=NotID&client_secret=Not_Secret&refresh_token=NotRefresh&grant_type=refresh_token', function (error, response, body) {
if (!error && response.statusCode == 200) {
callback(response)
}
});
}
Try this:
request.post('https://accounts.google.com/o/oauth2/token', {
form: {
grant_type:'refresh_token',
refresh_token:'..',
client_id:'..',
client_secret:'..'
}
}, function (err, res, body) {})
This works..
const axios = require('axios');
const querystring = require('querystring');
const keys = require('../config/keys');
const getAccessToken = async refreshToken => {
try {
const accessTokenObj = await axios.post(
'https://www.googleapis.com/oauth2/v4/token',
querystring.stringify({
refresh_token: refreshToken,
client_id: keys.googleClientID,
client_secret: keys.googleClientSecret,
grant_type: 'refresh_token'
})
);
return accessTokenObj.data.access_token;
} catch (err) {
console.log(err);
}
};