Custom authentication
Is it possible to develop some kind of sitefinity extension to authenticate users based on some HTTP headers coming in the requests?
Our website is behind a proxy in charge of the user authentication and we require sitefinity to decide if the request is authenticated or not based on the http headers present in the request.
Thanks a lot,
G.
Should I create a custom ASP.NET AuthenticationModule and fill context.User with a new SitefinityPrincipal in case of an authenticated request?
Any example of this kind of module?
Hello Gustavo,
There is a method of the SecurityManager
AuthenticateUser(string membershipProviderName, string userName, string password, bool persistent)
which you have to use. You can call it through a web service for each application.
Kind regards,
Ivan Dimitrov
the Telerik team
Thank you Ivan, but we don't have any password and we don't want to authenticate the user.
1. When a request arrives to our web we have to check if the request contains a special header to check if he is already authenticated or not.
2. If yes, we need to let know Sitefinity that is authenticated.
How should we proceed to get that behaviour?
Regards
g.
Hi Gustavo,
You can create a user account for that specific purpose.
Below is an example how you could handle this:
1. Create a user, let’s say username: ServiceAccount , Password: admin@2
2. Assign the new user to the appropriate roles.
3. Add Global.asax file to your application root.
4. Add the following method to Global.asax
void
Application_PostAuthenticateRequest(
object
sender, EventArgs e)
var request =
this
.Context.Request;
if
(
"True"
.Equals(request.Headers[
"AutoAthenticate"
], StringComparison.OrdinalIgnoreCase))
if
(!request.IsAuthenticated ||
this
.Context.User.Identity.Name !=
"ServiceAccount"
)
// You should set the provider name which was used to create the account.
var defaultMembershpProvider = Telerik.Sitefinity.Security.UserManager.GetDefaultProviderName();
Telerik.Sitefinity.Security.SecurityManager.AuthenticateUser(defaultMembershpProvider,
"ServiceAccount"
,
"admin@2"
,
true
);
Thank you very much Bob, but it doesn't fit in my concrete scenario.
I receive a request with a Header including a UserName, and those usernames doesn't exist in our website/membershiproviders at the time the request is received
What I'm trying to accomplished is summarized in this "snippet":
if (Request.Headers["UserName"] != null)
//Tell sitefinity that this is an authenticated request and that the user name
// is Request.Headers["UserName"] for all the processing required for this request
Best regards,
G.
Hi Gustavo,
Will it be ok if at that moment you first create the user with auto generated password and then authenticate with the generated credentials?
Regards,Yes, it sound a feasible approach for our requirements.
How could it be implemented?
Thanks a lot,
G.
Hi Gustavo,
Here is an example:
void
Application_PostAuthenticateRequest(
object
sender, EventArgs e)
var request =
this
.Context.Request;
var userName = request.Headers[
"UserName"
];
if
(!String.IsNullOrEmpty(userName) && !request.IsAuthenticated)
// If you want to have unique password for every user you have to figure out some mechanism for sending back and forward the generated passwords.
// You can generate passwords like this:
// var password = Telerik.Sitefinity.Security.SecurityManager.GetRandomKey(4);
//
// NOTE: the length of the password in the example above will be 8 characters, double the size of the parameter passed to GetRendomKey method.
var password =
"F2AA1527"
;
var defaultMembershpProvider = Telerik.Sitefinity.Security.UserManager.GetDefaultProviderName();
var result = Telerik.Sitefinity.Security.SecurityManager.AuthenticateUser(defaultMembershpProvider, userName, password,
true
);
// If user does not exist or wrong password.
if
(result == Telerik.Sitefinity.Security.UserLoggingReason.Unknown)
var userManager = Telerik.Sitefinity.Security.UserManager.GetManager(defaultMembershpProvider);
if
(!userManager.UserExists(userName))
// We have to suppress security since the current request is not authenticated yet and won't be allowed to create new user.
// Alternatively the next code block can be executed with elevated privileges but that is a bit more complicated and probably
// outside of the scope of the current example.
userManager.Provider.SuppressSecurityChecks =
true
;
System.Web.Security.MembershipCreateStatus status;
userManager.CreateUser(userName, password,
"some@email.com"
,
null
,
null
,
true
,
null
,
out
status);
if
(status == MembershipCreateStatus.Success)
userManager.SaveChanges();
result = Telerik.Sitefinity.Security.SecurityManager.AuthenticateUser(defaultMembershpProvider, userName, password,
true
);
if
(result != Telerik.Sitefinity.Security.UserLoggingReason.Success)
// Maybe throw an exception or return appropriate response.
// Else the user created and the current request authenticated successfully.
else
// Maybe throw an exception or return appropriate response.
userManager.Provider.SuppressSecurityChecks =
false
;
else
// User with that name already exists and the password is different.
// Maybe throw an exception in that case.
Thank you bob, we will try to integrate that solution.
We are aware of the security implications. There are a proxy in front of our web server, and that proxy authenticate the users and add/filter those HTTP Headers.
BR,
G.
Thank for this useful code :).
I have a custom membership provider. I know if a "external" user if login or logout reading a cookie. The cookie have this information:
Username, Login/Logout , Roles. Ej Roles:myCustomer,myVisitor
I have arround 200.000 Users, I want to show some "webpart" based in Roles.
The workarround is this:
1) Create in sitefinity Roles myCustomer, myVisitor
2) Create in sitefinity 2 new users userMyCustomer-->myCustomer, userMyVisitor-->myVisitor. Those users have BackendUser Rol disabled
3) Create PostAuthenticateRequest method with this functionality:
3.1) Read in my cookie roles for current "external" user
3.3)log current "external" user in sitefinty using this if roles=myCustomer then use SecurityManager.AuthenticateUser with userMyCustomer as username
The method works but i have 2 important cuestions
1) Is possible have the same frontend user logged in 2000 diferent locations at same time ?
2) Is better create 200.000 users with Bob´s code?
Regards,
Jose Antonio
Thank for this useful code :).
I have a custom membership provider. I know if a "external" user if login or logout reading a cookie. The cookie have this information:
Username, Login/Logout , Roles. Ej Roles:myCustomer,myVisitor
I have arround 200.000 Users, I want to show some "webpart" based in Roles.
The workarround is this:
1) Create in sitefinity Roles myCustomer, myVisitor
2) Create in sitefinity 2 new users userMyCustomer-->myCustomer, userMyVisitor-->myVisitor. Those users have BackendUser Rol disabled
3) Create PostAuthenticateRequest method with this functionality:
3.1) Read in my cookie roles for current "external" user
3.3)log current "external" user in sitefinty using this if roles=myCustomer then use SecurityManager.AuthenticateUser with userMyCustomer as username
The method works but i have 2 important cuestions
1) Is possible have the same frontend user logged in 2000 diferent locations at same time ?
2) Is better create 200.000 users with Bob´s code?
Regards,
Jose Antonio