When I use $resource for a REST login, the transformRequest doesn't add the Authorization header as intended. Using a $.ajax call it does work as intended.
So using:
$scope.login2 = function() {
function setHeader(xhr){xhr.setRequestHeader("Authorization", "Basic " + btoa($scope.gebruikersnaam + ':' + $scope.wachtwoord))}
$.ajax({type: "POST", url: "http://localhost:8000/authview/", beforeSend: setHeader}).
fail(function(resp){
console.log('bad credentials.')
}).
done(function(resp){
console.log('welcome ' + resp.email)
})
}
I get the authorization header added to the request:
Origin: http://localhost
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
But when doing:
$scope.login = function() {
api.auth.login($scope.getCredentials()).
$promise.
then(function(data){
// on good username and password
$scope.gebruikersnaam = data.username;
}).
catch(function(data){
// on incorrect username and password
alert(data.data.detail);
});
};
where "api.auth.login" is defined like:
kmregistratieApp.factory('api', function($resource){
function add_auth_header(data, headersGetter){
var headers = headersGetter();
headers['Authorization'] = ('Basic ' + btoa(data.username + ':' + data.password));
}
return {
auth: $resource('http://localhost:8000/authview/', {}, {
login: {method: 'POST', transformRequest: add_auth_header},
logout: {method: 'DELETE'}
}),
users: $resource('http://localhost:8000/authview/', {}, {
create: {method: 'POST'}
})
};
});
After "headers['Authorization'] = ('Basic ' + ..." (when debugging) I can see it sitting in headersGetter:
headers: Object
Authorization: "Basic YWRtaW46cGFzc3dvcmQ="
accept: "application/json, text/plain, */*"
content-type: "application/json;charset=utf-8"
But it doesn't turn up in the Network tab when inspecting the headers.
So my question is why doesn't the $resource way of working not add the Authorization header?
TransformRequest is not meant to be used to modify headers.
See AngularJS changelog. Scroll a bit downwards and you will see this:
transformRequest functions can no longer modify request headers.
HTTP headers can only be specified when using $http. Example:
$http.post('/someUrl', data, { headers: { 'Authorization': 'Basic'+key } });
Related
I am quite new to k6 and load testing and I could not figure out why I am not able to push a token from one request to another, to test the login process in a Laravel-built web app. I hope somebody can help me out with this issue.
So my script looks like the following:
First request from where I want the token:
import { parseHTML } from 'k6/html';
import { sleep, group, check } from "k6";
import http from 'k6/http'
export const options = {}
export default function main() {
let response
group('page_1 - http://localhost:81/login', function () {
response = http.get('http://localhost:81/login', {
headers: {
host: 'localhost:81',
'user-agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0',
accept:
'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'accept-language': 'en-US,en;q=0.5',
'accept-encoding': 'gzip, deflate, br',
connection: 'keep-alive',
cookie:
'XSRF-TOKEN=eyJpdiI6InY5ckZiaGdFTkI4Q0YyRi8rdmtyNUE9PSIsInZhbHVlIjoiT0NjZXlWWVBubTE5Zjh6cXBmNmZFWTdZKzBjVXlEOGhheGR0aVUybURSSGRZbEFmQ0N2RW5BQ3pOYzBQUXgweXhUaGNpRDhrcTV5SHBJUkEvU0FYTmN3eCswYTFsVnhQdk8wL1dkeHMvOTNXRTU4dnk2WjJ0QWFCSWdyQzEwQkwiLCJtYWMiOiIyODI1YmFkMDI1MzlkOGY4ODEyMDg4YWU5M2I5MWE3NmI3Yjg2ODczYTBkMzhhNmZiZTU5ODNlZDBjOGViNWIzIn0%3D; dev_session=eyJpdiI6ImNGalhPQW9GTWlYLzdsaEg1Qk0zdnc9PSIsInZhbHVlIjoiVU5jQ21OZmkyUDVnUmd2WUxUc3Z5dWhRbzBJTm1HWFhmQ1RuNzdFaEpRb1IzdVlIa1VhUkNXYTBlc2IxMHRMajl6UTAzYmFVTHZheEdTV2RrYU84d3pmdEUxYUlkaVFFT3J5YUVWSE1wVklRektqemVmbjhmK3hLWHo2ZmlMYlgiLCJtYWMiOiI3MTQ2ODg0Yjk4YjhhNjg2Yzg1YjllZjdmMWMyNzVkY2ZmNGM1NjAzYWUyN2NlMmE0ZjAwOTAyNWMwNGI2YmM2In0%3D',
'upgrade-insecure-requests': '1',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'none',
'sec-fetch-user': '?1',
'sec-gpc': '1',
},
})
// Query the HTML for an input field named "_token".
const elem = response.html().find('input[name=_token]');
// Get the value of the attribute "value" and save it to a variable
const token = Elem.attr('value');
// Now you can concatenate this extracted value in subsequent requests that require it.
// console.log() works when executing k6 scripts locally and is handy for debugging purposes
console.log('The value of the hidden field is: ' + token);
check(response, {
list_OK: (r) => r.status === 200,
});
})
Second request - I want to use the token from the previous request to log in:
group('page_2 - http://localhost:81/customlogin', function () {
const url = 'http://localhost:81/customlogin';
const payload = JSON.stringify({
_token: `${token}`,
email: 'user',
password: '1234',
});
const params = {
headers: {
'Content-Type': 'application/json',
host: 'localhost:81',
'user-agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0',
accept:
'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'accept-language': 'en-US,en;q=0.5',
'accept-encoding': 'gzip, deflate, br',
'content-type': 'application/x-www-form-urlencoded',
origin: 'http://localhost:81',
connection: 'keep-alive',
referer: 'http://localhost:81/login',
cookie:
'XSRF-TOKEN=eyJpdiI6ImlnZFZCUGF1b1FYUlJOdTJHNDd2Vnc9PSIsInZhbHVlIjoiTXhhdnZyQzlPamRFQ21rajdQVEZXcThzWittZndqU2d1L0hyN1BmRTA2a2RBbEpYZUhIUlRpWjh1RWJoQ1Y5dWJoTWVnaXEzZ1NVTjBndG1tenUyN2phY1lMdkIxSzBGek5aYndlSmRxaEhVTGY4WkNCcE1UY3N6YmowUnkrTkciLCJtYWMiOiJlNDIxNjhkYTc1NjYxNTVkNWZhOWViZDYwMGU1ODRkNmQ2ZGU0NjgyMjU5NjIxMzQ0MjYyYzRjMmJkYTVmNjUwIn0%3D; dev_session=eyJpdiI6IndxWXpobW9BUm1GSHNVZkorN0N0OGc9PSIsInZhbHVlIjoiSE82by9aRnBXQjFkNG5JMHFkVzUzc3kraUZOYUdIdjNlUGN6a3c2SjBSZy9TaVNxNmRsWnQzMTltMGt0MGQvWUoxQndyQXFvd2theWViNU94Z2FXaXlGTkc4ZVdERGY2KzRpUUZDZDIxNG85UFhhanRiajBCWElmcmthMWE0R3IiLCJtYWMiOiJjMDllMmRmNGJjNDRlMjM2MmZmZTViOWEwZmUzNWQ3MzNjZDI1NWQwYmU3MjE4OTZiMTRhN2U0NWNkMTcxMDAzIn0%3D',
'upgrade-insecure-requests': '1',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'same-origin',
'sec-fetch-user': '?1',
'sec-gpc': '1',
},
};
response = http.post(url, payload, params);
console.log(response)
check(response, {
list_OK: (r) => r.status === 200,
});
})
After running the script I get an error message saying:
> ReferenceError: token is not defined
Thank you for your passionate help!
In this case you are defining a variable in the first call to group (const token ....` and then try to use it in the second call.
This has nothing to do with CSRF or k6, but with javascript ... and arguably scoping in most other languages.
But in order for both functions to see the same variable you will need to define it earlier - so for example next to your let response in the start of the default function.
Also remove const from the current definition as otherwise it won't work ;)
I am trying to pass a bearer token, to the fastify http server, in my headers.
I set the headers inside my request as:
...
const headers = {
Accept: 'application/json',
'Content-Type': 'application/json'
}
const token = localStorage.getItem('token')
if (token) {
headers['Authorization'] = `Bearer ${token}`
}
const newOptions = {
...options,
mode: 'no-cors',
headers
}
console.log('options:', newOptions)
return fetch(url, newOptions)
My console.log prints:
options: {
mode: "no-cors",
headers: {
Accept: "application/json",
Content-Type: "application/json",
Authorization: "Bearer NQ9xQLmYtq92aT8JHHRd7DGZJ..."
}
}
From the Chrome network tab, I look at the headers, and Authorization is just not present there. My route handler function is below:
async function user(server, options) {
server.route({
method: 'GET',
url: '/user/:email',
handler: async (req, res) => {
const username = req.params.email
console.log('user email:', username)
console.log('headers:', req.headers)
res.send({
type: 'promoter'
})
}
})
}
When I print headers on the server, it also does not have Authorization, showing:
headers: { host: 'localhost:5000',
connection: 'keep-alive',
pragma: 'no-cache',
'cache-control': 'no-cache',
accept: 'application/json',
'sec-fetch-dest': 'empty',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36',
'sec-fetch-site': 'same-site',
'sec-fetch-mode': 'no-cors',
referer: 'http://localhost:3000/admin',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9,ru;q=0.8' }
What am I missing?
Another interesting issue is that when I run the request from Postman it shows 200 response code, and fastify prints 200 to the log. However, running from the saga/request with:
return fetch(url, newOptions)
.then(checkStatus)
.then(parseJSON)
I get response.status of 0 instead of 200 inside the request method, while the server log still shows "res":{"statusCode":200}.
I figured out what was the problem.
Apparently, my version of Chrome - Version 80.0.3987.106 (Official Build) (64-bit) and possibly other browsers and older versions of Chrome, as well, strip the authorization header, when it is used in conjunction with the no-cors mode. Enabling CORS and setting the appropriate headers solves the problem.
Try adding withCredentials: true and credentials: 'include' to your options:
options: {
mode: "no-cors",
withCredentials: true, // <-- ADD THIS
credentials: 'include', // <-- AND THIS
headers: {
Accept: "application/json",
Content-Type: "application/json",
Authorization: "Bearer NQ9xQLmYtq92aT8JHHRd7DGZJ..."
}
}
Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
I'm trying to make a request in angularjs to retrieve an access token, but I'm not 100% sure how to go about it. Here's the request in curl
curl -X POST -d
"grant_type=password&username=&password=&scope=read"
-u":" http://localhost:8000/o/token/
any and all help is appreciated
I think you need to post with query string parameters
To do that you need to make some modifications in your post request
var request = $http({
method: "POST",
url: "",
transformRequest: transformRequestAsFormPost,
data: {
grant_type: "password",
username: "Kim",
password: "123",
scope: "read"
}
});
Here is explanation in more details https://www.bennadel.com/blog/2615-posting-form-data-with-http-in-angularjs.htm
I figured it out
var data = "grant_type=password" + "&username="+cred.username + "&password="+cred.password +
"&client_id=" + cred.client_id +
"&client_secret=" + cred.client_secret;
$http({
method: 'POST',
url: 'BaseUrl',
data: data,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
I need your help, dunno no how to solve it, I'm using MEAN stack for simple app, that has a field with input tag inside and when i fill it the data is sending to server and save in db, the problem is that post request cant reach the server.
heres is my post:
$http({
method: 'POST',
url: 'http://localhost:3000/api/message',
headers: {'Content-Type': 'application/json'},
data: JSON.stringify({msg: $scope.message})
}).
success(function(response) {
console.log("Success " + JSON.stringify(response));
}).
error(function(response) {
console.log("Error " + JSON.stringify(response));
});
server side:
app.post('/api/message', function(req,res) {
var message = new Message(req.body);
message.save();
res.status(200);
})
app.get('/api/message', function(req,res) {
Message.find(function(err,message) {
if(err) {
res.send(err);
} else {
res.json(message);
}
})
})
and this is what i get in browser dev tool
Request URL:http://localhost:3000/api/message
Request Headers
!Provisional headers are shown
Accept:application/json, text/plain, */*
Content-Type:application/json
Origin:http://localhost:3000
Referer:http://localhost:3000/?
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
Request Payload
view source
{msg: "3232"}
msg:"3232"
Following could be the issue
actual request is not being sent from the code or browser is using cached data
some adBlocker or some extension is blocking the request
try removing http://localhost:3000 from the url
i'v got weird behaviour of my code. I'm using Satellizer to authenticate user and when user is not authenticated when i execute this code:
$http.get('http://eune.api.pvp.net/api/lol/eune/v1.4/summoner/by-name/somename?api_key=XXXXXXXXXXXXXXXXX')
.success(function (data) {
console.log(data);
});
my request is ok and i get data
headers:
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Host:eune.api.pvp.net
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36
but when i authenticate user and try to do same request i get:
XMLHttpRequest cannot load http://eune.api.pvp.net/api/lol/eune/v1.4/summoner/by-name/somename?api_key=XXXXXXXXXXXX. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 401.
and headers of this request looks like:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:accept, authorization
Access-Control-Request-Method:GET
Connection:keep-alive
Host:eune.api.pvp.net
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36
my app.config
.config(function ($urlRouterProvider, $stateProvider, $httpProvider, $authProvider, API_URL) {
$urlRouterProvider.otherwise('/');
... some routes ...
$authProvider.loginUrl = API_URL + 'login';
$authProvider.signupUrl = API_URL + 'register';
$authProvider.google({
clientId: 'secret',
url: API_URL + 'auth/google'
});
$authProvider.facebook({
clientId: 'secret',
url: API_URL + 'auth/facebook'
});
// $httpProvider.interceptors.push('authInterceptor');
})
So how should i fix it? I suppose that those headers with Access-Control are the reason, but how should i handle it?
You could try putting the following in the satellizer config:
$authProvider.httpInterceptor = false;
Adding skipAuthorization property in config block might be helpful:
$http.get('http://eune.api.pvp.net/api/lol/eune/v1.4/summoner/by-name/somename?api_key=XXXXXXXXXXXXXXXXX', {
skipAuthorization: true
})
.success(function (data) {
console.log(data);
});
I usually work with the config block by preference. This is how it would look.
//configuration block method:
$http({
method: 'GET',
url: 'http://eune.api.pvp.net/api/lol/eune/v1.4/summoner/by-name/somename?api_key=XXXXXXXXXXXXXXXXX',
skipAuthorization: true
});
Good Luck.
Ok i figured it out. As i supposed Satellizer registers new interceptor, which adds some headers and that's why it doesn`t work. This is satellizer code :
.config(['$httpProvider', 'satellizer.config', function($httpProvider, config) {
$httpProvider.interceptors.push(['$q', function($q) {
var tokenName = config.tokenPrefix ? config.tokenPrefix + '_' + config.tokenName : config.tokenName;
return {
request: function(httpConfig) {
var token = localStorage.getItem(tokenName);
if (token && config.httpInterceptor) {
token = config.authHeader === 'Authorization' ? 'Bearer ' + token : token;
httpConfig.headers[config.authHeader] = token;
}
return httpConfig;
},
responseError: function(response) {
return $q.reject(response);
}
};
}]);
}]);
i handled it by changing one lane to this:
if (token && config.httpInterceptor && httpConfig.rawReq !== true) {
and i pass in my httpConfig option rawReq: true
but this is not nice. Is there posibility to disable specific interceptor ?