How can I figure out if the authenticated user is authorized to access an area/controller/action? - authorization

Being in a view and you know the area-name, controller-name and action-name of a destination to which you want the user to provide a link to, how can I figure out if the area/controller/action is authorized for the authenticated user.
Imaginary Use-case:
I have a table with a list of books (the result of bookscontroller.index). To the far right are some icons to edit or delete a specific book. The edit link refers to bookscontroller.edit and the delete link to bookscontroller.delete.
On the actions there are custom authorizationattributes and this works perfect. If a user want to access books/edit/1 and the user is not allowed to edit books, the user gets redirected to the logon page.
It is a bit stupid to have that edit-icon there if the user is not allowed to edit books. So at view level I would like to be able to figure out if the user is allowed to use the edit action of the bookscontroller. If he is, show the icon if not, do not show the action.
Goal: use that knowledge to create a custom tag-helper.

The go-to method is reactive, i.e. you check if a user can do action when the user tries to do. Since you do not want to go that way, here is how. (yet, this is anti-pattern)
Have the authentication token of the user send back to backend. The backend should have an API end point for each button on the page user can click. With the authentication token, the back-end resolve whether to dim or enable the buttons.
Now, what the backend does to resolve this is not very efficient. The backend needs to literally attempt certain actions and aborts the transaction. For create and retrieve, it is trivial (you can pre-resolve them) but for edit and delete, this requires a lot of resources.

The standard way of controlling such actions on UI is to use role based authorization.
For the buttons or other such UI elements, setup role tags, e.g. "admin:edit", "viewer:readonly" etc.
When you are authenticating a user, send the applicable roles from the backend server, store them in a way that is globally accessible to your UI and use them for filtering UI elements across your application.

Related

Vue JS Role Based Authentication and Routing

i have an old asp.net web-form based application, which i want to convert to Vuejs based front-end and Asp.Net Core base api as back-end.
The current application has a login page, where the user inputs his credentials, once the credentials got verified, user is taken to application home page, which has side menu bar.
The side menu bar is loaded based on the current users role/privilege. Say for example, a user with role of admin may have 10 menu items, while a normal user may have only 5 menu items.
I'm very new VUE, so pls guide me, how to set up the vue application and routing for above scenario.
Thanks in advance.
There are many ways to go about this, your goal is to load data about your user into your application.
One way to solve this is to create an API function that returns information about the currently logged on user.
The authentication of the request can be done through cookies, jwt header or something else.
The api call to get the authenticated user data will also help you figure out if the user is already logged on when the app starts up.
Putting aside how you make the network request, lets say you now have the data in your application.
There are a few choices on how to store it, this is an architecture choice as the results of this will likely have effect on many other parts of your application.
The common solution to storing application-wide (global) state is to use Vuex.
This will also play well together with vue-router.
Lets say that in Vuex you will make a field roles that will hold an array of strings, indicating the roles the user has.
In a vue component you can reach the vuex store from the $store property (this.$store in the code, $store in templates).
The state of the store is then reachable via $store.state, and your roles array would exist over at $store.state.roles.
To set the roles you will have to setup mutations that will let you save the roles, and the api call would be part of an action. You can read more about that on the vuex documentation on how to update the state.

Is there a way to register routes after the application is started?

