AngularJS $cookies, getting undefined - angularjs

I'm trying to retrieve Cookies using the $cookies service provided by ngCookies but I keep getting 'undefined', I really don't know what it's wrong...
I can clearly see the cookie displayed in the Dev Console in Chrome.
AND I also set a XSRF-TOKEN cookie and Angular's $http is NOT including it as a Header (X-XSRF-TOKEN) which I think it's the same problem.
Laravel by default encrypts Cookies and are extremely long, could that be it?
If I set a cookie with the $cookies service, it appears and I can retrieve it withou issue, so the $cookies service is working.... :P
angular.module("MachinatorApp.Services.SectionService", [])
.factory("SectionService", ["$http", "$cookies", function($http, $cookies) {
console.log($cookies.laravel_session);
var doRequest = function(action, id) {
var params = $.param({
"action" : action,
"id" : id
});
return $http({
method : 'POST',
url : "/Sections/" + action,
data : params,
headers : {'Content-Type': 'application/x-www-form-urlencoded'}
});
}
return {
sections: function(action, id) {
return doRequest(action, id);
}
}
}]);

I found out what the solution was by looking a the Laravel API Documentation, Cooke::make() by default sends a HttpOnly cookie, that's why I could not read it from Angular, Adding false to the httpOnly parameter fixes the issue, Although Now I think it's just safer to leave it http only and read from the header's cookies.
http://laravel.com/api/4.1/
search for Cookie, click CookieJar, make method
Cookie::make("XSRF-TOKEN", Session::token(), 0, null, null, null, false))
This sends a NON HTTP ONLY Cookie which you can read from angularJS

Related

Can not get response cookie from angular $http post using ionic

I am sending a post auth request from my localhost to a remote server to get response cookies returned by server(using ionic proxy to solve CORS). From chrome network inspector, I can see the response cookie has been returned from server. However, I am not able to access it from $http post response. I try almost everything from other posts and I still can not get the cookie. What I have tried
I use ngCookie and $timeout combination. Basically I get an empty object when I use $cookie.getAll() which I assume the cookie is not there
I also set withCredentials to true
I also tried headers.get('set-cookie')
My angular version is 1.5.3. Please help
Below is my code
angular.module('starter.controllers', ['ngCookies'])
.controller('DashCtrl', function($scope, $http, $cookies, $timeout) {
$http({
method: 'POST',
url: '/api/User/Authenticate',
data: {
Username: 'xxx',
Password: 'xxx'
},
withCredentials: true
}).then(function(response) {
$timeout(function() {
console.log($cookies); // return {}
console.log($cookies.getAll()); // return {}
});
}, function(response) {
});
})
Here is the server response

can't access cookies on a rest response in angular

