Can someone tell how is authentication actually working in MEAN.JS [meanjs.org] here?
When the user logs in,where is the USER json object stored. The code is
// Authentication service for user variables
angular.module('users').factory('Authentication', [
function() {
var _this = this;
_this._data = {
user: window.user
};
return _this._data;
}
]);
//The implementation of the service in the controller
$scope.authentication=Authentication;
// If successful we assign the response to the global user model
$scope.authentication.user = response;
but in console window.user returns null
Another question, how the app retains the user JSON object when the page is refreshed? After the page is refreshed window.user returns the user JSON object, I don't see this object in the Local Storage or Session Storage, neither do i see any ajax being made to the server to fetch this object.
Thanks
Related
I have a page with a main controller and a nested controller for showing details about a product. I want to use a a service in angular to call the server, retrieve a data object and hold that data object. The main controller will call the service to fetch the data and the details controller needs to know it was updated and then access the data. My service looks like this:
.service("productService", function ($http, $q) {
var product = {};
//interface that is returned
return ({
fetchProduct: fetchProduct,
clearProduct: clearProduct,
product: product
});
function fetchProduct(ID) {
var request = $http({
method: "get",
url: "/online/productdata.ashx?itemID=" + ID,
params: {
action: "get"
}
});
return (request.then(handleSuccess, handleError));
};
function clearProduct() {
product = {};
};
// Transform the error response, unwrapping the application dta from
// the API response payload.
function handleError(response) {
// The API response from the server should be returned in a
// nomralized format. However, if the request was not handled by the
// server (or what not handles properly - ex. server error), then we
// may have to normalize it on our end, as best we can.
if (
!angular.isObject(response.data) ||
!response.data.message
) {
return ($q.reject("An unknown error occurred."));
}
// Otherwise, use expected error message.
return ($q.reject(response.data.message));
};
// I attempt to transform the successful response and unwrap the application data
// from the API response payload.
function handleSuccess(response) {
product = response.data;
console.log("Found Data: " + angular.toJson(response.data))
return (response.data);
};
})
In my main controller I set a scope object to the service like this:
$scope.SelectedProduct = productService;
When the user clicks the button to show the product it is called via the $scope handle:
$scope.SelectedProduct.fetchProduct(ID);
The details controller has the same assignment for the $scope.SelectedProduct. I am new to using services but what I understood is that angular would bind to the service object and changes to the property product would trigger binding to any updates. That is not happening - in fact I do see the data after the fetch operation. In the service I have a console.log on the returned data and it is showing the correct data. However the product property is not getting updated. Can someone tell me what I am doing wrong please? Neither controller has access to the data after it is fetched. I understand that I am getting back a promise but the data is never there even after a timeout check.
Try it with a factory instead of a service.
AngularJS: Factory vs Service vs Provider
So whenever I logout from Firebase, I got coupled
Error: permission_denied: Client doesn't have permission to access the desired data.
I understand it is because login session is terminated, some of my objects cannot access firebase data any more. But how can I disconnect this objects before logout?
For logout button in one of my Ionic View, it just call a firebase service:
function logout() {
auth.$unauth();
getCurrentUser();
};
function getCurrentUser() {
var authData = auth.$getAuth();
if (authData) {
$rootScope.userId = authData.uid;
$rootScope.currentUser = $firebaseObject(authRef.child("users").child(authData.uid));
return $rootScope.currentUser;
} else {
console.log("User is not login!");
$rootScope.userId = null;
$location.path("/auth/signin");
if ($rootScope.currentUser) {
$rootScope.currentUser.$destroy();
}
}
};
So I destroy the $rootScope.currentUser there. I use the same getCurrentUser for profile page. So the Error did not show up this way. But when in other views, which I have another $firebaseArray, and also another Ref.on("child_added", function(snap) with the same $firebaseObject. When I view the profile page, then this page with at least 3 firebase connection, I got 3 permission_denied Errors when I logout (logout button is on user profile page).
My question is, how do I disconnect this firebase connection before I logout? Is there a way disconnect ALL the firebase connection - no matter AngularFire or regular Firebase? So I can logout without worry about which firebase connection I have no close yet? Also, since the Logout button is in Profile scope and the others connection is in a different scope, I have no idea how to close the connection which is not even in the profile scope...
You need to destroy all the firebase references on logout.
Something like this.
In logout function.
function logout() {
auth.$unauth();
$rootScope.$broadcast('logout');
};
In controller
vm.profile = authService.profile(user.uid); // FirebaseObject Reference
vm.parties = partyService.getPartiesByUser(user.uid); // FirebaseArray Reference
$rootScope.$on('logout', function () {
vm.parties.$destroy();
vm.profile.$destroy();
});
well, i guess you have a button to logout.
so in your function logout() you'd first $destroy the data object, somehow wait (whichs' best practice i'm trying to figure out), and then authref.unauth();
i'd say
You need destroy the firebase ref for the object that you saved data previously. How?
Before, I initialize my var songs like:
this.songs = this.af.list('/songs');
When I signOut(), I should destroy the reference of the variable that I initialized so that I execute:
this.songs.$ref.off();
With this line, your problem
I'm having issues with $cookieStore retaining a cookie value after updating it. Here are two methods of a UserService that deals with the cookie:
var getCurrentUser = function () {
return $cookieStore.get('currentUser');
};
var updateCurrentUser = function () {
return $http.get(baseUrl + 'api/session').then(function (response) {
$cookieStore.put('currentUser', response.data);
$rootScope.$broadcast('currentUser', response.data);
}, function (response) {
$cookieStore.remove('currentUser');
$rootScope.$broadcast('currentUser', null);
});
};
Throughout my app, after an action is executed that would affect the current user's meta data, I call UserService.updateCurrentUser() which retrieves the latest user data from the server and updates that cookie. Then, in places that display the user data, I have the following code that will update the user model in that particular controller:
$scope.$on('currentUser', function (event, data) {
$scope.user = data;
});
As I step through the code, everything appears to be working correctly. After the $cookieStore.put('currentUser', response.data); line runs, the updated value can be confirmed by checking $cookieStore.get('currentUser'). When I check the actual cookie using a browser tool, however, the cookie value is not updated. I'm not sure if the browser tool requires a refresh to show the new data. But when I refresh the page, the updated cookie value is also no where to be seen. What is going on?
Thanks in advance.
Check out the documentation adding a cookie using $cookie service:
put(key, value, [options]);
The third argument allows additional options:
path (string)
domain (string)
expires (date)
secure (boolean)
You should set "expires" to define when the cookie should expire, otherwise the cookie will expire when you refresh or leave the site.
$cookies.put("id", 1, {
expires: new Date(2016, 1, 1)
});
Also the service is now called $cookies. Since Angular 1.4 you can now set expiry. Until then it wasn't possible.
http://docs.angularjs.org/api/ngCookies/service/$cookies
Maybe I am missing something very trivial, but I can't find an answer.
I am implementing a webapp based on nodejs, express and angular for the client side.
I handle my signup and sessions through passport.js. Therefore, server-side, I can access the logged user through request.user.
Now, I have a logged user which goes on its profile page, displayed through an angular view.
Here is the issue: In order to show them user information now I am thinking to send an $http request to the server, which takes the user from request and sends it back to the client where it is displayed. However, this sounds weird to me.
So here is my question: Is there any way to access the user in the session thruogh angular? If so, what user information is actually stored in the client?
Thanks in advance, and apologies if this is something too trivial to be asked:/
You will need to create a service in Angular that requests the current user, and stores the result so you can retrieve it for use in your controllers. There is nothing built in to Angular for this; you will have to create it your self. However, it's fairly straight forward.
myapp // assume was previously defined using var myapp = angular.module('myapp', []);
.factory('principal', ['$http', '$q', function($http, $q) {
var _identity = undefined;
return {
// this function returns the current _identity if defined; otherwise, it retrieves it from the HTTP endpoint
identity: function(setIdentity) {
if (setIdentity) {
_identity = setIdentity;
return;
}
var deferred = $q.defer();
if (angular.isDefined(_identity)) {
deferred.resolve(_identity);
return deferred.promise;
}
$http.get('/path/to/endpoint')
.success(function(result) {
_identity = result;
deferred.resolve(_identity);
})
.error(function() {
_identity = undefined;
deferred.reject();
});
return deferred.promise;
}
};
}]);
This principal service has one method at the moment, identity(). This method returns a promise. If the identity has already been retrieved, it will resolve with that value immediately. If not, it will attempt to get it from an HTTP endpoint. If the HTTP call succeeds, it will memoize the result to _identity and resolve the promise. If the call fails, the promise will be rejected. identity has a secondary use. If you supply it with a single parameter, it will set that value as the identity and return nothing. This is useful if you already have the identity and want to set it right away, for example, after they successfully sign-in.
You could manage the sign-in page like this:
myapp.controller('SignInCtrl', ['$scope', 'principal', '$http', function($scope, principal, $http) {
// these two values will be bound to textboxes in the view
$scope.username = '';
$scope.password = '';
// this function will be called when the sign in form is submitted
$scope.submit = function() {
$http.post('/path/to/signin', {username: $scope.username, password: $scope.password })
.success(function(identity) {
// assumes /path/to/signin returns a JSON representation of the signed-in user upon successful authentication
// presumably the endpoint also sets a cookie representing an auth token or something of that nature. the browser will store this automatically for you
principal.identity(identity); // set the identity immediately
// do whatever else on successful login, like redirect to another route
});
}
}]);
And a controller somewhere else that needs the current identity could do something like this:
myapp.controller('MyCtrl', ['$scope', 'principal', function($scope, principal) {
// retrieve the identity. when it resolves, set user on the scope
principal.identity().then(function(identity) {
// after this, you can use user in your view or later in your controller
$scope.user = identity;
});
}]);
Now you have a way of storing the identity immediately after sign-in. I do make an assumption that your code that signs the user in sets a cookie to represent an auth token or whatever in your signin endpoint. The good thing about this is that if the user refreshes their browser, or the cookie is stored for a period of time, the user can just visit your app and the identity will resolve it using that token cookie automatically.
This plunk is a working demo of a more elaborate set up. Some of it may not apply to you (for example, it uses ui-router instead of regular routing), but it should be a reasonable reference point.
I'm writing a cookie from a server through the response and it's fine the problem is when I try to read the same cookie using angularJs $cookieStore.get() returns always 'undefined', I have debugged with the developer tools using chrome and the cookie is there,
console.log($cookieStore.get("r"));
the $cookieStore seems to be injected and running ok, I'm just wondering why angularJs can't read the cookie.
Edit:
I tried with $cookies service and I get undefined as well.
I send the cookie in the server side without any problem, I'm getting the cookie in chrome developer tools
I'm using Service Stack and the code is the following:
public override object Logout(IServiceBase service, ServiceStack.ServiceInterface.Auth.Auth request)
{
var resp = service.RequestContext.Get<IHttpResponse>();
resp.Cookies.AddCookie(new Cookie { Name = "r", Path = "/", Value = "from server", HttpOnly = false, Discard = false, Expires = DateTime.Now.AddHours(12) });
return base.Logout(service, request);
}
I think $cookieStore is only meant to be used by itself, was 'r' set somewhere else? The docs say it provides a key/value store backed by cookies, not direct access to cookies. When I set 'myValue' to 'jason' it stores %22jason%22 (fiddle). This means you can set values to javascript objects if you want and the cookieStore will serialize and deserialize them for you.
Try using $cookies instead where you can just set properties and the values aren't encoded (fiddle):
$scope.setValue = function() {
$cookieStore.put("myValue", $scope.value);
};
$scope.getValue = function() {
$scope.value = $cookieStore.get('myValue');
};
$scope.setCookieValue = function() {
$cookies.otherValue = $scope.value;
};
$scope.getCookieValue = function() {
$scope.value = $cookies.otherValue;
};
Yes #Pedro is right in .NET ,for example, when doing an authentication with HttpCookie by default the attribute HttpOnly is true and in javscript -> document.cookie cant find the cookie you just saved to the browser.
It worked for me by setting to false HttpOnly when saving the cookie.