I downloaded CSLA.NET for .NET 2.0 and everything works fine with the PT Sample Project. I am now only converned about the Web UI (PTWeb).
This project is using Forms Authentication, and I need to use Windows Authentication.
Can some one help me to get started ?
Any documentation/sample code available ?
Please note that I am preparing a sample demo for the Management to show the benefit of CSLA.NET by applying it to one of the existing small projects in our environment, and I have to do that in a relatively short period.
You help will be greatly appreciated.
Regards ...
Tarek.
You have not explained the requirements in enough detail.
Do you need to use Windows Authentication only? Or do you also need to use it for Roles for Authorization?
In my Web app I allow both UID/PWD or Windows Authorization. When configured for Windows, I am only intercepting the principal in order to extract the Domain and UID from it. My DB has the same username and Domain fields so I can use these 2 Windows values to do a lookup and let them in or not. If I let them in then they end up using a CSLA principal filled with roles and permissions from my DB. So my config file still reads CSLA Authorization even though I am using Windows to get the UID. This allows the client to have "single sign on". I believe that I also have code to add a Forms Cookie so that Forms Auth will let them in too.
Joe
JoeFallon1:You have not explained the requirements in enough detail.
Do you need to use Windows Authentication only? Or do you also need to use it for Roles for Authorization?
...
I found another thread discussing the same issue, and I will continue there:
http://forums.lhotka.net/forums/22785/ShowThread.aspx#22785
Appreciate your comments and help.
Tarek.
I am posting here the details of the changes needed to implement Dual Authentication:
1. Changed/confirm that web.config has the following tags: Add imporsonation/allow/deny rules as needed, and the other thing will be almost the same:
<AUTHENTICATION mode="Forms">
<FORMS name="CSLASample" loginUrl="Login.aspx" />
</AUTHENTICATION>
<IDENTITY password="password" userName="username" impersonate="true" />
<AUTHORIZATION>
<DENY users="?" />
<ALLOW roles="xxxx" />
<ALLOW users="*" />
</AUTHORIZATION>
2. Add the following code to App_Code or to a Class Library Project:
Public Shared Function ValidateUserWindows(ByVal username As String) As Boolean If MyPrincipal.LoginWindows(username) Then System.Web.HttpContext.Current.Session("CslaPrincipal") = _ Csla.ApplicationContext.User Return True Else Return False End If End Function Public Shared Function GetWindowsLoginIDWeb() As String Dim strUserID As String With System.Web.HttpContext.Current strUserID = .Request.ServerVariables("LOGON_USER") If strUserID = "" Then .Response.StatusCode = 401 .Response.StatusDescription = "Unauthorized" .Response.End() Else Dim idx As Integer idx = strUserID.IndexOf("\") If idx >= 0 Then strUserID = strUserID.Substring(idx + 1) End If End If Return strUserID End With End Function
3. Add the following code to your custom Principal.vb Code:
Public Shared Function LoginWindows( _ ByVal username As String) As Boolean Dim identity As MyIdentity = MyIdentity.GetIdentity(username) If identity.IsAuthenticated Then Dim principal As New MyPrincipal(identity) Csla.ApplicationContext.User = principal End If Return identity.IsAuthenticated End Function
4. Add the following code to your custom Identity.vb code:
Friend Shared Function GetIdentity(ByVal username As String) As MyIdentity Return DataPortal.Fetch(Of MyIdentity)(New Criteria(username)) End Function
5. Modify the Criteria Class Definition as follows:
<Serializable()> _
Private Class Criteria Private mUsername As String Private mPassword As String Private mIsWindowsLogin As Boolean Public ReadOnly Property Username() As String Get Return mUsername End Get End Property Public ReadOnly Property Password() As String Get Return mPassword End Get End Property Public ReadOnly Property IsWindowsLogin() As String Get Return mIsWindowsLogin End Get End Property Public Sub New(ByVal username As String, ByVal password As String) mUsername = username mPassword = password mIsWindowsLogin = False End Sub Public Sub New(ByVal username As String) mUsername = username mIsWindowsLogin = True End Sub End Class
6. Modify the DataProtal_Fetch of the custom Identity as follows:
Private Overloads Sub DataPortal_Fetch(ByVal criteria As Criteria) 'Using cn As New SqlConnection(Database.SecurityConnection) Using cn As New OleDb.OleDbConnection(Database.AppSecurityDB) cn.Open() Using cm As OleDb.OleDbCommand = cn.CreateCommand If criteria.IsWindowsLogin() Then cm.CommandText = "LoginWindows" cm.Parameters.AddWithValue("prmUser", criteria.Username) Else cm.CommandText = "Login" cm.Parameters.AddWithValue("@user", criteria.Username) cm.Parameters.AddWithValue("@pw", criteria.Password) End If cm.CommandType = CommandType.StoredProcedure Using drLogin As OleDb.OleDbDataReader = cm.ExecuteReader() If drLogin.Read() Then mName = criteria.Username mIsAuthenticated = True drLogin.Close() cm.Parameters.Clear() cm.CommandText = "GetUserRoles" cm.Parameters.AddWithValue("prmUser", criteria.Username) Using drRoles As OleDb.OleDbDataReader = cm.ExecuteReader While drRoles.Read mRoles.Add(drRoles.GetString(0)) End While End Using Else mName = "" mIsAuthenticated = False mRoles.Clear() End If End Using End Using End Using End Sub
(Note: The above code was changed to connect to MS Access Database instead of SQL Server.)
7. In the Login.aspx Page, add a button or Link, in addition to the User Name/Password Login Control, and add the following code to login as Windows User:
Protected Sub lnkLoginWindows_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles lnkLoginWindows.Click Dim strUserID As String = MyMembershipProvider.GetWindowsLoginIDWeb() If MyMembershipProvider.ValidateUserWindows(strUserID) Then
' Check if this user has logged in before Dim LoggedInStaff As StaffBasicInfo = CType(Session("LoggedInStaff"), StaffBasicInfo) If LoggedInStaff Is Nothing Then
' If not, get his details from back-end system. LoggedInStaff = StaffBasicInfo.GetStaffBasicInfo(strUserID) Session("LoggedInStaff") = LoggedInStaff End If FormsAuthentication.RedirectFromLoginPage(strUserID, False) Else Response.Redirect("Login.aspx") End If End Sub
Note: the code above has minor bug about redirection, in case the first page was openened is the Login Page. Need to check the Query String Parameter to find out if there is a "redirect to" page to handle this part correctly.
I hope the above code will of value to you.
Regards ...
Tarek.
I am posting again to get your feedback/opinion about improving the authentication technique introduced here.
Our environment is actually a bit complicated, since we have different platforms (Adabs/Unix, SQL Server, MS Access, MySQL, VB.NET, PHP...etc.), and the purpose of the web applications we are developing is to provide unified front-end to the users for certain functionality, which may spread across those platforms.
The user will navigate to the web application which has public part, and secured part. When the user is not logged on, he is anonymous, and he can view the public part.
When he tries to access the secured parts, he is redirected to the Login.aspx page, and he will have 2 options: Login as Public User (Forms Authentication) or Login as Integrated Windows User.
When the user clicks on "Login as Windows User" I am defining the user as authenticated if:
1. The user has Windows Domain Account, meaning:
StaffID = Request.ServerVariables("LOGON_USER")
StaffID should have a value and it will be the Staff ID,
And
2. If this StaffID is defined as Active Staff in Adabas Staff Master Table (must connect to CONNX SQL Gateway via ODBC or OLEDB),
And
3. If StaffID is not defined in Adabas, this means he could be a temporary contract Staff and he may be defined in the Attendance System Staff Table (MS Access Database).
And, when the user clicks on "Login as Public User" (Forms Authentication), he will be defined in the SQL Security Database which has Table for UserID, Password and other details such as First Name and Last Name. In this case, the user is a client and he is not a company employee, and he may be accessing our systems to get a statement of account or follow on the status of a project for example.
In all other cases not mentioned above, the user is anonymous.
I need to modify the "DataPortal_Fetch" of the custom Identity object to handle all the above cases, which to use 3 different Database connections.
If you look at the code in DataPortal_Fetch, it has "USING - END USING" block, and I am a bit lost on how to do that, since this will make code looks very confusing and complicated when it will involve connecting to 3 different Database according to the type of the login request and the user, which will require 3 command objects and 3 DataReader Objects.
The Questions:
1. What do you think about this approach ?
2. How to simplify the coding ?
3. If you think it is approach complicated, do you have other alternatives to achieve this objective ?
Tarek.
I introduced this method for authentication to my colleagues, and one of them was not happy, because we have to add 3 connection strings in the web.config for each web application for the purpose of authentication.
One way to avoid this, is to build all these connection strings in SQL Server using Linked Servers, but I am not happy with this since it may result into future problems due to issues with linked servers, as we are now facing a problem in displaying Arabic Text properly for Linked Servers from Adabas Database Tables.
In general, I prefer to have a direct connection to the Database, and handle Data Access one at a time from each Database using .NET code. I feel that this method is more appropriate, more flexible and less possibility to face errors.
Any help or comment will be appreciated.
Tarek.
Well, you have a complicated
infrastructure, so you are likely to have a complicated solution. ;(
One option would be to set up a job that
runs every 5 minutes or so (maybe every half-hour or hour depending …)
that slurps the info about employees into your security info database. That
way, only one application needs to know how to access all three databases, the
rest of the applications get one-stop shopping.
Of course, those same apps may need to
know how to connect to multiple databases anyway, which defeats the simplicity
advantages of the above option. ;)
As for the scenario you outlined, you
don't need 3 connection objects. You only need one. Just re-use it.
J
From: tarekahf
[mailto:cslanet@lhotka.net]
Sent: Saturday, September 13, 2008
5:58 AM
To: david_wendelken@nc.rr.com
Subject: Re: [CSLA .NET] How to
use Windows Authentication with CSLA.NET?
I am
posting again to get your feedback/opinion about
improving the authentication technique introduced here.
Our
environment is actually a bit complicated, since we have different platforms
(Adabs/Unix, SQL Server, MS Access, MySQL, VB.NET, PHP...etc.), and the purpose
of the web applications we are developing is to provide unified front-end to
the users for certain functionality, which may spread across those platforms.
I am defining the following business
logic for an authenticated user.
The user
will navigate to the web application which has public part, and secured part.
When the user is not logged on, he is anonymous, and he can view the public
part.
When he
tries to access the secured parts, he is redirected to the Login.aspx page, and
he will have 2 options: Login as Public User (Forms Authentication) or Login as
Integrated Windows User.
When the
user clicks on "Login as Windows User" I am defining the user as
authenticated if:
1. The
user has Windows Domain Account, meaning:
StaffID = Request.ServerVariables("LOGON_USER")
StaffID
should have a value and it will be the Staff
ID,
And
2. If
this StaffID is defined as Active Staff in Adabas Staff Master Table (must
connect to CONNX SQL Gateway via ODBC or OLEDB),
And
3. If
StaffID is not defined in Adabas, this means he could be a temporary contract
Staff and he may be defined in the Attendance System Staff Table (MS Access
Database).
And, when
the user clicks on "Login as Public User" (Forms Authentication), he
will be defined in the SQL Security Database which has Table for UserID,
Password and other details such as First Name and Last Name. In this case, the
user is a client and he is not a company employee, and he may be accessing our
systems to get a statement of account or follow on the status of a project for
example.
In all
other cases not mentioned above, the user is anonymous.
I need to
modify the "DataPortal_Fetch" of the custom Identity object to handle
all the above cases, which to use 3 different Database connections.
If you
look at the code in DataPortal_Fetch, it has "USING - END USING"
block, and I am a bit lost on how to do that, since this will make code looks
very confusing and complicated when it will involve connecting to 3 different
Database according to the type of the login request and the user, which will
require 3 command objects and 3 DataReader Objects.
The Questions:
1. What
do you think about this approach ?
2. How to
simplify the coding ?
3. If you
think it is approach complicated, do you have other alternatives to achieve
this objective ?
Tarek.
david.wendelken:
Of course, those same apps may need to know how to connect to multiple databases anyway, which defeats the simplicity advantages of the above option. ;)
As for the scenario you outlined, you don't need 3 connection objects. You only need one. Just re-use it. J
Oh, yes ! I think I can use one connection object, one command and one data reader, but the problem is that I have to connect to Adabas/Unix using the ConnX .NET Data Provider connection object types as System.Data.CONNX.CNXConnection, and also, same for command and data reader object under the System.Data.CONNX Namespace. As per the help, it supports .NET OLE DB and ADODB Standard Connection Objects, but I have never tried them.
I think if I connect to all Databases via OLE DB Data Provider Objects, then this will simplify the code.
Tarek.
JoeFallon1:You have not explained the requirements in enough detail.
Do you need to use Windows Authentication only? Or do you also need to use it for Roles for Authorization?
In my Web app I allow both UID/PWD or Windows Authorization. When configured for Windows, I am only intercepting the principal in order to extract the Domain and UID from it. My DB has the same username and Domain fields so I can use these 2 Windows values to do a lookup and let them in or not. If I let them in then they end up using a CSLA principal filled with roles and permissions from my DB. So my config file still reads CSLA Authorization even though I am using Windows to get the UID. This allows the client to have "single sign on". I believe that I also have code to add a Forms Cookie so that Forms Auth will let them in too.
Joe
Joe,
Might I see that implementation? This is exactly what I have to implement (tho on Winforms).
Thanks,
Jeff
Hi Dave! How's Ethipoia? When are you coming back?
There's this big thingummy going on with the project now where they want to do everything through web services and apparantly in CSLA that's just a humungous waste of time. There's some rumblings going on about how insecure everything is with the clients hitting the db, so I want to come up with a good case for using CSLA to manage everything across the enterprise instead.
But doing Windows Authentication in a WinForms app is:
using
System.Security.Principal;username =
WindowsIdentity.GetCurrent().Name;and then just check it against your security object to get your role. Easy peasy. Windows is so much less fretful than ASP.Net.
- Charlie
Ethiopia is pretty wet at the moment, it's the tail end of the rainy
season. Should dry back up in a few weeks, then back to perfect weather
(instead of near perfect). J
I promised a year, so that would be
sometime in March. I expect I'll stay on a few months past that, so l'm
expecting to be back in late spring. I'll be back in Fayetteville Friday Dec 19th, and
we're having a traditional christmas party the 20th. Daffyd and
Kate are hosting it for me. J Hope you'll be there!
As for web services, there is no reason
you can't use the same csla business objects we've already got and expose them
via a web services interface. The sample csla project shows how to
do it, if I remember right.
Who is "they"? users or
other technical people?
From: Charles
Asbornsen [mailto:cslanet@lhotka.net]
Sent: Monday, September 08, 2008
9:33 PM
To: david_wendelken@nc.rr.com
Subject: Re: [CSLA .NET] How to
use Windows Authentication with CSLA.NET?
Hi
Dave! How's Ethipoia? When are you coming back?
There's
this big thingummy going on with the project now where they want to do
everything through web services and apparantly in CSLA that's just a humungous
waste of time. There's some rumblings going on about how insecure
everything is with the clients hitting the db, so I want to come up with a good
case for using CSLA to manage everything across the enterprise instead.
But doing
Windows Authentication in a WinForms app is:
using
System.Security.Principal;
username
= WindowsIdentity.GetCurrent().Name;
and then
just check it against your security object to get your role. Easy
peasy. Windows is so much less fretful than ASP.Net.
- Charlie
Hi Tarek
I made some changes to PTracker authentication in order to have Windows Authentication. In fact you just need to change CslaAuthentication attribute. The nicest thing about it is that you can have both at the same time.
If the users that is authenticated under Windows exists in the users table, it gets logged on with no further questions. Otherwise (the windows user name doesn't exist in the users table) the login window will ask for username/password. This is quite useful when you have an application on a client but your laptop is not in the client's domain. You can still use your laptop and login in the application using the application admin username.
FAQ: How to use Windows authentication in PTracker (PTWin) (C#)
http://forums.lhotka.net/forums/post/28161.aspx
Cheers
Hi tiago,
Thank you for the info.
I have already implemented mixed Authentication Mode, and in case of Integrated Windows Authentication, the application will not ask the user for his User Name/Password if he is already logged in to the Domain, and will get the User Name from the LOGON_SERVER Variable.
I think there are some differences between my approach and yours, but this is really interesting.
Check the details here:
http://forums.lhotka.net/forums/22855/ShowThread.aspx#22855
Of course, that was last year, now the module has been updated several times, and it is much more advanced, but the details mentioned in the above link will give a clear idea about the requirements and how to implement it.
Thank you agian for the update.
Tarek.
Copyright (c) Marimer LLC