How do I configure what happens when using Authorize(Roles) attribute? - asp.net-mvc-4

I have an MVC4 project with simplemembership configured. It's all working etc. but I would like to know how to tell it wich controller/action to redirect to when a user is not authorized to view a given page.
For example, if I use [Authorize(Roles="Admin")] and try to view that page with a logged in user that does not have the "Admin" role it redirects me to the login page, even though I am already logged in.
I would like to change this to something else... maybe a 404 or a nice message to say "You are not authorized to view that content".
I've tried googling for just about everything I can think of to do with this but haven't found an answer so far.
Can this be done with the current setup or do I need something else? A pointer in the right direction would be appreciated :)

Try creating a custom AuthrorizeAttribute and override the OnAuthorization method so that you do a redirect to your custom page if authorization fails and to the logon page if authentication fails. Another approach that some people use is to check if the current user is authenticated on the logon page and if they are you can assume they were redirected to this page because authorization failed. In that case display a special message to the user indicating that they are not authorized to access that page. For some applications this may make sense because a user might have multiple accounts and they want to logon to another account where they are authorized to perform the operation. Some of these concepts are discussed in this QA.

This is, unfortunately, a problem with Asp.net as a whole (although it originates from a problem in the HTTP specification), it does not differentiate between unauthorized users and unauthenticated users, even though they seem to go out of their way to talk about the difference. In order to change this behavior, you would have to write a lot of code, and it's just easier to write a custom handler to check if you are already authenticated.
The HTTP standard never intended for a user to be in an "authenticated state". In fact, it doesn't really even know about the concept of a "user". Each page request is intended to carry information independent of the other page requests. The fact that browsers cache this information (or authentication is done by cookie) is irrelevant to what the standard intended.
The standard basically says that the server should issue a 401 if the requested resource is not authorized, and since each request has it's own authorization, the intention a simple pass/fail scenario. There is no concept of an authorized state for the site. The request either succeeds or fails.
I think frameworks like ASP.NET have gone a long way to creating their own authorization/authentication state, but they really should just go all the way here.
You might find this thread enlightening regarding the disagreement among the web community about the exact interpretations.
403 Forbidden vs 401 Unauthorized HTTP responses

Related

What HTTP status code return when user needs to be UNAUTHORIZED to access page

I was wondering what HTTP status code should I return if user that is authorized tries to access page that should be accessible only by unauthorized users.
Currently I am just throwing 404, but was wondering if there is some common approach for this.
HTTP Status Code 403 Forbidden can be used when a request isn't allowed based on the user's identification, so I guess it can be used in this case.
However, have you also considered sending back a Redirect (https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections) to send the user to a different resource that might be more appropriate because they are authenticated?
This is a common method used to redirect authenticated users away from login pages to their home screens or profile page.
Also, for future reference, I think you might be referring to autheNtication (with a N, the process of verifying a users identity) instead of authoriZation (with a Z, the process of determining whether an authenticated user has access to a particular resource)
https://www.okta.com/identity-101/authentication-vs-authorization/

How to force login per client with keycloak (¿best practice?)

We are currently implementing keycloak and we are facing an issue that we are not sure what’s the best way to solve it.
We have different webapps making use of the sso and that’s working fine. The problem we have is when we make log in using the sso in one webapp and then we do the same in a different webapp.
Initially this second webapp does not know which user is coming (and it’s not necessary to be logged in to make use of it). When clicking on “login”, it automatically logs in the user (by making a redirection to keycloak and automatically logging the already logged user in the other webapp). This second logging happens “transparently” to the user, since the redirection to keycloak is very fast and it’s not noticeable. This behaviour is not very user friendly.
The question is: Taking into account that this second webapp can’t know upfront which user is accessing the site (unless actively redirecting to keycloak), is it possible to force always the users to log in for a specific keycloak client? By this I mean actually ask the visitor for user/pw even if keycloak knows already them from other keycloak clients.
Thanks in advance!
In the mail listing from keycloak, they gave me a good solution but for version 4:
in admin console, go to Authentication
make a copy of Browser flow
in this new flow, disable or delete Cookie
go to Clients -> (your client) -> Authentication Flow Overrides, change Browser Flow to your new flow, click Save."
Use logout endpoint as a default login button action in your app and redirect uri param use for login page, where you use your specific client (of course you need proper URI encoding):
https://auth-server/auth/realms/{realm-name}/protocol/openid-connect/logout?redirect_uri=https://auth-server/auth/realms/{realm-name}/protocol/openid-connect/auth?client_id=client_id&redirect_uri=.....&other_params....
=> user will be logged out and then it will be redirected to the login page

