How to bypass forced login for a token authenticating service? - asp.net

OK so whenever anyone hits our site who is not logged in, it pushes to the login page and has them sign in, and then pushes them back to the page they attempted to access. I have been tasked to create a service (using ASHX) that returns reporting data via xml. This is all done, however in order to access it you have to be logged in. Instead of logging in I am going to have them pass a token through query string to authenticate that it is a valid request. However I am unsure how to go about bypassing the forced login. Is this too vague or does anyone have any ideas? I suppose the last ditch effort would be to create a totally separate site in ISS but I would like to avoid that if possible.

One way to do it in the same site would be to have your service accessible anonymously, then do your own authentication inside the service against the token.
Edit:
To allow anonymous, add a section to your web.config that allows full access to a directory that contains your service. For example, your service is http://www.foo.com/Services/bar.asmx.. Add this to your web.config where your other authorization sections are:
<location path="Services">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
Then, in your service, authenticate your token you've passed in however you want to. If the authentication doesn't pass, throw a SoapException. How to authenticate all depends on how you are currently authenticating in your login page..
Hope this helps.

Just change your sign in page to check the referrer or URL for your details.
If it finds it, automatically make it authenticate this user you have setup.
Eg.
// In your signin aspx file
bool bYourCriteriaIsMet = true; // do something here like check the referrer or querystring etc..";
if (bYourCriteriaIsMet)
{
FormsAuthentication.RedirectFromLoginPage("Your Temp User Name", false);
}
Just figure out what you need to verify and then do the redirect manually.
You could also just have the page you want accessible in the NON secured area like where your sign in page exists then anyone will be able to access it without having to worry about all this redirect and authentication stuff.

Related

Allow roles not working but allow users working in web.config

I implemented asp.net membership for forms authentication. Generally for login it is used username, but i changed this to login with email id. Which is working fine. Now i am trying to restrict access to the users which are not in Admin role. I created web.config file in that folder i written like this.
<?xml version="1.0"?>
<configuration>
<system.web>
<authorization>
<allow roles="Admin" />
<deny users="*"/>
</authorization>
</system.web>
</configuration>
When i tested with this one even though the users who is having the admin role is not able to access. When he clicks the link he is signing out (like the user doesn't have permission to access the page). For showing menu i am using web.sitemap file. It is working fine based on roles.
Code in the web.cofnig file under that particular folder is correct as per MSDN. I don't know why it is not working. If we change membership controls default login behavior then any thing should take care about roles?
Many questions to similar were found in stackoverflow as well as in some other sites also. But nothing gives me solution. Whats wrong in this? Need to write any custom code to handle?
For allowing users i written like below. It is working perfect
<?xml version="1.0"?>
<configuration>
<system.web>
<authorization>
<allow users="master#yahoo.com" />
<deny users="*"/>
</authorization>
</system.web>
</configuration>
Why it is not working only for roles?
RoleProvider use GetRolesForUser method to retrieves authorized roles for a user.
// Notice that it accept username instead of email
public string[] GetRolesForUser(string username)
In your case, your RoleProvider passes master#yahoo.com as username. As the result, there is no username with master#yahoo.com in User table.
Here are solutions -
1) The easiest way to solve the problem is copy Email column of Memberships table to UserName column of Users table.
2) The hard way create custom RoleProvider and override GetRolesForUser method.
3) If you happen to use legacy Membership Provider instead of Universal Membership Provider, you can modify aspnet_UsersInRoles_GetRolesForUser.
I used another approach. I didn't changed the login with emailid. I am logging with email only. But problem is coming because by default, role provider verify with user name instead of email. For that i changed login behavior. So when ever user login i used to give the login control value like below.
string username = Membership.GetUserNameByEmail(Login1.UserName);
if (username != null)
{
isUser = Membership.ValidateUser(username, Login1.Password);
}
if (isUser)
{
Login1.UserName = username;
e.Authenticated = true;
}
I am writing this code in the Login page. So after successful login, the loginview will update accordingly. Now it is working perfect.
The answer given by Win also good one. If we want to show only email id in LoginView instead of user name we have to implement this method.
public string[] GetRolesForUser(string username)
To get the user name by email we can write like
string username = Membership.GetUserNameByEmail(Page.User.Identity.Name)

Making a page secure

