Windows Authentication
Hi,
I've been holding off on upgrading to 4 from 3.7 because currently we have windows authentication enabled and 4.0 didn't support this.
I noticed with 4.1 you know allow auto login with windows authentication if you have AD enabled:
www.sitefinity.com/.../enabling-windows-authentication.aspx
While I didn't really want to turn on AD authentication I'm happy to do so if it works. My main problem is going to be: Does Sitefinities LDAP support searching/authenticating accross the root and Child domains and if so how would I do this.
We have about 6 or 7 active domains on our network.
Thank you for any help you can provide.
Regards
Byron
Hi Byzza,
If you mean Single Sign On, by authenticating over several domains, this is still not supported out of the box. It could be done with a custom implementation on subdomains, because this will allow you to easily pass the cookies from the cookie collection. There is a method of the SecurityManager that you can use - AuthenticateUser. AuthenticateUser validates the user - password and username - password is encrypted and compared with the input you use. Then the username and passwordare compared. If the user is valid we get the user , verify the ip and last login request SetAuthenticationCookie was made internal, so to authenticate a user you should use AuthenticateUser method. Basically we create the cookie with the cookie path, domain and whether ssl is required. Then we add the cookie to the FormsAuthenticationTicket, decrypt it and set Expires property of the cookie. To decrypt the password we use the decryptionKey inside App_Data/Sitefinity/Configurations/SecurityConfig.config
<securityConfig authCookieName=".SFAUTH-/" rolesCookieName=".SFROLES-/" validationKey="279EB02E02B8322864837AA092A6384F61E267310BD526CA5AA7BA61B7ECA17071022B3F025FBA05CB390ECE4CF2B7D93F377CD50085355795AF69C89AA347C2" decryptionKey="DF845BFCA7B2A84D0649DA8F2C033715772EA183D8A1A2E7072082CD0482DBDE" loggingCookieName=".SFLOG-/">
Here is a sample code that should authenticate a user from one application to another. Note that this will work only if you are on the same domain name, because the cookies are not valid between different domains. If you are going to use different domains you should have a common repository where you should save the cookies. You should also add another parameter to the request - some ID that will take care of the expiration of this cookie for the current request, so that this will not allow to others to use it.
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.Net;
using
System.IO;
using
System.Text;
public
partial
class
Default8 : System.Web.UI.Page
protected
void
Page_Load(
object
sender, EventArgs e)
var membershipProvider =
""
;
var userName =
"admin"
;
var password =
"admin@2"
;
var rememberMe =
true
;
if
(AuthenticateRequest(membershipProvider, userName, password, rememberMe))
Response.Redirect(
"http://localhost:4000/Sitefinity/Pages"
);
else
Response.Write(
"Try Again."
);
public
string
InvokeWebMethod(
string
serviceUrl,
string
methodName,
string
httpMethod,
byte
[] data)
var request = (HttpWebRequest)WebRequest.Create(String.Concat(sitefinityHost, serviceUrl, methodName));
request.Method = httpMethod;
request.ContentType =
"application/json"
;
request.CookieContainer =
new
CookieContainer();
if
(cookies !=
null
)
foreach
(Cookie cookie
in
cookies)
if
(!cookie.Expired)
request.CookieContainer.Add(cookie);
if
(data !=
null
)
request.ContentLength = data.Length;
using
(var writer = request.GetRequestStream())
writer.Write(data, 0, data.Length);
using
(var response = (HttpWebResponse)request.GetResponse())
// HERE WE GET THE RESPONSE AND ADD THE COOKIES TO IT.
cookies = response.Cookies;
using
(var reader =
new
StreamReader(response.GetResponseStream(), Encoding.UTF8))
// GET THE cookies AND ADD COOKIES NAME AND VALUE TO THE CURRENT RESPONSE!
var name =
""
;
var value =
""
;
Response.Cookies.Add(
new
HttpCookie(name, value));
return
reader.ReadToEnd();
public
bool
Logout()
return
InvokeWebMethod(usersServiceUrl, logoutCurrentUserMethod,
"GET"
,
null
) ==
"true"
;
public
bool
Logout(
byte
[] credentials)
return
InvokeWebMethod(usersServiceUrl, logoutUserWithCredentialsMethod,
"POST"
, credentials) ==
"true"
;
private
bool
AuthenticateRequest(
string
membershipProvider,
string
userName,
string
password,
bool
rememberMe)
var jsonData = String.Format(credentialsFormat, membershipProvider, userName, password, rememberMe.ToString().ToLower());
var credentials = Encoding.UTF8.GetBytes(jsonData);
string
result = InvokeWebMethod(usersServiceUrl, authenticateMethod,
"POST"
, credentials);
switch
(result)
case
"0"
:
return
true
;
case
"3"
:
case
"6"
:
case
"9"
:
Response.Write(
"There is a user with the same credentials logged in the system form another application or browser.\r\n It will be logged out"
);
if
(Logout(credentials))
return
InvokeWebMethod(usersServiceUrl, authenticateMethod,
"POST"
, credentials) ==
"0"
;
return
false
;
default
:
return
false
;
private
const
string
credentialsFormat = @"
""
MembershipProvider
""
:
""
0
""
,
""
UserName
""
:
""
1
""
,
""
Password
""
:
""
2
""
,
""
Persistent
""
:3
";
private
static
CookieCollection cookies;
private
const
string
usersServiceUrl =
"/Sitefinity/Services/Security/Users.svc/"
;
private
const
string
authenticateMethod =
"Authenticate"
;
private
const
string
logoutCurrentUserMethod =
"Logout"
;
private
const
string
logoutUserWithCredentialsMethod =
"LogoutCredentials"
;
private
const
string
logoutOtherUserMethos =
"Logout/0/1"
;
private
const
string
sitefinityHost =
"http://localhost:4000"
;
Hi,
Thank you for such a quick response.
I don't think that is actually what I'm after. Please correct me if I'm wrong but what you have there is to allow a user to be authenticated on:
http://domain1.mycompany.com
http://domain2.mycompany.com
http://domain3.mycompany.com
so if they log into one they log into all 3 so they don't have to log in again?
If so, not that is not what I'm after.
We have an intranet here (eg http://intranet/) which is avalible from all our sites around the world via VPN. Each of the Major sites have their own Active directory Server, and such their own Domain. So a user at head office would log in with the username "HeadOffice\user1" where as a user at another site might log in with the username "Site123\user2"
The HeadOffice domain is the master/primary domain and all the other domains are linked into it so that they all work together and can see each other.
Now I think I worked out in theroy I could create a whole heap of membership providers, one for each domain and the user just selects the domain they need to sign in to, BUT because I'm trying to avoid the whole sign in all together and use Windows Authentication I assume I must have only one LDAP membership provider active.
So could you please let me know if Sitefinity would be able to support this setup with Windows authentication and how I can set it up.
--------------------------------------
On another note though, just to try and see how the LDAP worked (this is the first Time I've ever used LDAP) I decided to try and set it up with just HeadOffice, just to see if it would work if it could even connect, and so far nothing I try will work. I've spoken to our network admin, and I've used a program called "LDAP Browser" to mimic the settings in Sitefinity, but no matter what settings I try when I go to users none are returned from AD.
I've attached a screen shot of the final Config I tried.
the port I have set in the screen shot is to a Global list which should have all the domains together according to the network admin (just experimenting with both), but I've tried the normal port as well just for Head office.
If you could please help on either issue that would be great.
Thank you
Byron Boardman
Ok, so i'm still having the mulitple domain issue still (well haven't started too look into it yet), but as far as the second issue goes I finally got SF connected to LDAP and under user accounts I can see the full list under our main domain, but when I follow the instructions here:
http://www.sitefinity.com/documentation/installation-and-administration-guide/system-settings/enabling-windows-authentication.aspx
And change the web.config from
<
authentication
mode
=
"Forms"
/>
<
authentication
mode
=
"Windows"
/>
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. |
|
Byzza -
I am seeing similar error messages after following the instructions listed in that link - but only for a few users so far - others are fine.
So I ask...
What can we look at to see why certain users are getting the above message?
Also - what happens when a user can't be authenticated automatically? It seems as though they go to my defined login page - is this correct? ---- EDIT: This was because I still had some Authentication-related code in my .MASTER page for generating some Session variables
Hi Daniel,
I'm not even sure where to start, I only have 3 users in that DB and all of them have the same problem.
Hi Byzza,
We thrown this error Invalid full name format.", "windowsIdentity.Name" when the windowsIdentity.Name is not in format Domain\USER
I am not able to replicate this issue locally with LDAP and Windows authentication. Can you check what the the identity name?
System.Web.HttpContext.Current.User.Identity.Name
All the best,
Ivan Dimitrov
the Telerik team
OK - I figured out.... Now keep in mind I am using this current SF installation in an Intranet context - NOT public facing web.
The instructions to have people auto-login to the backend does not work properly for me. The /Sitefinity/Services directory must be under Anonymous authentication according to the popups I see because of the WCF stuff.
At first I tried turning off FORMS and putting WINDOWS authentication on for everything and I got the error above.
My current setup is this in IIS7 to achieve Windows Authentication properly on Front End ( - but still cannot get AUTO-Login to backend):
IIS Settings
Site - Windows Authentication ON
Site/Sitefinity/Services - Windows Authentication OFF Anonymous Authentication ON
FORMS authentication OFF totally
Windows File System
Site - Read/Write permissions to INTRANET_GROUP - an AD group with has all of my Intranet users in it
I now have Windows Authentication for the Front End, plus I have an LdapUsers Membership provider from which I assign Backend and other Default Roles to my backend users. These users must logon manually to the Backend, but can use their NT logon credentials.
The ultimate goal would be for the backend to be seamless for those logged in users that have backend access, but this setup works for now.
I thought I had this working.... until I went in to actually do editting in the backend - but because the webservices are all over the place - I keep getting yelled at about not being Anonymous!!!!
I don't get it. The instructions say to change to the authenitcation method to WINDOWS - but the services on the backend NEED Anonymous??? How to overcome this?
This is soooooooooo frustrating.
Sorry - Not trying to bump this - but I am finding lots of information about using Windows Authentication in WCF Services.... So this should be possible.
The core issue preventing my Windows authentication from working right is because the WCF calls fail in a non-anonymous context.
I'm not sure if this would help, but I did some research and found the following links - hope they might help:
http://www.codeproject.com/KB/WCF/WCFBasicHttpBinding.aspx?msg=3104044
http://social.msdn.microsoft.com/forums/en-US/wcf/thread/442be0c8-309e-4000-9311-57189ae7a900/
Thanks Lupi.
I went through all of those steps and have read those articles while working through this issue, but thanks for making sure that I know how to Google - ;) I know some people choose to be lazy and not find things for themselves.
First of all - the main web service for the CMS CRUD actions uses webHttpBinding - which can also use Transport authentication. There are also basicHttpBinding services, but the big issue area is the webHttpBinding one - the ones that handle the JSON data.
The problem is that we cannot change the authentication scheme on the services in the Service's web.config - at least as far as I have been able to figure out. You can do all of the work in the world on the site's web.config - but if you can't let the service know that it is using Windows authentication - the service will still send a 500 response.
This is where the real hangup is. The WCF service doesn't need to care if it is receiving credentials at all. It can choose to ignore them if it chooses, BUT it has to be setup to understand that credentials are in fact being presented to it in the first place.
If this hurdle can be cleared, I have a feeling that Windows authentication can work on SF4.1
Hi,
Anonymous authentication is required by Sitefinity. This is due to WCF binding we are currently using. This limitation will be fixed soon. You have to allow anonymous access in IIS. Then go to ~/Sitefinity/Pages and then click on the link “Permissions for all pages” on the left panel. In the new screen click on “Change” button in the “View pages” section. Select the fourth option “Selected roles or users” and then click on “Add roles or users” button. Select the role you want to allow to view your pages.
Regards,Ivan-
I updated my ticket the same, but just want to make sure the forum users are given a clear answer too...
What about this scenario:
http://www.sitefinity.com/documentation/installation-and-administration-guide/system-settings/enabling-windows-authentication.aspx
This scenario involved Windows authentication - so how is it expected to work?
I have tried this example in new web project but when I run my website its still going to login page.
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.Net;
using
System.IO;
using
System.Text;
public
partial
class
Default8 : System.Web.UI.Page
protected
void
Page_Load(
object
sender, EventArgs e)
var membershipProvider =
""
;
var userName =
"admin"
;
var password =
"admin@2"
;
var rememberMe =
true
;
blah blahhblah blahhblah blahhblah blahhblah blahh
My requirement is my web site need to talk to sitefinity svc services like "Sitefinity/services/Content/ContentItemService.svc" and get the content and feed to my website.
To call this services I need to be authenticated but its not working. Even when I make client calls thru jquery like this
function WCFJSON()
Type = "GET";
Url = "http://localhost:49213/Sitefinity/services/Content/ContentItemService.svc/f294027d-268f-40d1-b869-cb93b59f4f95/";
Data = '';
ContentType = "application/json; charset=utf-8";
DataType = "json"; varProcessData = true;
CallService();
I am getting error saying I am not authenticated/session timeout.
I would appreciate if you can give us working example.
Hi kiran,
Currently it is not possible to use our services if you are not authenticated. We know about this extensibility issue and we have to expose a proper way to authenticate requests through another service or some methods.
Kind regards,
Ivan Dimitrov
the Telerik team