asp.net authentication - use credentials from web.config - problem - asp.net

I have a simple problem which is giving me headaches for a couple of days.
I've created very simple application with login control. I keep user data in web.config file:
<authentication mode="Forms">
<forms name=".RzeskoLoginCookie">
<credentials passwordFormat="Clear">
<user name="test" password="test"/>
</credentials>
</forms>
</authentication>
I will deploy this simple website to IIS on computer on which I do not want to use SQL Server.
My login button event looks like this:
protected void Login1_LoggingIn(object sender, LoginCancelEventArgs e)
{
if(FormsAuthentication.Authenticate(Login1.UserName, Login1.Password))
{
FormsAuthentication.RedirectFromLoginPage(Login1.UserName, Login1.RememberMeSet);
}
}
Now the problem:
When I am running a website on VS2008 built in webserver, everything works fine (I can log in). When I copy my website to IIS I am constantly getting this annoying error (after I click Login button):
Failed to generate a user instance of
SQL Server due to failure in
retrieving the user's local
application data path. Please make
sure the user has a local user profile
on the computer. The connection will
be closed.
I also observed that in my App_Data folder some weird files are being created.
To sum up. What I want to achieve is to use user credentials from web.config file, without using sql server.
I'd appreciate any help
Kind Regards
PK

From the MSDN page for Login control:
*
The Login control uses a membership
provider to obtain user credentials.
Unless you specify otherwise, the
Login control uses the default
membership provider defined in the
Web.config file. To specify a
different provider, set the
MembershipProvider property to one of
the membership provider names defined
in your application's Web.config file.
For more information, see Membership
Providers.
*
The default Membership provider is the AspNetSqlProvider which uses a SQL Server database as its user store.
If you want to provide a custom authentication routine, you can either write your own custom Membership provider or handle the OnAuthenticate method of the Login control to provide your own authentication logic.

If you notice in your code, you have the method declaration for handling the <asp:Login> control's LoggingIn event:
protected void Login1_LoggingIn(object sender, LoginCancelEventArgs e)
This control interfaces with the ASP.NET Membership provider which is probably why it is looking for a connection string.
So rather than using the <asp:Login> control, simply use a button and handle the Click event so that there is no use of Membership:
<asp:Button id="LoginButton" Text="Login" OnClick="Login_OnClick" runat="server" />
Code behind (notice the different signature of the method):
public void Login_OnClick(object sender, EventArgs args)
{
if(FormsAuthentication.Authenticate(Login1.UserName, Login1.Password))
{
FormsAuthentication.RedirectFromLoginPage(Login1.UserName, Login1.RememberMeSet);
}
}

Ok, thanks everybody for pointing out the solution.
I finally managed to avoid that error by creating my own authentication event (associated with the login control).

Related

ASP.net Identity can't login

I'm using Asp.net Identity and I've deployed my web role to Azure, and changed my connection string in Web.config so it looks like this:
<connectionStrings>
<add name="DefaultConnection" connectionString="Server=SERVERNAME,1433;Database=DATABASE;User ID=USER;Password=PASSWORD;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" />
</connectionStrings>
I haven't changed default Account controller, but when I try to Login nothing nothing happens except that URL changes to "/Account/Login?ReturnUrl=%2FRoutines" which should happen if user successfully logged in (no errors are shown)
Why is this happening ? (and how can I fix it)
EDIT
Here is code which configures ASP.net Identity
public class DatabaseContext : IdentityDbContext<User>
{
public DatabaseContext()
: base("DefaultConnection")
{
Configuration.LazyLoadingEnabled = true;
}
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>()
.ToTable("Users");
modelBuilder.Entity<User>()
.ToTable("Users");
var usermapping = new UserMapping();
usermapping.MapUser(modelBuilder);
}
I've noticed that now even when I'm using LocalDb I can't Log in, and I don't know why is this because, I haven't changed my code, only changes that I made to the project is Added Azure web service, and Asp.net web Api 2 project (and when I've tested locally I didn't run my web api project), before this everything worked fine.
Are you sure your connection is really used when you deploy (in Web.config.release)?
In case you are, try testing the website locally (with the Azure SQL connection string) and stepping through the code for POST version of Login. There you should be able to see, what exactly is going on. You will probably need to enable access to SQL from your IP address, which is easy to do - just go to Azure Portal, click on your SQL database and down below select Manage, which will automatically ask you for your IP address access permission.
I don't know what I exactly happened, but I've fetched older version of solution from TFS and that helped (eve though code was same)

