I am running the following script in a Windows command prompt with node myscript.js. The script requests a web application which is using Windows Authentication. I expect to receive status code 200. But the script returns a 401 Unauthenticated.
let request = require('request');
console.log(process.env.USERDOMAIN);
console.log(process.env.USERNAME);
request('http://internalurl',
function (error, response, body){
if (!error && response.statusCode == 200){
console.log('request successful!');
var input = JSON.parse(body);
}
console.log(response);
});
The process.env.USERNAME displays my current username which should have access to the web application. Because of this I am assuming that the script is running under the correct user account. What is the best practice to login into the web application?
It's normal to receive a 401 message when using Windows authentication - that's the first step in the Windows authentication process. The WWW-Authenticate header in the 401 response then tells you which authentication mechanisms are available (either NTLM or Negotiate).
The accepted answer to this question describes the process in more detail: https://stackoverflow.com/a/13960538/1202807
However, that answer doesn't provide a solution for a node client. But the last answer to that question does give an example of how to do it with node-libcurl:
var endpoint = urlString;
var url = require("url");
var endpointUrl = url.parse(endpoint);
var Curl = require( 'node-libcurl' ).Curl;
var curl = new Curl();
curl.setOpt( 'USERNAME', '' );
//curl.setOpt( 'VERBOSE', 1 );
curl.setOpt( 'URL', endpoint );
curl.setOpt( 'HTTPAUTH', Curl.auth.NEGOTIATE );
curl.setOpt( 'NOPROXY', endpointUrl.hostname );
curl.on( 'end', function( statusCode, body, headers ) {
if (statusCode === 200) {
console.log(body);
cb(null, { statusCode, body, headers } );
} else {
cb(new Error(), { statusCode, body, headers } );
}
this.close();
});
curl.on( 'error', curl.close.bind( curl ) );
curl.perform();
I've never done this in node myself though, so that's about all the help I can be.
Related
I am trying to set up a simple login system for a small project. I have managed to connect the website to an login api hosted locally via mysql database.
I'm using express/nodejs on backend and Vue for front end. Also using axios to send http requests.
The error i get is POST http://localhost:3001/api/get-user 422 (Unprocessable Entity)
"{"message":"Please provide the token"}"
Client side part of code.
finally{
const auth = await axios.post(`/api/get-user`, {
headers: {
Authorization: `Bearer ${this.Token}`
}
})
}
Server side part.
router.post('/get-user', signupValidation, (req, res, next) => {
if(
!req.headers.authorization ||
!req.headers.authorization.startsWith('Bearer') ||
!req.headers.authorization.split(' ')[1]
){
return res.status(422).json({
message: "Please provide the token",
});
}
const theToken = req.headers.authorization.split(' ')[1];
const decoded = jwt.verify(theToken, 'the-super-strong-secrect');
db.query('SELECT * FROM users where id=?', decoded.id, function (error, results, fields) {
if (error) throw error;
return res.send({ error: false, data: results[0], message: 'Fetch Successfully.' });
});
});
I have put a base URL.
The login is working 100% and I am able to extract the token from the response data.
I used Postman to send the request to the server to get the user and it works perfectly. I believe the issue is in the code of the client side or maybe the client side is sending the token incorrectly where the server side cant read it... I'm not sure please help.
The second parameter in axios post is the body
finally{
const auth = await axios.post(`/api/get-user`,{}, {
headers: {
Authorization: `Bearer ${this.Token}`
}
})
}
I'm trying to build an app that allows me to call Spotify's API from a create-react-app client through a nodejs express server. I'm trying to use the Authorization Code Flow.
It works getting the authorization code using the following code to generate the URL, completely on client side (if and how using server-side is another question):
getSpotifyCodeUrl() {
const authEndPoint = 'https://accounts.spotify.com/authorize'
const clientId = CLIENT_ID;
const responseType = 'code';
const redirectUrl = 'http://localhost:3000/';
// TODO: state for cross-site request forgery protection
// cont state = '...';
const scope = 'user-read-private user-read-email';
return(
authEndPoint +
'?response_type=' + responseType +
'&client_id=' + clientId +
(scope ? '&scope=' + encodeURIComponent(scope) : '') +
'&redirect_uri=' + encodeURIComponent(redirectUrl)
)
}
The user simply clicks a link with the href as generated above.
{!this.state.token ? <a className="btn btn--loginApp-link" href={this.getSpotifyCodeUrl()}>
Login to Spotify
</a> : ""}
After the user gets redirected back, I use the following function to extract the authorization code from
componentDidMount() {
this.setState({code: new URLSearchParams(window.location.search).get('code')});
}
With the code I retrieve the access token. Call from client:
getSpotifyAccessToken() {
fetch('/auth?code=' + this.state.code)
.then((res) => res.json())
.then(data => {
this.setState({token: data.token});
localStorage.setItem('token', this.state.token);
});
}
API call on server:
app.get("/auth", (req, res) => {
let code = req.query.code;
let authOptions = {
url: 'https://accounts.spotify.com/api/token',
form: {
code: code,
redirect_uri: 'http://localhost:3000/',
grant_type: 'authorization_code'
},
headers: {
'Authorization': 'Basic ' + (new Buffer.from(clientId + ':' + clientSecret).toString('base64'))
},
json: true
};
request.post(authOptions, function(error, response, body){
if (!error && response.statusCode === 200) {
token = body.access_token;
res.json({ token: "Token: " + body.access_token});
} else {
console.log("/auth response body")
console.log(body)
}
});
});
Strange thing is I get a token, but can also see the following error in my server terminal:
{
error: 'invalid_grant',
error_description: 'Invalid authorization code'
}
If I then try to use the token to do a (simple) request from client:\
getSpotifyMe() {
fetch('/me?token=' + this.state.token)
.then((res) => res.json())
.then(data => {
console.log(data);
});
}
And corresponding server call:
app.get("/me", (req, res) => {
let token = req.query.token;
console.log("Token: " + token);
let options = {
url: 'https://api.spotify.com/v1/me',
headers: { 'Authorization': 'Bearer ' + token },
json: true
}
request.get(options, function(error, response, body) {
console.log("/me request body");
console.log(body);
if (!error && response.statusCode === 200) {
res.json(body);
} else {
}
})
})
Which gives me a 401 error:
{ error: { status: 401, message: 'Invalid access token' } }
I've tried some things. Doing the call from client, no success. Refreshing tokens, deleting cookies, authorizations from account, but no success. The strange thing is I can use the token said to be invalid in the Spotify Web Console, doing the exact same call I'm trying to do in the application.
Do you know where I'm causing these errors (invalid_grant and 401) in my application? And how I could solve them?
I ended up following the example on Spotify GitHub more closely.
I changed my create-react-app to simply call the /login server route. Don't use fetch like I tried, you'll end up with a cross-origin error once the server calls the Spotify API from a different origin. For some unapparent reason I can't use href="/login", the server simply doesn't respond, but that's fruit for another SO question.
Login to Spotify
The server index.js is now simply the Authorization Code Flow app.js with my own variables and one minor tweak.
My redirect_uri is http://localhost:3001/callback, I struggled long and tiresome with redirecting back to my client create-react-app at http://localhost:3000, perhaps this is where something goes wrong with the auth code and access token, IDK. You wanna go straight into the server-side callback. Much more intuitive for the user as well: one click and bam, logged in, no messy redirects in between.
In the /callback route on the server, when the access_token and refresh_token have either been successfully retrieved or not, that's when you want to redirect back to your client, http://localhost:3000 for me. With the tokens of course. The example uses URL params, I'm guessing setting a cookie should also work, but have to do some research if that's a security no-go.
The small little tweak I made is to the CORS clause for the app. There's no need for incoming request at the server other than coming from my client, so I added a {origin: 'http://localhost:3000'} there, just in case.
app.use(express.static(__dirname + '../client/build'))
.use(cors({origin: 'http://localhost:3000'}))
.use(cookieParser());
That's it, works like a charm, I can see the response body of the /v1/me call coming in at the server (there's a console log in the example code) and tokens are coming back to the client.
var queryparam = "track:godsplan%20artist:drake&type=track&market=US&limit=10";
app.get('/get_track', function(req,res){
var options = {
url:"https://api.spotify.com/v1/search?"+queryparam,
headers: { 'Authorization': 'Bearer ' + access_token },
json: true
}
request.get(options, function(error, response, body) {
if(!error && response.statusCode === 200) {
console.log(body);
}
else{
console.log(error);
console.log(response.statusCode);
}
res.redirect('/#');
});
});
here is what I have and i am trying to get god's plan by drake to appear on my console when I run the server on local host and my access_token works but whenever i run the "/get_track" i get a bad request error, does anyone know why?
Your missing q=
var queryparam = "q=track:godsplan%20artist:drake&type=track&market=US&limit=10";
https://developer.spotify.com/documentation/web-api/reference/search/search/#request-parameters
what is that module "request" ?
(http, request-promise, request)
although I suppose that your request is simply not correctly formed
you need to try:
var queryparam = "q=track:godsplan%20artist:drake&type=track&market=US&limit=10";
I'm trying to build a CLI that uses the GitHub api. I instantly run into a road block. Although I've read the introductory docs up and down, I don't see what is wrong in the following code.
var userData = require('../userData');
var request = require('request');
module.exports = {
hitEndpoint: function() {
var username = "<redacted_user_name>",
password = "<redacted_password>",
auth = "Basic " + new Buffer(username + ":" + password).toString("base64");
var options = {
method: 'get',
url: " https://api.github.com/<redacted_user_name>",
headers: {
"Authorization": auth,
"User-Agent": "<redacted_whatever_doesnt_matter>"
}
}
request(options, function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
});
},
}
prints:
error: null
statusCode: 404
body: {"message":"Not Found","documentation_url":"https://developer.github.com/v3"}
To get your own profile you'll want to hit the authenticated user endpoint, you shouldn't replace this with your own username, GitHub will know who you are based on your authentication string:
https://api.github.com/user
To get another user's profile you'll want to hit the users endpoint:
https://api.github.com/users/:username
I'm trying to validate recaptcha using requestify. This is what the docs says about the api:
API Request
URL: https://www.google.com/recaptcha/api/siteverify
METHOD: POST
POST Parameter Description
secret Required. The shared key between your site and ReCAPTCHA.
response Required. The user response token provided by the reCAPTCHA to the user and provided to your site on.
remoteip Optional. The user's IP address.
This is my request
requestify.post('https://www.google.com/recaptcha/api/siteverify', {
secret: '**********',
response: req.body['g-recaptcha-response'],
})
.then(function(response){
console.log(response.body);
})
The response i get is
{
"success": false,
"error-codes": [
"missing-input-response",
"missing-input-secret"
]
}
I think I may be posting the parameters in the wrong way or maybe I misuderstand the api docs.
I use "request" but it should work the same way.
var request = require('request');
var data = {
remoteip: req.connection.remoteAddress, // #IP of the user
response: req.body["g-recaptcha-response"],
secret: RECAPTCHA_PRIVATE_KEY
};
request.post({
'url': RECAPTCHA_URL,
form: data,
'proxy': HTTP_PROXY // (optional) I'm behind a proxy
}, function (error, response, body) {
if (!error && response.statusCode == 200) {
var b = JSON.parse(body);
if ( b.success === true ) {
// ... your code here
} else // ...
} else // ....
});