How to deal with logged in user who happens to be deleted?

In MVC 4 project I've deleted user from the system while he happened to be logged in. Now he's getting exception from SimpleMembershipProvider methods (or from Membership/Role helpers) that user does not exists.
The issue is however, that while logged in, instead of any possibility to log off gracefully, he's getting error page, which would not let him use the page till the auth cookie would get outdated. How to intercept such a situation? It looks like I can't hook anywhere to just handle those exceptions. What is a nice way of dealing with it?
If you are using role-based authorization and have authorization setup correctly in your application, then the graceful way to handle this is to not delete the user but to take his roles away so he does not have access to areas you do not want him to.
Another way to do this is to add an enabled flag to the UserProfile by customizing it as described in this article. Then use the enabled flag in your authorization process by customizing the Authorize attribute to fail authorization if enabled is false. Instead of deleting the user you just flip the enabled flag to false.

LinkedIn grant access screen showing even though user already authenticated

I'm using an external Node.js module, everyauth, to handle my LinkedIn API authentication. I'm not yet positive if this is a problem with the way my module handles their API, or some other API issue itself.
Basically, after a user has already granted access, LinkedIn nevertheless continues to ask whether to continue to grant access. I know this is not standard because I've seen a different user flow in other applications.
Here's an example of what happens:
You can see I granted access on Jan 11th, but this was taken on Jan 13th. Why must I re-auth!?
Do you have any idea what is causing this? I dove into the relevant LinkedIn module code for everyauth but nothing in that application flow caught my eye as the problem.
Modify the script to send them to https://www.linkedin.com/uas/oauth/authenticate instead of
https://www.linkedin.com/uas/oauth/authorize.
That will cause LinkedIn to automatically redirect them back to your site.
See more at https://developer.linkedin.com/documents/linkedins-oauth-details
If you are using the JavaScript API (which it looks like everyauth uses), then it is likely that the OAuth tokens that LinkedIn stores in the browser have become 'stale'. To ensure that the user is the correct user, the browser tokens expire after ~30 minutes.
That being said, if the session is still fresh and the authorize value is set to true, you should be able to bypass the screen you are seeing.
https://developer.linkedin.com/documents/overview

CAS authentication and limiting access for specified users

I'm using CAS (Central Authentication Service) from Jasig in a client JSF app running on tomcat 6 server. I would like to limit the access to the app just for the users specified in my database rather than all the users which can be authenticated using that CAS service. When the user attempts to log in, I need to check if his username is also in my database's table user and if it is - allow the access to the app. Otherwise, I would like to redirect user to a page "You don't have permission to access this part of the application". So I need authorization as well. Is there a good way to authorize the users in jsf 2.0? Thanks in advance for any help/suggestions.
Sounds like you need to design a custom Authentication Handler class in CAS. In theory, your handler would extend this [1], perform all the necessary checks and database look ups and will then be able to return a signal that indicates whether or not the user could authN.
You should then reference your custom handler in the deploerConfigContext.xml file.
For displaying the message, you could either throw an exception with the proper messages code, such that the message would appear above the login form, or you could alter the spring webflow and generate a new view-state which the user would be redirected to, if they fail to get access. The first approach is much easier to implement.
Another approach would be to take advantage of the isUserInRole() method [2] using the persondir api.
[1] http://developer.jasig.org/projects/cas/cas-server-core/cas-server/cas-server-core/apidocs/org/jasig/cas/authentication/handler/support/AbstractUsernamePasswordAuthenticationHandler.html
[2] https://wiki.jasig.org/pages/viewpage.action?pageId=47874068