asp.net session logout

I have made an asp.net application. This application has session variables which shows that a user is logged in or logged out.
If there any way to capture the expiration of session without going to single pages and once this is logged out user can be redirected to login( Re-login) page?
Can my asp.net classes inherit some base class which can have some abstract method to check if session is existing or not.
Please suggest me some architecture to do this.
Thanks in advance.
This application has session variables which shows that a user is logged in or logged out.
This can be achieved by checking the HttpContext.Current.Request.IsAuthenticated property.
If there any way to capture the expiration of session without going to single pages and once > this is logged out user can be redirected to login( Re-login) page?
Configure the following elements in your applications web.config to restrict\allow access to resources\pages\directories on your site:
<authorization>
<allow .../>
<deny .../>
</authorization>
http://msdn.microsoft.com/en-us/library/8d82143t
And, configure the FormsAuthentication defaulturl and loginurl attributes to redirect users away from restricted resources.
You can use global.asax's session end event:
void Session_End(Object sender, EventArgs E) {
// your code....
}
When the session expire this event called.

Give access to the corresponding asp page based on user id and password enter in login control

I have two folders "Admin", and "User" folders in my ASP.NET web application project. Under the Admin folder there is a "Admin.aspx" page, and under the User folder there is a "User.aspx" page. I have another page called "Login.aspx" under the Account folder. For this login page, I have used the built-in Login control from the toolbox. Based on id and password given in the fields the corresponding webpage must be invoked. For example, when I enter the username as "admin" and password as "password" (basically admin user), it should load the Admin.aspx page. On the other hand when the username is "mike" and password is "mike123"(basically normal users), the application should load User.aspx page. I have already created the required access rules for the "Admin" and "User" folders by using the "ASP.NET configuration" wizard. My issue here is mapping the corresponding aspx page based on id and password entered.
Your question is a bit vague, I am assuming you are using the standard SqlMembership provider and forms authentication.
Using the Web Site Administration Tool to manage your logins provides the mechanism for authentication. I suggest to configure and use User Roles to define access to web site functionality.
To redirect to a specific page depending on roles looks like:
Handle the LoggedIn event of the Login control.
protected void LoginControl_LoggedIn(object sender, EventArgs e)
{
try
{
if (HttpContext.Current.User.IsInRole("Site Admin"))
{
Response.Redirect("~/Admin/Admin.aspx");
}
else if (HttpContext.Current.User.IsInRole("User"))
{
Response.Redirect("~/User/User.aspx");
}
catch (Exception ex)
{
Debug.WriteLine("Exception in d: " + ex.Message);
throw;
}
}
You also need to provide access to the Login.aspx page outside of the secure sections of the site via the web.config.
<authentication mode="Forms">
<forms name="MyApplication" loginUrl="~/Account/Login.aspx" timeout="60">
</forms>
</authentication>
This is just one of any number of solutions you could implement. There are many resource online to help you get this going.
protected void Login1_LoggedIn(object sender, EventArgs e)
{
String[] users = Roles.GetRolesForUser(Login1.UserName);
if (users.Contains("admin"))
{
Response.Redirect("~/Admin/Admin.aspx");
}
else if (users.Contains("users"))
{
Response.Redirect("~/Secure/User.aspx");
}
}

ASP.NET impersonates NT AUTHORITY\IUSR but impersonation is disabled. ASP.NET bug?

I have an ASP.NET 4.0 application running on Windows 7 / IIS 7.5 in the "ASP.NET v4.0 Classic" application pool, which is configured to run as Network Service. The application has an Application_EndRequest handler which connects to a local SQL Server instance. The SQL connection string specifies Integrated Security=SSPI. Web.config does not have <identity impersonate="true" />.
When I browse to http://localhost/TestSite/, the following exception is thrown:
System.Data.SqlClient.SqlException (0x80131904): Login failed for user 'NT AUTHORITY\IUSR'.
...
at System.Data.SqlClient.SqlConnection.Open()
at Global.Application_EndRequest(Object sender, EventArgs e)
This exception is not thrown when I browse to http://localhost/TestSite/default.aspx (the default document configured in IIS) or any other .aspx page; in those cases the application correctly connects to SQL Server as "NT AUTHORITY\NETWORK SERVICE", which is a valid login.
Why would ASP.NET impersonate "NT AUTHORITY\IUSR" in EndRequest even though impersonation is disabled? Is this a bug in ASP.NET?
The following Global.asax.cs file demonstrates the problem:
public class Global : HttpApplication
{
public Global()
{
this.BeginRequest += delegate { Log("BeginRequest"); };
this.PreRequestHandlerExecute += delegate { Log("PreRequestHandlerExecute"); };
this.PostRequestHandlerExecute += delegate { Log("PostRequestHandlerExecute"); };
this.EndRequest += delegate { Log("EndRequest"); };
}
protected void Application_EndRequest(Object sender, EventArgs e)
{
try
{
using (SqlConnection connection = new SqlConnection("Server=.;Integrated Security=SSPI"))
{
connection.Open();
}
}
catch (Exception ex)
{
Trace.WriteLine(ex);
}
}
private static void Log(string eventName)
{
HttpContext context = HttpContext.Current;
Type impersonationContextType = typeof(HttpContext).Assembly.GetType("System.Web.ImpersonationContext", true);
Trace.WriteLine(string.Format("ThreadId={0} {1} {2} Impersonating={3}",
Thread.CurrentThread.ManagedThreadId,
context.Request.Url,
eventName,
impersonationContextType.InvokeMember("CurrentThreadTokenExists", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetProperty, null, context, null)));
}
}
Here's the trace output:
ThreadId=3 http://localhost/TestSite/ BeginRequest Impersonating=False
ThreadId=3 http://localhost/TestSite/ PreRequestHandlerExecute Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx BeginRequest Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx PreRequestHandlerExecute Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx PostRequestHandlerExecute Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx EndRequest Impersonating=False
ThreadId=7 http://localhost/TestSite/ PostRequestHandlerExecute Impersonating=True
ThreadId=7 http://localhost/TestSite/ EndRequest Impersonating=True
System.Data.SqlClient.SqlException (0x80131904): Login failed for user 'NT AUTHORITY\IUSR'.
...
at System.Data.SqlClient.SqlConnection.Open()
at Global.Application_EndRequest(Object sender, EventArgs e)
Note that a request to TestSite/ (which is mapped to DefaultHttpHandler) seems to spawn a nested request to TestSite/default.aspx (which is mapped to ASP.default_aspx). After ASP.NET finishes processing TestSite/default.aspx, it impersonates "NT AUTHORITY\IUSR" when it resumes processing the request to TestSite/.
UPDATE: I've submitted this issue to Microsoft Connect.
Most likely, the settings for your server, site or application are set so that "Anonymous Authentication" mode causes page requests to be handled as the IUSR user. It doesn't matter that your application is not requesting impersonation; IIS is forcing it. (By the way, "impersonation" is generic term in Windows-land for assuming another user's credentials. It is not specific to ASP.NET.)
A bit of background:
For security reasons, IIS allows your server to field "anonymous" and "authenticated" requests under different system credentials.
Now, in IIS 7.5, if you have both anonymous authentication and Forms authentication enabled (which is typical), before your website user logs in via Forms, it considers your user "anonymous". After your user logs in with Forms Auth, it considers your user "authenticated."
I found this behavior confusing at first because it's a change from IIS 6.0, which wasn't aware of Forms auth, and considered all Forms-Authenticated users to be anonymous!
If you want, you can change the identity under which anonymous requests are fielded. My preference (and it sounds like yours too) is that they run under the same system credentials as my site's app pool. To make IIS do that, do the following:
Open the IIS Manager (inetmgr)
In the "Connections" panel, drill down to your site's node and select it
In the right-hand panel, under the "IIS" group, double click the "Authentication" icon.
Right-click on "Anonymous Authentication" and choose "Edit..." from the context menu.
In the popup dialog, select the "Application pool identity" radio button.
Click OK.
Step 5 also confused me at first, because I thought "application pool identity" meant "the application pool pseudo-account" (another new feature in IIS 7.5). What it really means, of course, is "the same account the app pool is configured to run under, whatever that is."
If you want this behavior by default for all of your websites on that server, or even just single application under a particular site, you can configure the authentication options at those levels too. Just select the node you want to configure in the Connections pane, then repeat steps 3-6.
Why would the application attempt to log in as "NT AUTHORITY\IUSR" even though the application is (probably) not using impersonation?
If you do
<identity impersonate="true"/>
it will impersonate the logged in user
If you do
<identity impersonate="true" userName="contoso\Jane" password="pass"/>
it will impersonate the user set above.
But if you don't impersonate at all and use windows authentication, it would make sense that it uses a default system account.
I do not know why it makes the first attempt as IUSR and then automatically switches to NETWORK SERVICE on subsequent requests. But I do know that when you jump from one server to another, the application pool credenticals are NOT used. Unless you set an impersonated user as shown below, NETWORK SERVICE is default account that is used to fetch resources outside the server.
<connectionStrings>
<add name="myConnectionString" connectionString="Data Source=MyServerName;Initial Catalog=MyDataBaseName;Integrated Security=True;"
providerName="System.Data.SqlClient" />
</connectionStrings>
<identity impersonate="true" userName="contoso\Jane" password="pass"/>

