so i'm trying to create a public/external link that can be generated and shared to anyone for people to get to a specific state of my angularJS app.
I am using $stateProvider to manage states on the app. but i need a part of the app to be open to the public. i.e a particular state open to the public such that as soon as they hit that the url e.g mydoamin/post it gives them access to that state alone. for example
.state("post", {
url: "/post",
controller: "postController",
templateUrl: "templates/post.html",
})
My app currently user $stateChangeStart to check between state transitions but is setup to block any unauthenticated user. so if anyone that is not logged in tries to get to a state it kicks them back to the login state which is the default '/'.
.state("login", {
url: "/",
controller: "LoginController",
templateUrl: "templates/login.html",
})
I know i could just give each state a value probably 'authenticated' and set it to true or false for each state and check the toState on $stateChangeStart if 'authenticated' is false and grant access based on that but i need to know if its a good idea and how to securely implement it.
How would you do this?. thanks in advance for any reply/suggestion.
For 'securing' the UI, i.e. hide some pages from unauthorized users, use ui-state router's resolve parameter. See this question for more info. Put a 'resolve' on the states that need authentication, and leave it out for the public pages.
However it is important to understand that any security measure that is implemented client-side, is never fully secure. Anyone can have access to any page, including the ones that require authentication. All it takes for them is to open dev tools and alter the JavaScript. That's why you should properly handle authorization at API level. This way, even if a malicious user can see a hidden page (i.e. he can browse to it and see the html), he won't be able to see any data that was fetched from the API.
Related
Using mean.js:
I have a large application that is divided by say, offices. Each office accesses the same application in the same way, but employees of an office may only access information pertaining to that office. Company administrators may access the app fully, switching between office contexts. The caveat is that there are no user accounts (no login/auth) for office employees, only admin accounts for the administrators.
I'm exploring doing it in the following way:
I created an access module with a service that stores the office context, passing it to the backend when making API calls. This is set upon application startup from config files.
This is well and good, but I need to allow the administrators to switch office contexts. I use a link <a ui-sref="Context({ officeID: 'x' }) (in the navbar dropdown, so accessible from every state) to access the angular router:
.state('Context', {
url: '/Context/:officeID',
controller: 'ContextController',
controllerAs: 'vm'
});
This passes the officeID to the ContextController, which would set the ContextService.officeID variable. At this time, I believe I would make an api call from the ContextController to refresh the current state's data to reflect the current context. Not sure how to do that.
I feel that I have some options here, which I am unsure how to implement:
I can make the Context state abstract, and every other state a child, but that seems bulky. If this is correct, how do I tell the current state to refresh it's data?
I could enter the Context state, set the ContextService.officeID, and immediately redirect back to the previous state, which upon entering, should make an api call using the new context. If this is correct, how do I properly perform that redirect?
I could scrap how this is being done entirely, but I don't know where I would start. Any advice is welcome.
I figured out something that feels a bit more elegant.
I still use the Context route. I've included the ContextService in all of my angular modules, and call it when the context needs to be set.
I tried to redirect using $location.path(...), which was a major headache. Using $state.go($state.previous.state.name) works a treat.
Even better, if you use routes that depend on resolves, you can further redirect using $state.go($state.previous.state.name, $stateParams);
I am developing a SPA (Single Page Application) with Angular JS and using "UI Router" for routing and using Spring MVC framework for back-end.
I would like to bring the user role based view in the application as we have different user roles in application.
What is the best way to do this?
Is there any way to retrieve the user role from server check it in the ui route before state changes?
You could pass roles through the data attribute and the check the user access on the $stateChangeStart event. This would off course require you to implement users with user roles.
Pass the role restriction as custom data to state object (https://github.com/angular-ui/ui-router/wiki#user-content-attach-custom-data-to-state-objects)
$stateProvider
.state('admin', {
url: '/admin',
data: {
roles: ['ROLE_ADMIN']
}
})
Then in the .run function do a check on the $stateChangeStart event if current user has said role and if so allow the route change, if not send user to some kinda access denied page (or just prevent state change).
.run(function($rootScope, $state) {
$rootScope.$on('$stateChangeStart', function (event, toState, toStateParams) {
// Check if current user has group access
if(!AuthService.userHasRole(toStateParams.roles)) {
$state.go('accessdenied');
}
})
})
There would be quite a bit of work off course to get this working. Setting up users/roles/auth etc. Will leave that to you. JHipster (https://jhipster.github.io/) has a pretty solid auth, access, user with user roles implementation. The backend is in Java though. But the Angular implementation is rock solid.
One way I am exploring is simply putting the various views on the page wrapped in ng-if's and checking the userRole.role(a global value) to determine which state to view.
However, there has to be(or should) be a way to do it relatively easily in UI-Router I would think...
Then again, I wam building this on a sharepoint site, so I don't have to worry about top level access rights as we set those on Sharepoint itself. Anyone who can actualy view the page will be 1 of 5 types of userRoles, I simply have to get the role and then show the proper view based on that role
on our company, we're currently working on a single page web application. Users can login and fill their profiles with data and share those with other subscribers (it's a social network-ish application).
Now, I've imagined this schema:
the users data are provided by a UserService, using REST APIs to recover profiles information;
the profiles related pages are managed by a unique controller (ProfileController);
my question is: what's the best way to associate a route (let's say "view-profile") to a specific controller method (ProfileController.viewProfile)? Is this a right pattern in AngularJS?
Thanks!
Investigating further I've found that the best way to achieve the result I want is by using the resolve in the state configuration, as explained in this article: https://scotch.io/tutorials/making-skinny-angularjs-controllers.
EDIT:
I'll try to explain it a little bit. What I'm trying to achieve is to route a specific application state to a controller method, in order to avoid preloading a huge subset of data everytime I access the controller. Let's say I've this situation in my ui-router
.state('view-profile', {
url: '/view-profile',
templateUrl: 'components/profile/profile.html',
controller: 'ProfileController'
})
[...]
.state('edit-profile', {
url: '/edit-profile',
templateUrl: 'components/profile/edit-profile.html',
controller: 'ProfileController'
})
Since the ProfileController could potentially do a lot of stuff, not necessary related to edit/view, I'd like to set a specific controller method to be called when I navigate to these urls.
In other MVC frameworks you can associate a route to a specific controller method, so you'll have
route: /edit-profile -> resolvesAs: ProfileController.editProfile(args)
Unfortunately, there's no really a way to do this in AngularJS 1.4, at least not using the ui-router.
But fortunately enough, we can use the resolve attribute on the ui-router configuration to avoid preloading useless data for a specific route.
I want to use different different types of template in client side and admin side using angular-fullstack.
Can you please let us know how i can achieve this. My routes look like Ex:
www.sitename.com - main site with theme1 (http://demo2.jlvextension.com/probusiness/)
www.sitename.com/administrator - administrator dashboard with theme2 (http://www.theme-guys.com/materialism/angular/)
It seems to me like you're trying to create two very different front ends. I recommend building two different angular applications that utilize the same api's and domain. You could put an entire admin angular application at www.[sitename]/admin.
We also had a requirement like this and initially we had both in one SPA, where we distinguished each page by URL. The URL 'admin/login' loaded admin login page while '/login' loaded the login page for others. The $routeProvider config is given below.
$routeProvider.when("/admin/login", {
templateUrl: "app/admin/login.html",
controller: "AdminCtrl"
}).
when("/login", {
templateUrl: "app/user/login.html",
controller: "LoginCtrl"
}).
Later when the application became big and difficult to maintain, we ported the admin part to a separate application like Gabriel suggested above.
you can resolve this problem with creating a directive with different
templates,This plunker should demonstrate what needs to be done,
but basically:(you should just change the value of isAdmin property
to simulate ). good luck
I have an angularjs app and would like the homepage to depend on the logged in status of the user.
Im looking for something like the following to happen:
When I goto mypage.com use 'resolve' to perform an HTTP GET with a server to check if logged in.
If the user is not logged in resolve the promise from 1) and show some generic splash screen. For example, templateUrl: splash.html
If the user is logged in then fetch additional data from the server. Once the data has been returned then resolve the promise from 1) and show a page specific for this user. For example, templateUrl: loggedin.html
In either case, the URL should not change. ie: I do no want to redirect to another route. The URL should always be mypage.com.
How can I have a dynamic page like this without using any redirects?
Have a look # https://github.com/angular-app/angular-app, its the best example app I've found so far for dealing with the user authorization rabbit hole.
For a quick start with getting your head around how user auth works in angular-app, have a look at these 3 files:
https://github.com/angular-app/angular-app/blob/master/client/src/app/app.js
https://github.com/angular-app/angular-app/blob/master/client/src/common/security/security.js
https://github.com/angular-app/angular-app/blob/master/client/src/common/security/authorization.js