I need to create a website with non standard authorizaion logic (or rather not exactly the site. It should be separate Area in existing ASP.NET MVC3 application). Access to most of the pages sould be available only to authorized users. Authorization is carried out on the token passed in the link. After the user arrived to this area, the token should be checked and if it’s valid site will create a session key for 30 minutes (we already have our own mechanisms of session managment and it should be used).
Workflow example :
Third-party website generates a link for user, e.g. https://example.com/securedPage/?accountId=123456&token=XXXXX
Our site check this token (it depends on the page from URL, in this case https://example.com/securedPage/)
If the token is valid, example.com obtains a session key for the user and stores it in cookies.
Then user continues browsing whole website and only session is checked.
I’m new to MVC framework, so I’d like to ask several questions about architecture.
What is an apropriate place for this logic? ActionInvoker, Global.asax etc.?
Currently I'm trying to create my own ActionInvoker and keep this logic there, but I'm afraid that it could be a wrong way.
If I understand correctly you want yo extend the Action of the controller to inject/check your token.
I think the global action filters should help you.
Related
I want to allow a new login to 'kick' a prior login session by the same account, in ASP.NET MVC.
It seems pretty clear that I'll give each browser a cooking representing the session ID. I'll track the currently active session ID in a server-side cache. If an already-active user attempts to log in, I'll verify the business logic (username, password, has been at least 15 minutes since last activity), and then update the active session ID cached at the server.
Now my issue is, a browser is holding an invalid session ID. What is the best point for me to inject a rejection or redirect to sign-in for this scenario?
I could modify the AuthorizeAttribute, but it seems like there should be a cleaner place to do this that won't require me to search and replace all my Authorize attributes, for example via a Global.asax event, or a controller event (I've already extended Controller in my project).
For example, if PreAuthorize existed, I would write some code there to test the request's cookies for a valid user/session ID pair, and if it didn't exist, I could simply remove the authentication cookie from the request, which would result in a standard unauthorized redirection.
So after a bit of research, it seems that a custom AuthorizeAttribute would typically be the correct approach. However, in my case, since I already had a custom role provider implemented, it was just a line of code to do it there. This also benefited me because I only wanted session concurrency for a single role. A side effect is that any use of web.config to control access to static files by role is also in-effect for session concurrency.
I currently have an intranet site that is accessed by external customers. I therefore set this up using Forms Authentication. However the powers that be (my bosses) want all our domain users to not have to enter their username and password to access the site.
I've done a bit or reading and everything seems to point to setting up a WinLogin.aspx page that you alter to use WindowAuthenthication and then redirect from there.
I have a problem with this as I don't like the idea of putting an aspx form in my mvc application.
Can anyone tell me how to achieve mixed authentication using a strictly MVC Controller/Action setup without a second application?
NOTES: running MVC 3 on an IIS 7 box.
Forms Authentication is not related to the URL or physical structure of your files. What matters is that a URL should ultimately map to a physical (or virtual) resource on the server, and be processed, and be returned back to the user.
Thus, somewhere in between for each incoming call (each HTTP request, even those for CSS and JavaScript files), you have to see if the current user has enough permission to access it or not. If no, then you might redirect him to the login page.
If you want, you can have a URL like /user/windowslogin where user is the name of the controller, and windowslogin is the name of your action method. Then you can create a custom authentication attribute (something like [WindowsAuthentication]) on your windowslogin action, and in that attribute (which is an MVC filter in essence), you can see if the current request comes from within your domain, and if so, talk to Active Directory for authentication or stuff like that, and on case of successful authentication, create an authentication cookie using FormsAuthentication class, and the rest of the story.
However, I don't think this would be an easy task. Others might introduce better solutions.
I'm trying to implement a small ASP.NET MVC site which interacts with another site. In short, sessions are managed between the main site and satellite sites through tokens in the URL. I can specify the url format but I can't remove the requirement that a session token is submitted as part of the URL.
I'm trying to work out how to set up the routing and am in a few minds here. I can't decide which would be best, or if there is perhaps a better way to do it. The main ways I'm thinking:
routes.MapRoute("Main", "{controller}/{action}/{id}/{token}");
Gives URLs like http://mysite.com/Products/Detail/5/5f1c8bbf-d4f3-41f5-ac5f-48f5644a6d0f
Pro: mostly keeps with existing MVC convention for site nagivation
Con: Adds complication to routing when supporting defaults for ID and Action.
routes.MapRoute("Main", "{token}/{controller}/{action}/{id}/");
Gives URLs like http://mysite.com/5f1c8bbf-d4f3-41f5-ac5f-48f5644a6d0f/Products/Detail/5
Pro: simplifies routing - can still apply action/id defaults as per standard MVC convention
Con: very "un-web-like" URLs. Requires regex to validate that the first variable is a valid GUID / token before moving on to next route in the table.
The other possibility coming to mind, passing sessions like:
http://mysite.com/Home/Index?session=5f1c8bbf-d4f3-41f5-ac5f-48f5644a6d0f
The related problem with that is I have a base class derived from Controller which all other secure pages are going through. The SecureController class overrides Execute() and checks for the validity of the token taken from the URL. Both approaches (GET and routing) seem like it would be easy enough to get the token within the controller Execute() function, but the GET approach feels kind of tacky whereas the routing approach feels like it's, for lack of better explanation, breaking the elegance of the MVC routing design.
Has anyone else out there taken on a similar problem and had any particular successes or difficulties to share?
It seems no matter you do, your URLs will be pretty messy with that token.
I have had to handle this kind of single sign-on functionality in an ASP.NET MVC app as well, but I went for a slightly different and much simpler approach: I created a GatewayController with a SignOn action that took a session token and a URL as parameters.
Then this SignOn action would just check the validity of the session token and then sign the user on to my site, redirecting to the supplied URL. From then on, the session token is not needed anymore, as authentication from then on would be cookie-based.
It might not be entirely applicable in your case, depending on your requirements. If you are required to continuously check the validity of the session token somewhere, you could however just do the same thing as I did and then store the session token in the user's session data, allowing you to check the token in each request.
We are attempting to integrate an ASP.NET MVC site with our client's SSO system using PingFederate. I would like to use the built in FormsAuthentication framework to do this. The way I've gone about it so far is:
Set up my Web.config so that my FormsAuthentication LoginURL goes to my site's "BeginAuthentication" action on a "Security" controller. From this action, I set up some session variables (what URL was being accessed, for example, since Ping won't send this info back to me), and then redirect to our client's login page on an external site (www.client.com/Login for example).
From here, the authentication takes place and a cookie is generated on the same domain as the one that our application is running on which contains the unique identifier of the authenticated user, I've set it up so that once this happens, the Ping server will redirect to my "EndAuthentication" action on my "Security" controller.
In this action, I call my membership class's "ValidateUser" method which takes this unique identifier from the cookie and loads in the user on our application that this ID refers to. I save that logged in user in our Session (Session["LoggedInAs"], for example) and expire the cookie that contains the id of the authenticated user that the SSO system provided for me.
All of this works well. The issue I'm wondering about is what happens after our user has already authenticated and manually goes back to our client's login page (www.client.com/login) and logs in as another user. If they do that, then the flow from #2 above to number 3 happens as normal - but since there already exists an authenticated user on our site, it seems as though the FormsAuthentication system doesn't bother kicking off anything so I don't get a chance to check for the cookie I'm looking for to login as this new user. What I'd like to do is, somewhere in my Global.asax file (probably FormsAuthenticate_OnAuthenticate), check to see if the cookie that the SSO system sends to me exists, and if so, sign out of the application using FormsAuthentication.SignOut().
Another issue that seems to be related is that if I let my Session expire, the FormsAuthentication still seems to think I am authenticated and it lets me access a page even though no currently logged in user exists in my Session, so the page doesn't render correctly. Should I tap into the Session_End event and do FormsAuthentication.SignOut() here as well?
Basically, I want to know when the authentication ticket created by
System.Web.Security.FormsAuthentication.SetAuthCookie(..) gets checked in the flow of a request so that I can determine whether I need to SignOut() and force revalidation or not.
Thanks for any help. Sorry for the length of this message, trying to be as detailed as possible.
Mustafa
Welcome to the small section of Hades that is mixing session with formsauth.
If your needs are as complex as presented, you would get more sleep if you implement a full provider stack to share amongst the participating sites. Easier said than done, I know.
But to address your question:
from http://www.codeproject.com/Articles/39026/Exploring-Web-config-system-web-httpModules.aspx
On the way in....Check ticket and set identity #
app.AuthenticateRequest += System.Web.Security.FormsAuthenticationModule.OnEnter-->OnAuthenticate
On the way out... set the ticket and redirect as necessary
app.EndRequest += System.Web.Security.FormsAuthenticationModule.OnLeave
Reflector is your friend. ;-)
I don't know about a specific event for when the cookie is checked, but you could place the appropriate logic in Application_BeginRequest() and check the user's authentication state there.
Another issue that seems to be related
is that if I let my Session expire,
the FormsAuthentication still seems to
think I am authenticated and it lets
me access a page even though no
currently logged in user exists in my
Session, so the page doesn't render
correctly.
The life of the cookie (how long until ASP.NET feels it needs to ask for a password again) and how you are managing state are unrelated. The ASP.NET authentication is cookie based so that, should a developer want to, he could turn off viewstate, session, use no query strings or hidden fields and authentication still works.
If you want to tie the interval at which you request the password to how you are persisting data, then you will want your session expiration to be roughly the same as the cookie expiration, but they will never quite match up. It would be better to have two policies (one for how fast you throw away a users session data and one for how long you are willing to wait before you need to reask for a password)
I'm working on a project where certain logged in users have a dedicated page which they can choose the url of. When a user logins in i would like to display a link "View my page". I was just wondering what is the best way to store this baring in mind it needs to be accessible for as long as the user is logged in (The site has a remember me feature as well). Would a session variable surfice? or a cookie? Or a custom IPrincipal?
Many thanks
Matt
UPDATE:
What do you guys thing of using the UserData string you can store with the authentication cookie? It seems to satisfy my requirements, but i can't say I know a lot about it.
Forms authentication (based on cookie) should be enough. Here you can read about using FormsAuthentication with custom IPrincipal:
ASP.NET 2.0 Forms authentication - Keeping it customized yet simple
This page is about how forms authentication works:
Explained: Forms Authentication in ASP.NET 2.0
When you use forms authentication, you have Authorize attribute to limit access to controllers and action. It works pretty well. Your own IPrincipal is not necessary. I wouldn't use Session, because it can be easily lost.
Thanks guys, however I have ended up using the UserData string that you can store along with the authentication cookie. This way I know the data will always be available while the user is authenticated. And since I only need to remember simple data (the users url), this seems like a good solution.
Anybody with the same problem can find more info here:
http://www.asp.net/learn/security/tutorial-03-cs.aspx (See step 4)
If what you mean is that you want to display a different custom URL for each user and you simply want to cache that URL then there's a few things to consider:
If you use a session value or a cookie then you need code for the possibility of the value not being present. Both the server session or the browser session could expire and the user could still be logged in.
If you use a cookie you could consider setting the cookie expiry to the same as the authentication cookie expiry but this still doesn't guarantee availability.
A cookie value will not be secure, it could be modified. A session value will be secure.
If you're using custom forms authentication then you could store the URL in the authentication cookie itself and then load it into a custom IPrincipal. I would advise against that as I don't feel it's the right place.
If you're just trying to cache the URL then as long as your code re-fetches the data when the value is not present then a session value or a cookie will be fine depending on the level of security required.
If I have read that wrong and you just want to show/hide a link to depending on whether a user is authorized or not you can simple use
<% if (User.Identity.IsAuthenticated) { %>
view my page
<% } %>
And have your MyPage action in your controller render the dedicated page for the user.