AngularJS - calling a webservice with authentication - angularjs

I am making a web service call using -
$http.get(url)
Note -
1) I am dynamically creating the url with query strings.
2) When i type the url in the address bar, it asks for login credentials.
Question -
1) How to add the login credentials in the url, while i am creating it dynamically? I know this is a not a good idea, is there a better way to deal with this situation?
2) I am getting the data from the $http call. Is it because i have logged in once before and the same session is continuing?

Is it standard HTTP credentials? If so, you can use the config flag
withCredentials - {boolean} - whether to set the withCredentials flag on the XHR object. See requests with credentials for more information.
Your service:
app.service('myService', ['$http', function($http){
var service = {};
service.getUrlWithCredentials = function(url){
return $http(url,
{
withCredentials : true
}
}
return serivce;
}])
Taken from:
https://docs.angularjs.org/api/ng/service/$http

Related

maintaining session from server application in angularjs

I have an angularjs application, in this application I have a login form when I submit it I call a rest service to authenticate the user to my server application, as following :
$http.get('http://localhost:8080/user', {
headers : credentials ? {
authorization : "Basic "
+ btoa(credentials.username + ":"
+ credentials.password)
} : {};
}).then(function(response) {
if (response.data.name) {
$rootScope.authenticated = true;
$rootScope.username=response.data.name;
$rootScope.roles=response.data.authorities;
$rootScope.sessionid=response.data.details.sessionId;
} else {
$rootScope.authenticated = false;
}
}, function() {
$rootScope.authenticated = false;
});
So the $rootScope will have all the informations about the authenticated user, but when I refresh my application, all those informations I attached to $rootScope are removed.
Notice that http://localhost:8080/user will always maintain the session.
How can I solve that ?
You can either store it in sessionStorage or just get the current user logged from server side. Then in order to retrieve them use an angular.run
angular.run(...function($http, $rootScope){
// either use session storage or $http to retrieve your data and store them in $rootScope.
// if you use $http i suggest you to store the promise of $http to be sure in your controller/route to wait that it has been resolved.
});
The fact that you're loosing what you store when using f5 is normal, you lose all javascript context when doing so. The usage of angular.run permit to use the request before any controller is called However with $http you may need to wait the end of the promise. So it's better to have a reference to the promise store in $rootScope to be able to use it in the javascript part. You can reference directly the data in the templates as they will get refresh as soon they will be loaded.
Check for Local and Session storage service. You can easily attach informations to variables with getters and setters, and retrieving them through page refreshing.
Example: You can set a variable like this:
localStorageService.set('myVar', data);
And then retrieve it in another controller, after refreshing, or elsewhere in your application with:
localStorageService.get('myVar');
It is rather well documented and easy to use.

AngularJS : How to encode decode JSON data in Services

I have used CakePHP + AngularJS for the application
I have below code in Sevices file
test.factory('Dashboard', function ($http, $q) {
return {
userDirectory: function (){
return $http.get(hostName + 'dashboards/userDirectory.json');
}
}
});
The above code calls dashboards's controllers userDirectory function and return JSON data this is how it's work.
Some one raised one issue, When he hit url "http://hostname/dashboards/userDirectory.json" he can see the response data in browser and that is not authenticated. Is there any way through which I can secure it.
By any encoding/decoding or What you prefer.
Decode/encode doesn't make any sense here if the client can decode it the user can get the data as well.
Just send data the user is allowed to see and use, even if he is authorized for that request, remove everything else that is not needed.
Use a JWT token to authorize them
https://github.com/ADmad/cakephp-jwt-auth
http://www.bravo-kernel.com/2015/04/how-to-add-jwt-authentication-to-a-cakephp-3-rest-api/
http://florian-kraemer.net/2014/07/cakephp-and-token-based-auth-with-angular-js/

Angular Jhipster - How to send x-csrf token in all http requests?

I generate an app from hipster generator and create a new factory to call my services.
All the existing services are called with x-csrf token in the headers but when i try to make a Get or a Post with my factory, i get de error 401, Unauthorized
In my app config, i have this:
//enable CSRF
$httpProvider.defaults.xsrfCookieName = 'CSRF-TOKEN';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRF-TOKEN';
This is my factory:
angular.module('jhipsterApp')
.factory('WalletsService', function ($http) {
return {
findAll: function () {
return $http.get('api/walletslist/').then(function (response) {
return response.data;
});
}
};
});
When i execute findAll function, i get this error:
[Error] Failed to load resource: the server responded with a status of 401 (Unauthorized) (walletslist, line 0)
The x-csrf is saved in cookies but how i pass it in the headers?
thanks
Look at SecurityConfiguration, /api/** requires authentication, so your endpoint requires it too. It's not a CSRF issue, it's just that you must be logged in.
If api/walletslist has to be public, you must do this in SecurityConfiguration
.antMatchers("/api/walletslist").permitAll()
Warning: order matters and make sure your authorizations URLs matches your angular services and REST controller request mappings. It's easy to forget a final slash character in one place.
Any reason why you want to use $http, why not using $resource like other JHipster services?

AngularJS - Setting default http headers dynamically

To overcome csrf attack, I have to send in csrf-token value in a header for every request by picking in the value from cookie as described here. Since this is to be done at every request, I am setting the default headers for $http in the main module's run function.
Now, If a new tab is opened for the same website, a new csrf token (in cookie) is issued by the server. Since the run function is run only once, the default header for csrf will be old one (for old tab), while the new csrf cookie will be sent to server, resulting in csrf-mismatch.
How to overcome this at a global level?
I want somehow to create a function which will be run everytime the $http is called, so that then I'll override the default headers.
Note: I do not want to set this header value for every $http request.
(Not that I think that it's relevant, but I'm using ui-router)
Edit
This is not just limited to csrf-token, I want to set some other headers too based on the logged in user, which has to be done dynamically (say when one user logs in, and logs out, then another user logs in).
you need to use http interceptor to do this on every request. read more about http interceptors here
below is one such example
module.factory('xsrfTokenInterceptor', function ($q, $http) {
return {
'response': function (response) {
var cookies = response.headers("Set-Cookie");
var token = someCrazyParsing(cookies);
$http.defaults.headers.common["X-CSRFToken"]=token;
return response || $q.when(response);
}
};
});
module.config(function($httpProvider){
$httpProvider.interceptors.push('xsrfTokenInterceptor')
})
How about headers $http(config) parameter.
$scope.getWithHeader = function(){
$http({
method: 'GET',
url: 'http://fiddle.jshell.net',
headers: {
'CustomHeader': 'HelloWorld'
}
}).success(function(){
console.log("success");
});
};
sample code on jsFiddle

How do I handle Token Authentication with AngularJS and Restangular?

I have an angular app that uses Restangular and ui.router.state.
This is what I am currently doing
I have an Endpoint /Token that accepts a username/pass and gives
back a bearer token and some user info.
On successful login I save off the userinfo and token into a global var, user.current and I also set Restangular's default headers to include the bearer token:
Restangular.setDefaultHeaders({Authorization: "Bearer " + data.access_token});
When a user wants to access a route that has requiredAuth = true (set in the routeprovider as custom data like Access routeProvider's route properties) I check the user.current to see if its set.
a. If user.current is set, take them to the route.
b. If user.current is null or if the token would be expired (based on time) send them to /login
Problems/Concerns
If I Ctrl+R I lose my user info and the user has to log in again.
a. Should I be saving off the bearer token or credentials into a cookie or something and have a user service try to grab that in the event that user.current == null?
Am I even approaching this right? Seems like something that literally 100% of people using AngularJS would want to do, yet, I can't find an example that aligns with my situation. Seems like Angular would have mechanisms built in to handle some of this auth routing business...
When do I need to be getting a new token/verifying the current one? Do I just let anyone with devtools set something like isAuthorized = true so they can get to /admin/importantThings but then let the calls to /api/important things fail because they don't have a valid bearer token or should I be verifying that they have a valid token before I even let them get to that route?
You could put it in localStorage (always kept) or sessionStorage (cleared when browser is closed). Cookies are technically also a possibility, but don't fit your use case that well (your back end checks a separate header and not a cookie)
I guess there are many ways to skin a cat.
Always depend on server-side checks. Client-side checks might offer some increased usability, but you can never depend on them. If you have a lot of buttons that result in going to a login screen, it will be faster if you keep the client-side check. If this is more the exception than the rule, you could instead redirect to the login page when you get a 401 Unauthorized when calling your back end.
Here is an example of how you can manage your token:
/* global angular */
'use strict';
(function() {
angular.module('app').factory('authToken', ['$window', function($window) {
var storage = $window.localStorage;
var cachedToken;
var userToken = 'userToken';
var authToken = {
setToken: function(token) {
cachedToken = token;
storage.setItem(userToken, token);
},
getToken: function() {
if (!cachedToken) {
cachedToken = storage.getItem(userToken);
}
return cachedToken;
},
isAuthenticated: function() {
return !!authToken.getToken();
},
removeToken: function() {
cachedToken = null;
storage.removeItem(userToken);
}
};
return authToken;
}]);
})();
As you can see I use "$window.localStorage" to store my token. Like "Peter Herroelen" said in hist post.

Resources