I am building a ASP.NET website that has members pages. I have created a folder where I keep the members pages in and that can only be accessed by logging in or creating a new account. The problem is how do I make the url of these members pages secure, so that someone cant simply give the url to another user for them to copy into a browser or bookmark. Any suggestions greatly appreciated.
In web.config you need specify that this folder for permitted user only.
To grant individual security (person against person) just add checking (for example at Page_Load) that member is permitted to see this page and throw HttException with code 403 (forbidden)
You can do this through the Authentication element in your web.config.
http://support.microsoft.com/kb/316871 has details on this but roughly you will add things that look like this:
<location path="subdir1">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
This will deny access to that subdir to all anonymous users.
To quote the MSDN page above:
When using forms-based authentication
in ASP.NET applications, only
authenticated users are granted access
to pages in the application.
Unauthenticated users are
automatically redirected to the page
specified by the loginUrl attribute of
the Web.config file where they can
submit their credentials. In some
cases, you may want to permit users to
access certain pages in an application
without requiring authentication.
Edit:
In response to your edit of testing user pages then there are two ways I can think of that this might work. If the page is specific to a given user then you can just make sure that in the code rather than getting the user details from the url that you look up who the logged in user is and give them their page. So for example if you are currently looking at members/mypage.aspx?user=bob then instead just link to members/mypage.aspx and in the code get the name of the logged in user to use. Then there is no way to tell the code that you want Bob's page without being Bob.
In the more likely event that you have groups of users (eg admin) that can see a page then you will need to put some code on your page to check permissions. For a given page you will need to work out who can view it somehow (eg by lookign up that page against the allowed user roles to get a list of roles) and then check if the logged in user is in that list of who can view (does the user have one of those roles.
eg Bob is an admin and Frank isn't. When going to your admin.aspx page you first of all lookup admin.aspx and find out that roles Admin and SuperAdmin are allowed to view it. You then look up the logged in user and iterate through their roles til you find one in the allowed roles list. If you find one process the page as normal, if you don't then either redirect somewhere else or throw an exception (eg throw your own MyAccessDeniedException that gets caught in your global event handler and shows a message explaining the user doesn't have permissions).
All of this can be done in a base class of your page to prevent you having to include the code on every page. That is you can create MyPage that inherits from Page and in the onload (or oninit or wherever you fancy) of MyPage run this security check. Then all the pages of your site inherit from MyPage instead of Page and you immediately get the functionality on all pages.
Hopefully this answers your questions.

How to get ASP.NET Forms Authentication (using role restrictions) to not redirect to login page

Does anyone know of a way to get ASP.NET Forms Authentication to not redirect back to the login page if a user is not allowed to visit a certain page or folder based on their role (and perhaps show a message instead)?
The redirect happens because the user is not authorized to see the page - not because she is not authenticated with the system. As such, the framework does not distinct between the situation where a user is "not logged in" and the situation where she is just "missing the required role". If she does not have acccess, she is redirected to the login page - end of story.
What I usually do, is to create my login form with a MultiView with a view for each of the two cases, as well as one for the case where the user asked for the login form himself. Then I do something like this to toggle between the different views:
if (Request.QueryString["ReturnUrl"] == null)
myMultiView.ActiveViewIndex = 0; // user asked for login form
else if (Request.IsAuthenticated)
myMultiView.ActiveViewIndex = 1; // insufficient rights
else
myMultiView.ActiveViewIndex = 2; // login required
Rather than using a MultiView you could also insert a Response.Redirect in branch above, if this seems to make more sence in your application - e.g. if the three login forms are significantly diverse.
If you don't want it to redirect back to the login page, then what page do you want to resolve, the requested page, which they don't have access to? If so, and if you want that URL to be in their address bar, then you will need to override the base ASP.NET page, and prevent the continuation of rendering, and instead return an simple page with a pop up message or something.
I think you'll have to change the authorization in web.config for the given page's location so that everyone is authorized.
<configuration>
<location path="somepage.aspx">
<system.web>
<authorization>
<allow users="?"/>
</authorization>
</system.web>
</location>
</configuration>
Then you can use Roles.IsUserInRole() in the page logic to determine if they are authorized, and then display a message if they are not. I've done this before when I use the same aspx page for viewing and editing a record where anyone can view but only certain roles can edit.
4GuysFromRolla have a pretty detailed tutorial on how to use the membership provider. The link provided gives you details about how to apply user- and role-based authorization rules to methods and classes.
Hope this helps some.

ASP.NET: directing user to login page, after login send user back to page requested originally?

I am trying to manually implement a login system in ASP.NET 3.5. Basically, on load, I would like the site to check and see if user object is active, if not, than I want the login page to appear.
After user has logged in successfully, I would like the user to be able to access the same page he has requested originally.
for example:
user request to: MyPage.aspx - not logged in
login page appears instead of MyPage.aspx
user logs in successfully
MyPage.aspx appears instead of Default.aspx for example
Peering at the System.Net namespace, I see that there is an "HttpWebRequest Class" which has a "HttpWebRequest.AllowAutoRedirect Property" but am unsure how that would get me back from the login page.
NOTE: I know there are automatic authentication systems setup in ASP.NET, but I would like to have manual control over the database.
-- Tomek
What you could do, if you don't want to actually use the built in Forms Authentcation is:
Check if the user is authenticated on each page you want to hide from anonymous users. If they are not authenticated, redirect them to your login page with the URL in the query string.
if(!HttpContext.Current.User.Identity.IsAuthenticated) {
Response.Redirect(~/login.aspx?redirect=this_page.aspx");
}
Then on your login page, after a user logs in. Check the query string to see if there is a redirect parameter.
if(!String.IsNullorEmpty(Request.QueryString["redirect"]) {
string url = ResolveClientURL(redirect);
Response.Redirect(url);
}
Of course this is all built into .NET using Authentication, where you can deny anonymous access to certain directories, and when you do that, .NET will redirect to your login page (which is set in the web.config) and will include a "ReturnURL=blahblah" on your login page.
Just an FYI.
Just save the originally requested url in Session or a hidden field on the login page
After successful login, use Server.Transfer or Response.Redirect to jump to that page.
It looks like another method is described here. It seems that you can use the following object to return from the login page:
FormsAuthentication.RedirectFromLoginPage
Yet, according to the article, the better method is to use what JackM described, but with an overload:
Response.Redirect("~/default.aspx", false);
In doing so, you prevent the Session from ending when the page is redirected.

Prevent visitors from opening certain pages

I have as ASP.Net 2.0 website with SQL Server as database and C# 2005 as the programming language. The website is almost complete and all the links are working fine. But I want to prevent normal users from opening a couple of pages. When any user clicks on those specific links, another page opens which contains a ASP Login control. The user has to supply a valid userid and password to display the links pointing to the restrictive pages. But being a newbie, I don't know how to leverage the full power of the ASP Login control. Because, if a user gets to know the exact url of the restricted pages, then he/she can bypass the login control and directly access those pages by typing the url into the address bar. I want to prevent this. If the user types the url directly in the address bar, I want that the page itself should check, whether the user has been validated through the Login control and either display the page or point the user to the Login page.
How do I implement this feature??
Thank You.
Lalit Kumar Barik
You'll want to take a look at the location secton of the web config.
In that section, you can define down to the page level the access rights, so it wouldn't matter if the users knew the URL of the secured pages, ASP.NET wouldn't let them in.
So you would add something like:
<location path="SecuredPage.aspx">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
The "deny users="?"" bit says "Deny all anonymous users".
You can also set it up to only allow certain roles, if you are using those.
More information on the Authorization section can be found here:
authorization Element
This is food for the ASP.Net Membership services. Take a look at this article and also the great series over at 4GuysFromRolla.
Membership allows you to store user/password information which is used, among others, by the Login control. Coupled with the authorization configuration you will be able to directly narrow access to specific pages down to specific users or roles.
You will need a way to manage login sessions for each user. The following are some tutorials that could help you:
http://www.codeproject.com/KB/session/NoCookieSessionLogin.aspx
http://www.dotnetspider.com/resources/5597-Handling-Session-for-Login-Logout.aspx
You should verify the user's logged in state at every Page_Load() event on pages that must control permissions, or simply put the authentication code in a CS file that will be included in all other files.
Depending on the authentication architecture that you choose (simply use the session variable, or create a session id with cookies), you must adapt your code accordingly.
The simplest way would be to manage log-ins through the session object. When the user logs in properly with the right credentials, you can set Session["logged_in"] = true. And on every Page_Load() event of the pages you want to protect, you'd need to do the following check.
Add this code at the beginning of your Page_Load() function:
if (Session["logged_in"] != null && (bool)Session["logged_in"] == true){
Response.Write("I'm logged in!");
}else{
Response.Write("I'm not logged in.");
}
Please keep in mind that this is okay for simple intranet applications, but if you want to get into more secure login architectures, read up more about the subject, as reloying solely on session variables isn't safe because sessions can be highjacked.
I would make a role table for users. Everyone who logs in gets the 'normal' role. Special uses whom you designate by their credentials get assigned roles to access a page or section of your website. Certain users (like yourself) would get an administrator role that automatically allows them access to everything.
Fire off a function called CheckIsInRoles('Admin', 'Normal', 'WhateverRoleYouChoose') which returns a boolean. If true, load the page; if not, don't.
Even better don't display a link if not in the correct role.
This has the added benefit of everyone logging on once and then accessing all the pages they need to without having to log on each time.

Resources