Kenneth Van Coppenolle
Kenneth Van Coppenolle

Reputation: 166

Authenticate forms user without password in SharePoint 2010

I am working on a little project for SharePoint 2010 that will allow users to authenticate with their OpenID (and maybe more later on).

How it currently works is I have a membership and role provider based on SQL. My login page uses DotNetOpenAuth to send an authenticationrequest to the OpenID endpoint. If I get a positive response I read the e-mail address from the OpenID persona and create a session for the MembershipUser that has that e-mail address (if I know the endpoint he's from). If that user doesn't exist, I create a new MembershipUser and store the endpoint in the comment property (so that you can't simply edit your own persona to log in as another person's e-mail address).

This works, but the problem is in creating the session. I currently do this with the following bit of code:

//authenticate
SecurityToken token = SPSecurityContext.SecurityTokenForFormsAuthentication(new Uri(SPContext.Current.Web.Url),userProvider,roleProvider,username,user.GetPassword());         
SPFederationAuthenticationModule.Current.SetPrincipalAndWriteSessionToken(token);

But that bit only works if the membership provider doesn't encrypt passwords because, once encrypted, I can't just read the user's password and use it in that method.

I was hoping to find a way to just let a user log in but I can't seem to find a simple way of doing that.

Using

FormsAuthentication.SetAuthCookie(username, false);

Just creates an exception (I assume that's because that method is for standard FBA, and not claims-based FBA but I'm just guessing there. The built-in FBA login control with username and password does work, though.)

System.ArgumentException: Exception of type 'System.ArgumentException' was thrown.  Parameter name: encodedValue   
 at Microsoft.SharePoint.Administration.Claims.SPClaimEncodingManager.DecodeClaimFromFormsSuffix(String encodedValue)    
 at Microsoft.SharePoint.Administration.Claims.SPClaimProviderManager.GetProviderUserKey(String encodedSuffix)    
 at Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(SPSite site, String name, Boolean bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte[] UserToken, String userName, Boolean bIgnoreTokenTimeout, Boolean bAsAnonymous)    
 at Microsoft.SharePoint.SPWeb.InitializeSPRequest()    
 at Microsoft.SharePoint.WebControls.SPControl.EnsureSPWebRequest(SPWeb web)    
 at Microsoft.SharePoint.WebControls.SPControl.SPWebEnsureSPControl(HttpContext context)    
 at Microsoft.SharePoint.ApplicationRuntime.BaseApplication.Application_PreRequestHandlerExecute(Object sender, EventArgs e)    
 at Microsoft.SharePoint.ApplicationRuntime.SPRequestModule.PreRequestExecuteAppHandler(Object oSender, EventArgs ea)    
 at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()    
 at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Long story short, I would like a way to create tokens for my members without having to use their password.

Does anyone have some experience in this, or an idea of how I can get what I want?

Thanks in advance.

Upvotes: 1

Views: 5261

Answers (1)

Kenneth Van Coppenolle
Kenneth Van Coppenolle

Reputation: 166

In case someone else runs into the same situation, I'll say how I 'solved' the problem.

In a professional environment, you would most likely create your own membership provider / security token service so you can request tokens in your code without requiring the password of the user.

In my case (due to time constraints) I couldn't do that, so I took a simpler way out. Instead of using encrypted passwords (via IIS) I used hashed passwords (set that manually in the web.config). I also made sure to allow resetting of passwords for my membership provider. Then I used the following code to issue a token:

MembershipUser user = membershipProvider.GetUser(username, true);
if(user == null)
{
    //create new user here
}
string password = user.ResetPassword();
SecurityToken token = SPSecurityContext.SecurityTokenForFormsAuthentication(new Uri(SPContext.Current.Web.Url), membershipProviderName, roleProviderName, user.UserName, password, false);
SPFederationAuthenticationModule.Current.SetPrincipalAndWriteSessionToken(token);            

Practically, this means that the forms user has his password reset each time I log him in, but since he never actually uses his password it's not that big of an issue. It works well enough to quickly show OpenID support in SharePoint.

Upvotes: 1

Related Questions