I have an angular front end with a webapi back end. I have implemented OAuth v2 security using OWIN/Identity and JWT tokens (thanks to Taiseer Joudeh's blogs). My burden is that we still have legacy pages that require a specific cookie. I have augmented the Http Response from WebApi to include that cookie when the JWT token is returned from a login request. I have verified the cookie is in the response header.
My problem is that I am unable to see the cookie inside my angular response handler where I will push it to the browser. I have tried each of the following based on suggestions I found elsewhere within StackOverflow but so far visibility of the cookie within the .js code has eluded me (alternate attempts have been commented out but left in for completeness). I have also made sure I set the appropriate "allow" fields on the server by adding "Access-Control-Allow-Headers" to "set-cookie" and "Access-Control-Allow-Credentials" to "true" at the end of my ValidateClientAuthenticationContext(..) method.
What do I need to do to see the attached cookie on my webapi response? Is this a problem on the server or client? both?
in my authService.js file:
var _login = function (loginData) {
// this makes the data "form data"
var data = "grant_type=password&client_id=ngAuthApp&username=" + loginData.userName + "&password=" + loginData.password;
var deferred = $q.defer();
$http.post(serviceBase + 'oauth/token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
.success(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
console.log($cookies);
//var xxx = $http.defaults.headers;
//var headers = $http.response.headers;
var ddc = $http.response.cookies;
$cookies.DDC = ddc;
deferred.resolve(response);
})
//.success(function (data, status, headers, config) {
// // any required additional processing here
// var results = [];
// results.data = data;
// results.headers = headers();
// results.status = status;
// results.config = config;
// deferred.resolve(results);
//})
.error(function (err, status) {
_logOut();
deferred.reject(err);
});
return deferred.promise;
};
in my custom OAuthProvider .cs file
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// skipping over lots of code here
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "authorization", "content-type", "set-cookie" });
context.Validated();
return Task.FromResult<object>(null);
}
According to the docs - see here
$http.post() method returns an HttpPromise future object. Your call to .post() returns a promise. Which according to the Deprecation Notice on the above referenced page :
The $http legacy promise methods success and error have been
deprecated. Use the standard then method instead. If
$httpProvider.useLegacyPromiseExtensions is set to false then these
methods will throw $http/legacy error.
So instead of .success() / error(), use this: (Copied from docs)
$http.post()
.then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Also, if you haven't already tried this (according to the .post() call it doesn't appear to) set the responseType property of your $http configuration object. This sets the datatype of the response object returned. Otherwise the default of a DOM string is returned. It may not fix it but it could be a start.
This could also need the help of withCredentials property set. Test them out and see how it goes. Idea comes from the suggestion of bastijn.
Your $http call should also set the withCredentials flag to true to explicitly allow cookie sharing.
$http.post(url, {withCredentials: true, ...})
The withCredentials flag allows javascript to access the authenticated session of the user.
//edit
Now that I read your question again this is probably not your issue. The withCredentials is to,communicate your session to the server on the next request you make that requires the authenticated session. From your question it seems you want to validate in the js code that the cookie you verified is there is also reachable by code.
It turns out the error was in my assumptions. I expected that a cookie sent via a web service directly from embedded js code would be ignored by the browser. However, the response header has the "Set-Cookie" value in the header and the browser IS already pushing it to be with the rest of the cookies. I really didn't expect that.
I must add this has been a very useful question for me because it taught me a lot about web programming and how the browser works with http header values. I appreciate everyone's time!
Marcus

API-key header is not sent (or recognized). Angularjs

I'm trying to access an API with AngularJS but I get the following error:
XMLHttpRequest cannot load http://www.football-data.org/alpha/soccerseasons/398/leagueTable?callback=JSON_CALLBACK. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://purepremier.com' is therefore not allowed access.
This is my code for the service:
angular.module('PremierLeagueApp.services', []).
factory('footballdataAPIservice', function($http) {
var footballdataAPI = {};
footballdataAPI.getTeams = function() {
$http.defaults.headers.common['Auth-Token'] = 'token';
return $http.get('http://www.football-data.org/alpha/soccerseasons/398/leagueTable?callback=JSON_CALLBACK');
};
return footballdataAPI;
});
I use an authentication token (api key) to access the api, but according the API owner this API key header is not sent or recognized. Do you have any idea how I can adapt the code to make this work? thanks!
You should hide that API key before posting on a public site such as this. I would advise you regenerate your key (if possible) just in case - better safe than sorry.
Assuming your site url is 'http://purepremier.com' from the error message, the API should add a 'Access-Control-Allow-Origin' header with your site URL to allow you access. Have a look here for more information.
This is not directly related to your problem, but I notice you are setting $http defaults every time getTeams() is called. You should either set this outside of the actual function call (preferably in a run block), or just send the GET request with that header specifically applied. As the API key is specific (I assume) to that call, you may not want to be sending it to anyone and everyone, every time you make a HTTP request.
Change your factory code like this:
factory('footballdataAPIservice', function($http) {
return {
getTeams: function(){
return $http({
url:'http://www.football-data.org/alpha/soccerseasons/398/leagueTable',
headers: { 'X-Auth-Token': 'your_token' },
method: 'GET'
}).success(function(data){
return data;
});
}
}
});
Inject factory in your controller and retreive the data:
.controller('someController',function(footballdataAPIservice,$scope){
footballdataAPIservice.getTeams().then(function(data){
$scope.teams=data;
console.log($scope.teams)
});
});
Here is the working plunker
You change the Auth-Token To Authorization
$http.defaults.headers.common['Authorization'] = 'token';
Because token is send via headers using Authorization
try jsonp
angular.module('PremierLeagueApp.services', []).
factory('footballdataAPIservice', function($http) {
var footballdataAPI = {};
footballdataAPI.getTeams = function() {
$http.defaults.headers.common['Auth-Token'] = 'token';
return $http.jsonp('http://www.football-data.org/alpha/soccerseasons/398/leagueTable?callback=JSON_CALLBACK');
};
return footballdataAPI;
});

