I would like to do a token request from angular like below:
http --auth <email>:<password> --json GET http://127.0.0.1:5000/api/v1.0/token
the above is httpie, description below:
--auth, -a Pass a username:password pair as the argument. Or, if you only specify a username (-a username), you’ll be prompted for the password before the request is sent. To send a an empty password, pass username:. The username:password#hostname URL syntax is supported as well (but credentials passed via -a have higher priority).
--auth-type Specify the auth mechanism. Possible values are basic and digest. The default value is basic so it can often be omitted.
here is the output of the above command:
root#localhost:/var/www/myapp# http --auth myname#email.com:thepassword --json GET http://127.0.0.1:5000/api/v1.0/token
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 159
Content-Type: application/json
Date: Wed, 25 Nov 2015 03:13:16 GMT
Server: nginx/1.4.6 (Ubuntu)
Set-Cookie:session=eyJfaWQiOnsiIGIiOiJOR000TkdGak1UQTFabUppTldNeE1HVTBZemt3TjJWaU1EVmpNemN4WkdZPSJ9fQ.CTa4zA.YoXlQf5H68q3lRzuAEmEQ5kRm_I; HttpOnly; Path=/
{
"expiration": 0,
"token": "eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ0ODQyNDc5NiwiaWF0IjoxNDQ4NDIxMTk2fQ.eyJpZCI6MX0.NY5hSBVjeddctBVvlM1cDJw2A9Yv38om5cqyBQUQhgU"
}
below is the code i have on angularjs:
$scope.login = function() {
var config = {
method: 'GET',
url: '/api/v1.0/token',
headers: {'auth':'myname#email.com:thepassword'}
};
$http(config)
.success(function(data, status, headers, config) {
if (data.status) {
//logged in
}
else {
//failed
}
})
.error(function(data, status, headers, config) {
//failed
});
}
i hard-coded with the email and password to the code, so when i click on the button, it should use the email/password to get the token from the server with the correct output like above, but instead, i got this:
Failed to load resource: the server responded with a status of 401 (UNAUTHORIZED)
I don't know what went wrong, please correct me if i missed anything.
Thanks.
Related
I have an API on AWS API Gateway that takes a POST request and forwards headers and body to a third party API and returns the result. This process works fine when I send the request from Postman, but doesn't work either via cURL or JavaScript.
NB - all URIs, auth tokens etc below are modified so may be inconsistent between screengrabs.
The request in Postman is below
Postman console for this looks like
POST https://dsvdvsdvsdrc.execute-api.eu-west-1.amazonaws.com/Prod/
200
957 ms
Network
Request Headers
Authorization: Basic <myauthtoken>NTAwYTQxNDdmYzcyLWFkZDgtNDZmMy05ZWU0LWQzYWM=
Content-Type: application/x-www-form-urlencoded
User-Agent: PostmanRuntime/7.26.8
Accept: */*
Cache-Control: no-cache
Postman-Token: 9dab6f01-67bf-4611-8d8e-c3d5fe725067
Host: tsfsfsdrc.execute-api.eu-west-1.amazonaws.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 82
Request Body
grant_type: "client_credentials"
scope: "https://api.ebay.com/oauth/api_scope"
In my JavaScript app I have the following code:
var data = qs.stringify({
'grant_type': 'client_credentials',
'scope': 'https://api.ebay.com/oauth/api_scope'
});
var config = {
method: 'post',
url: 'https://fddgdgddrc.execute-api.eu-west-1.amazonaws.com/Prod/',
headers: {
'Authorization': 'Basic sssscyLWFkZDgtNDZmMy05ZWU0LWQzYWM=',
'Content-Type': 'application/x-www-form-urlencoded'
},
data : data
};
console.log("******Here is ebayData REQUEST***** "+ JSON.stringify(config));
axios(config)
.then(function (response) {
console.log("******Here is ebayData***** "+ JSON.stringify(response.data));
})
.catch(function (error) {
console.log( "******Here is ebay Error***** "+ error);
});
However when the application runs I get a 500 response. Below are the request headers and body that is being sent in the request
I've enabled cloudwatch logs on the API and below is an example of a successful request via Postman
and here is an example of an unsuccessful request from the browser
Looking further into the response headers for a failed and a successful response I see the headers with comments against them are different
Failed request
(d360923b-eff2-433f-8f76-a9038547dcdf) Endpoint response headers: {rlogid=t6ldssk67%3D9whhldssk67*qc1qr%28rbpv6710-17dd35648ce-0x129,
x-ebay-c-version=1.0.0,
x-frame-options=SAMEORIGIN,
x-content-type-options=nosniff,
x-xss-protection=1; mode=block,
set-cookie=ebay=%5Esbf%3D%23%5E;Domain=.ebay.com;Path=/; Secure,dp1=bu1p/QEBfX0BAX19AQA**6581b87b^;Domain=.ebay.com;Expires=Tue, 19-Dec-2023 15:36:27 GMT;Path=/; Secure,
content-encoding=gzip,
cache-control=private, <--- doesn't appear in successful response
pragma=no-cache, <--- doesn't appear in successful response
date=Sun, 19 Dec 2021 15:36:26 GMT,
server=ebay-proxy-server,
x-envoy-upstream-service-time=19,
x-ebay-pop-id=UFES2-RNOAZ03-api,
transfer-encoding=chunked}
Successful request
(fe565553-3283-4593-8b07-b4e2d58dd2a6) Endpoint response headers: {rlogid=t6ldssk67%3D9vjdldssk67*5cddm%28rbpv6775-17dd23fa53c-0x124,
x-ebay-c-version=1.0.0,
x-ebay-client-tls-version=TLSv1.2,<--- doesn't appear in failed response
x-frame-options=SAMEORIGIN,
x-content-type-options=nosniff,
x-xss-protection=1; mode=block,
set-cookie=ebay=%5Esbf%3D%23%5E;Domain=.ebay.com;Path=/; Secure,dp1=bu1p/QEBfX0BAX19AQA**65817126^;Domain=.ebay.com;Expires=Tue, 19-Dec-2023 10:32:06 GMT;Path=/; Secure,
content-encoding=gzip,
content-type=application/json,<--- doesn't appear in failed response
date=Sun, 19 Dec 2021 10:32:06 GMT,
server=ebay-proxy-server,
x-envoy-upstream-service-time=96,
x-ebay-pop-id=UFES2-SLCAZ01-api,
transfer-encoding=chunked}
I think I've been looking at this for too long and am probably missing something obvious, but headers and body etc all seem to be consistent across the app and Postman, so I'm confused why the request from one is successful and the other is failing. Any advice much appreciated.
Add all other headers as in Postman , some application rejects requests without proper user-agent header or some other required headers.
I have written a REST service that deals with errors like this:
return Response.status(vr.responseStatus).entity("Oh No")
.type(MediaType.APPLICATION_JSON).build();
On the client side, I have called this:
var request = $http({
method: "put",
url: serviceProvidersURL,
params: {
//action: "add"
},
data: item
});
return( request
.then( handleSuccess,
function(response){
alert("Here1: " + response);
alert("Here2") + JSON.stringify(response);
})
);
Both the alerts are failing to deal with the response. In the first alert, I get "Here1: SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data" and the second alert, I just get "Here2"
If I look at the response in firebug, the "Oh No!" is in the response section and these are the headers:
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 08 Jun 2016 06:49:57 GMT
Connection: close
The Oh No! is definitely in the response body - I have no idea how to get to it through the client side.
Thanks
I have an angularjs HTML client to a WebApi project. When I test the APIs via POSTMAN or other REST Client, it seems that everything is ok.
When I start using browsers with my angularjs client, browsers always start preflight requests with OPTIONS. There, my WebAPI always answers 400 Bad Request - I am still on a "/api/token" phase.
I have already attached every single point of my WebAPI project to the debugger. I have also changed several points according to several answers here in SO on how to enable CORS. Some of them I have already tried: changing web.config to add headers enabling cors on every request, adding cors to WebApi startup, enabling cors at "/token" overridden functions.
Here is what I got so for:
Angularjs TypeScript call to "/api/token":
logIn = (userName: string, userPassword: string): ng.IPromise<void> => {
var postData = {
"grant_type": "password",
"client_id": this.appConfiguration.ClientId,
"client_secret": this.appConfiguration.ClientSecret,
"username": userName,
"password": userPassword
};
return this.$http.post<models.LoggedUserModel>('http://local.web.api/api/token', $.param(postData), {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then((result) => {
this.localStorageService.set('Auth', result);
this.goHome(true);
}).catch((error) => {
console.warn(error);
});
}
Here is the only function that is called on my WebApi:
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// handle cors requests
if (!string.IsNullOrEmpty(context.OwinContext.Request.Headers.Get("Origin")))
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new string[] { "*" });
}
try
{
// retrieve clientId and clientSecret from request body
string clientId;
string clientSecret;
if (context.TryGetFormCredentials(out clientId, out clientSecret))
{
// here it comes our application specific security code....
}
else
{
// this is part of enabling CORS..
if (context.Request.Method.ToUpper() == "OPTIONS")
{
// it returns OK to preflight requests having an empty body
context.Validated();
}
}
}
finally
{
// log stuff...
}
}
If I just left OWIN Cors stuff, adding headers and calling ´context.Validated()´ it all continues the same. Here is what I get:
Firefox Network Tab:
--------------------
Request URL: http://local.web.api/api/token
Request method: OPTIONS
Remote address: 127.0.0.1:80
Status code: 400 Bad Request
Version: HTTP/1.1
Request headers:
----------------
Host: local.web.api
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.7,pt-BR;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization
Origin: http://local.web.client
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Response headers:
-----------------
Access-Control-Allow-Origin: *
Cache-Control: no-cache
Content-Length: 34
Content-Type: application/json;charset=UTF-8
Date: Tue, 22 Dec 2015 15:24:23 GMT
Expires: -1
Pragma: no-cache
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
I would really appreciate some ideas of where to got.
This is brand new to me, and I do operate some other WebApi projects + angularjs.
Ok, that's is terrible but I found the issue.
I am using a http interceptor on angularjs that would automatically check for a logged user and add an Authorization header with the Bearer token when needed. Problem is I was doing it wrongly.
I created a new property in the config object, bypassToken as boolean, that would be the flag to add or not the Authorization header. Removing this actually fixed the code. Not sure why, but analyzing the request now I can see that all headers are actually sending as expected: with the Content-Type which was not being filled on the first case correctly. Weird though no warning was thrown by angularjs.
// http auth interceptor
angularApplication.factory('httpAuthInterceptor', ['$rootScope', '$injector', '$location', ($rootScope, $injector, $location): ng.IHttpInterceptor => {
var $q: ng.IQService = $injector.get('$q');
var localStorageService: ng.local.storage.ILocalStorageService = $injector.get('localStorageService');
return {
request: (config: ng.IRequestConfig): ng.IRequestConfig => {
// check if headers are present
config.headers = config.headers || {};
// the error was here! I was trying to add properties to config that I think angular was not expecting
// removing this line solved the issue
// if (!config.bypassToken) {
// check if user is logged in
var loggedUserInfo = localStorageService.get<models.LoggedUserInfoModel>('Auth');
if (loggedUserInfo) {
config.headers['Authorization'] = 'Bearer ' + loggedUserInfo.access_token;
}
return config;
},
responseError: (rejection) => {
// check if user is logged in
var loggedUserInfo = localStorageService.get<models.LoggedUserInfoModel>('Auth');
if ((rejection.status === 401) && (loggedUserInfo)) {
// if so, then the user must login againd
localStorageService.remove('Auth');
$location.path('/home');
console.error(rejection);
}
return $q.reject(rejection);
}
};
}]);
I appreciate your help.
I am only posting this here in case someone faces a similar issue.
Don't mess with the config object!
I am making an authentication system based on tokens. When a user logs in a token sent back and this then submitted with each call to the server
Assigning a token
.factory('AuthenticationService', function($rootScope, $http, authService, $httpBackend) {
var service = {
login: function(user) {
$http.post('http://192.168.100.100/myApp/login', { user: user }, { ignoreAuthModule: true })
.success(function (data, status, headers, config) {
$http.defaults.headers.common.Authorization = data.authorizationToken;
console.log("token:" + data.authorizationToken);
authService.loginConfirmed(data, function(config) {
config.headers.Authorization = data.authorizationToken;
return config;
});
})
After this is executed calls are sent as OPTIONS rather than POST the problem being that I am sending to RESTful server and OPTIONS isn't ahhh ummm an option. i.e server expects POST, GET etc.
Chrome shows my headers as ..
General
**Remote Address:** 192.168.100.100:80
**Request URL:** http://192.168.100.100/myapp/login
**Request Method:** OPTIONS
**Status Code:** 404 Not Found
Response Headers
**Access-Control-Allow-Origin:** *
**Cache-Control:** no-cache, must-revalidate
**Connection:** Keep-Alive
**Content-Encoding:** gzip
**Content-Length:** 563
**Content-Type:** text/plain
**Date:** Tue, 04 Aug 2015 04:29:14 GMT
**Expires:** 0
**Keep-Alive:** timeout=5, max=100
**Server:** Apache/2.2.22 (Debian)
**Vary:** Accept-Encoding
**X-Powered-By:** PHP/5.4.41-0+deb7u1
Request Headers
OPTIONS /myapp/login HTTP/1.1
**Host:** 192.168.100.100
**Connection:** keep-alive
**Access-Control-Request-Method:** POST
**Origin:** null
**User-Agent:** Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
**Access-Control-Request-Headers:** authorization, content-type
**Accept:** */*
**Accept-Encoding:** gzip, deflate, sdch
**Accept-Language:** en-US,en;q=0.8
Will it always be OPTIONS and do I have to alter my RESTful server to accomodate this, should I not be able to see the token in the headers?
This is an preflight request to check if CORS are enaabled or not
During the preflight request, you should see the following two headers: Access-Control-Request-Method and Access-Control-Request-Headers. These request headers are asking the server for permissions to make the actual request. Your preflight response needs to acknowledge these headers in order for the actual request to work.
Shortly. You need to enable these headers at you server for actual request to work
Can you please check if CORS is enabled? if yes please try to handle OPTIONS request like this
if (req.method === 'OPTIONS') {
console.log('!OPTIONS');
var headers = {};
// IE8 does not allow domains to be specified, just the *
// headers["Access-Control-Allow-Origin"] = req.headers.origin;
headers["Access-Control-Allow-Origin"] = "*";
headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
headers["Access-Control-Allow-Credentials"] = false;
headers["Access-Control-Max-Age"] = '86400'; // 24 hours
headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept";
res.writeHead(200, headers);
res.end();
}
I am learning Angular JS and am facing an issue with an the HTTP Get Request. Here is my code:
function countryController($scope,$http) {
delete $http.defaults.headers.common['X-Requested-With'];
$http.get("http://localhost:8080/countrybook/api/v1/countrybook")
.success(function(response) {
$scope.countries = response;
})
.error(function(response){
alert(response);
});
}
I get a blank error response (alert with nothing in it. when i debug in firebug i see that response is "") for some reason.
My headers look like this:
Response Headers:
Cache-Control private, must-revalidate
Content-Length 355
Content-Type application/javascript
Date Sat, 15 Nov 2014 16:53:52 GMT
Last-Modified Sat, 15 Nov 2014 16:52:06 GMT
Server WebStorm 9.0.1
Request Headers:
Accept */*
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Cache-Control max-age=0
Connection keep-alive
Host localhost:63342
If-Modified-Since Sat, 15 Nov 2014 16:52:06 GMT
Referer http://localhost:63342/CountryBook/index.html
User-Agent Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
and the Response that I see in Firebug is this:
function countryController($scope,$http) {
delete $http.defaults.headers.common['X-Requested-With'];
$http.get("http://localhost:8080/countrybook/api/v1/countrybook")
.success(function(response) {
$scope.countries = response;
})
.error(function(response){
alert(response);
});
}
Could you please help me figure out whats wrong? When I use the same link mentioned above in the http get request directly from the browser I see the response that I expect. Thanks for your help!
The problem was:
The Same Origin Policy disallows reading the remote resource at localhost:8080/countrybook/api/v1/countrybook. This can be fixed by moving the resource to the same domain or enabling CORS.
Solved it by adding these two headers at the server side response:
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
Smartbart24 - looking at the console logs helped. Thanks for your help!
So without knowing your backend my general $http pattern is:
$http.get(requestEndpointString)
.success(function(data,status,headers,config){
if(status!=200){
/*unexpected response status ...*/
console.log('API error status: '+status);
}else{
/* Success ... */
}
})
.error(function(data, status, headers, config){
/* Handle errors */
});
Maybe it helps you to debug with logging the response status ?
Also try to take out the line:
delete $http.defaults.headers.common['X-Requested-With'];