I want to have app which has some default route and controller (Let's say Login page). I can register this at the Configure method but after the user successfully logs in I want to fetch the pages related to the user and register them so he can have access to it. Is there a way to achieve that?
As long as I read that's impossible but who knows, I'm new to ASP NET Core?
Based on the wording, this sounds like a security question. You only want users to have access to certain pages. If that's the case then I would look at something like role-based authorization.
If the question is more about showing the user a list of resources they can access, then the most obvious solution I can think of is to store that information in a relational database. When the user logs in, select the relevant pages / resources by user ID.
In any case, changing the registered routes is not the correct approach.

Spring. Java. Log in and activation email

I have a "chicken egg" problem.
In application I use UserDetailsService to get User (we don't store user information in our DB, we use third party service to actually get all information).
Recently we've added account activation feature. After registration, we send an activation email to a user and if he clicks on it, we mark the User as ACTIVE and redirects him to log in page. User can login only if he has ACTIVE status. The problem is: we'll start charging user from the date he activates his account even if he never logs in. How can I (maybe using spring security) make those processes (activation and login) almost simultaneous? We don't want to charge user if he just activates his account, we want to charge him only if he has logged in (after activation). So can I actually do it somehow "user clicks activation link, login and then his status is changed to ACTIVE (but he can login only if he is ACTIVE)".
Sorry if my problem description isn't clear enough
I'll appreciate any feedback.
Thanks!
If I understood your requirements correctly, you'll need two different entry points (login pages) to your application:
One for activation (first login) for users not yet activated.
Another "normal" one for active users.
The problem is that the authentication logic would need to be context sensitive and be aware of which of the above pages initated the authentication. However the framework was not designed for such uncommon use-cases, so the authentication provider has no knowledge about the URL from which the login-form were actually sent.
What you need to solve is to somehow relay contextual information to an authentication provider that processes the auth request according to that information (i.e. authenticate only non-active users logging in from url1, and authenticate only active users logging in from url2). There could be hundreds of different ways to achieve this, one possible solution is to put two different authenentication filters in place that intercept auth requests sent to the two different urls. Details outlined below:
Create your own custom versions of the existing WebAuthenticationDetailsSource and WebAuthenticationDetails (preferably by subclassing the latter) that stores and exposes the URI of the authentication request. (That will be the contextual information based on which the auth provider can implement its conditional logic.)
Configure and insert two different instances of the UsernamePasswordAuthenticationFilter in the filter chain. Set their filterProcessesUrl attribute to /j_spring_security_check_active_user and /j_spring_security_check_nonactive_user respectively, plus inject the above created custom AuthenticationDetailsSource in both of them.
Override DaoAuthenticationProvider.additionalAuthenticationChecks() in a subclass in the following way:
Retrieve the URI stored in the above created WebAuthenticationDetails object (it's accessible via authentication.getDetails())
Assert that the user is active/non-active according to the URI, and throw an AccountStatusException if the asserion fails.
Don't forget to delegate to the superclass if the assertion succeeds.
Create the two different login pages mentioned at the beginning of the post, making sure that the login forms post credentials to their respective URL (/j_spring_security_check_nonactive_user vs. /j_spring_security_check_active_user).

Grails Spring Security forcing user to a specific screen after successful authentication

Here is the scenario. I have two objects Users (with username/password) and UserInfo with rest of the data related to user. The Users is an old table with thousands of records and UserInfo is fairly new. I want to get as much UserInfo as I can when the user first logs in.
I'd like to force user to a custom screen after first login and ask for the UserInfo data. Once I get the "required" data in the new screen, I dont show it till the user voluntarily wants to fill in the data under "Profile".
Since there are multiple entry points to the application, I dont want to update all the controllers to check for this.
Is there a way I can use a Spring Security filter or something which is executed on successful login? I had a look at ApplicationListener<AuthenticationSuccessEvent> but it doesnt solve the problem as if I copy paste the link in the browser, it lets me go ahead to the destination without asking for "extra information".
In a nutshell, I want a check after each login which, if fails, user is not allowed to enter the application. No matter how he tries to get in.
In your Config.groovy, configure Spring Security's defaultTargetUrl and tell it to always redirect there:
grails.plugins.springsecurity.successHandler.alwaysUseDefault = true
grails.plugins.springsecurity.successHandler.defaultTargetUrl = '/userInfo/edit'
In your UserInfoController's edit action, you can check that the required fields are present (userInfo.validate() perhaps?) and if they are, redirect to wherever you like, perhaps '/', otherwise render the edit info view.
You can adopt what #doelleri proposed and enhance the rule by those steps:
run a batch task to assign a temporary ROLE_DISABLED role to each user who does not provide supplemental information yet. If the user already had some roles, save them in some property.
setup your authorization rule as that users with ROLE_DISABLED role only allowed to access /userInfo/edit.
in /userInfo/edit, if the user has a ROLE_DISABLED role, render the information input view, and resume user's role after it successfully updated its information. Otherwise redirect to '/' or the path it requested.

How to deliver form parts based on user's permission in ASP.NET

I am developing an application in ASP.NET and I have a page that depening on user's role displays different parts. If the user is an Admin s/he sees for instance a page part where to input a new user and role that a normal user cannot see. Let's think about this page as a portal.
I already wrapped all the different sections in with Id and I can control their visibility. However this is not the optimal solution concerning security since the user or a malicious robot can still fill and access the parts that are not visible in the browser.
With MVC it is easy since I just create several partial views and render them upon users' credentials but how do you do it in standard Web Forms? Thanks
You can use the ASP.NET LoginView control. The control has an AnnonymousTemplate which you can use to specify which content should be shown to Annonymous users, and a LoggedInTemplate which you would use to specify the content shown to logged in users. But is also has RoleGroups which can be used to specify content that can be shown to users in different roles.
The article in this link will walk you through the use of this control.
http://weblogs.asp.net/sukumarraju/archive/2010/07/28/role-based-authorization-using-loginview-control.aspx