How can i set default param in ngResource to be POST

I have a simple AJAX request that needs a csrf token for every call and i define it like so:
app.factory('auth', ['$resource', '$cookies', function($resource, $cookies){
var getCsrf = function() {
//get csrf token from cookie
};
return {
login: $resource('auth/login', {}, {
'q' : {
method: 'POST',
params: {csrf_token: getCsrf()}
}
}),
// ... some more requests
};
}]);
As i understood it you can specify the default url parameters as second param of the $resource()-call, in my case the empty object {}. Apparently the data i set in the configurations object under params: ... also gets send via GET and not with the specified POST-method.
One way would be to manually put the csrf_token in where i make the call to the api-function, but i'd like to keep it clean. Is there a way to tell angular what method to use for the default params? So i could simply use ..
auth.login.q(email, password, ...).then( ... );
.. without having to implement the csrf-getter function into all my calls. Also i am relatively new to AngularJS so a simple answer would be great!
There is an easy way to this in angular:
set the xsrf cookie name and header name defaults in the config module.
app.config(['$httpProvider', function($httpProvider) {
// response cookie name
$httpProvider.defaults.xsrfCookieName = 'csrf_cookie';
// request header name where the value of the cookie get set
$httpProvider.defaults.xsrfHeaderName = 'HTTP_X_XSRF_TOKEN';
// to set ajax request header
$httpProvider.defaults.headers.common = { 'X-Requested-With' : 'XMLHttpRequest'};
}

AngularJS POST with $resource sending in query string, what am I doing wrong?

I'm a bit of a noob with Angular and am having issues trying to post to a Drupal Services endpoint. I can post just fine with HttpRequester (FFox plugin), however all my attempts with Angular to post data to get a session result in 401 Unauthorized: missing required argument username or other errors.
Here is my testing factory resource with default input:
userInfoApp.factory('LoginService', function($resource) {
return $resource('/auth-service/user/login', {username: 'admin', password: 'admin'}, {
update: {
method: 'POST', // this method issues a POST request
headers:{'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'}
}
});
});
Here is the call I am making to it inside the controller (this):
this.login = function() {
var login = LoginService.update(function(data) {
console.log(data);
});
};
So far this usually results in a query string generated like so:
http://project.loc/auth-service/user/login?password=admin&username=admin
and the response of:
401 Unauthorized : Missing required argument username
What might I be doing wrong here? I have gotten $resource to work just fine with other endpoints (like for a menu service to retrieve a menu) however posting seems to be much more finicky. Any suggestions would be appreciated.
Thanks
Your current configuration for $resource sends username & password as querystring. Hence they appear in your URL. I assume you need these values to be POST.
According to documentations all non GET methods have a payload parameter in the action method:
non-GET "class" actions: Resource.action([parameters], postData,
[success], [error])
What you need to do is stop sending the parameters as default [parameters] and make use of the postData to POST data to your Drupal Services endpoint. You could do this when you call $update() as:
LoginService.update({}, {username: "admin",password: "admin"});
Ok, I found a way that works; for the controller function:
this.login = function() {
var data = {
username: this.username,
password: this.password
};
var login = LoginService.save({}, data,
function(data) {
// possibly do stuff with result
},
function(reply) {
// Comments on best way to access $scope here are welcome.
// This feels a bit weird to me.
$scope.info.errorMessage = reply.statusText;
}
);
};
And for the factory service:
// Login factory service
userInfoApp.factory('LoginService', function($resource) {
return $resource('/auth-service/user/login');
});
This actually retrieves the session id and other user data from the server.

Resources