ASP.NET: Authenticating user in code

I'm playing around with authentication and authorization to prepare for some task. I've created two pages: Login.aspx and Default.aspx. In config file i've set authentication to forms and denied unauthenticated users access:
<authentication mode="Forms">
<forms name="aaa" defaultUrl="~/Login.aspx" />
</authentication>
<authorization>
<deny users="?"/>
</authorization>
Then I've written some simple code to authenticate my user in Login.aspx:
protected void Page_Load(object sender, EventArgs e)
{
GenericIdentity identity = new GenericIdentity("aga", "bbb");
Context.User = new GenericPrincipal(identity, new String[] { "User" }); ;
Response.Redirect("~/Default.aspx");
}
When i run it, the redirection doesn't take place. Instead Login.aspx is called over and over because the user is not authenticated (Context.User.Identity.IsAuthenticated is false at every load). What am i doing wrong?
Context.User only sets the principal for the current request. Once the redirect takes place, the current request ends and a new one begins with the non-overridden principal again (which is apparently not authenticated). So, setting Context.User doesn't actually authenticate anything.
Using FormsAuthentication.SetAuthCookie() will set the user's cookie to a valid value accepted by the FormsAuthentication provider, or put the token in the URL. You can redirect to your heart's content because the cookie obviously sticks with the user for future requests.
From MSDN (em added):
With forms authentication, you can use the SetAuthCookie method when you want to authenticate a user but still retain control of the navigation with redirects.
As stated, this does not necessarily require cookies - the name is a little misleading, because it will still work via the URL if FormsAuthentication is in cookieless mode:
The SetAuthCookie method adds a forms-authentication ticket to either the cookies collection, or to the URL if CookiesSupported is false.
Use FormsAuthentication.SetAuthCookie(..). Or FormsAuthentication.RedirectFromLoginPage(..).
You need to actually set the user as authenticated. All of the following methods will work and let you actually get away from your login screen.
FormsAuthentication.Authenticate()
FormsAuthentication.RedirectFromLoginPage()
FormsAuthentication.SetAuthCookie()
Lots of ways to get to the same result.
You need to actually make a call to the formsAuthentication provider to set the login.
FormsAuthentication.RedirectFromLoginPage(txtUser.Text, chkPersistLogin.Checked)
is a simple example
After creating the dummy Context.User, you need to perform a FormsAuthentication.SetAuthCookie or RedirectFromLoginPage method.

Resources