Sunday, November 22, 2009

SharePoint: Integrate SSO with third party site

Say you have a sharepoint site which needs to authenticate to a third party site with web service. So authentication on your SharePoint site will be against the third party site. Here how I have implemented:
Created a custom membership provider. In this membership provider I have connected to the third party site with token or username/password.

Create a custom  Membership Provider

First of all I have developed a custom membership provider. The following code snippet shows my custom membership provider. FYI, I have overridden few methods of membership just for making things working:
public class MyMembershipProvider : MembershipProvider
{
    //actually token is passed in the parameter usernameToMatch
    public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
    {
        AuthUser user = webService.GetUserByToken(usernameToMatch);
        MembershipUserCollection users = new MembershipUserCollection();
        if (user != null)
        {
            users.Add(new MembershipUser(Membership.Provider.Name, user.UserName, user.UserName, "aa@bb.com", string.Empty, string.Empty, true, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now));
            totalRecords = 1;
        }
        else
        {
            totalRecords = 0;
        }
        return users;
    }


    public override MembershipUser GetUser(string username, bool userIsOnline)
        {
            int total=0;
           MembershipUserCollection users = //find user by username
           if (users.Count == 1)
           {
               return users[username];
           }
           return null;
        }


    public override bool RequiresQuestionAndAnswer
    {
        get { return false; }
    }

    public override bool RequiresUniqueEmail
    {
        get { return false; }
    }


    public override bool ValidateUser(string username, string password)
    {
        if (string.IsNullOrEmpty(password))
        {
           //validate by token as this will be called from autologin page
        }
        else
        {
           //validate by username password
        }
    }
}
Code Snippet 1: Membership Provider

In the above code snippet FinduserByUsername will find user by token and GetUser will find user by username.By setting enableSearchMethods=false in the provider settings in the web.config, you can ensure that the find method will not be invoked by sharepoint. Its only be invoked by you.

Modify web config to put custom membership in action

Once you have finished with custom membership provider and deployed in gac or bin and added the dll in safecontrol list you need to use it. You need to make sure you have put your custom provider web config as shown below:
<membership defaultProvider="AuthProvider"> 
<
providers>
<
add name="AuthProvider"
type="K2.Providers.K2MembershipProvider,K2.Providers,
Version=1.0.0.0,Culture=neutral,PublicKeyToken=c2c2b5c92b3495f9
"
enableSearchMethods="false" connectionProtection="None" />
</
providers>
</
membership>
Code Snippet 2: Define membership provider in web.config

You need to put this configuration in both your web application’s web.config as well as site collection web application’s web.config file. Also if you need some kind of configuration in the appsettings section of web.config then you need to put it central admin web application’s web config also. This is because when you will set site collection administrator from central admin site, central admin site will try to use your membership provider and definitely any appsettings value your membership provider will try to read from config file will fail if the value is not in the web.coinfg file.

Change the Authentication Provider from central admin site

Once you have modified both web.config file of current and central admin site, navigate to the central admin site. Go to the page Application Management –> Authentication Providers (under application security section). Make sure your web application is selected from list and then click on the default provider. In the provider text box put the provider name you have defined in the web.config file for your provider (which is AuthProvider in my case as shown in the code snippet 2). Once you have finished this go to Application Management –> Site Collection Administrators (under sharepoint site management section). Make sure your site collection is selected in the list. And then enter the user name in site collection administrator box. If everything is ok then you will find that SharePoint is getting the user.
image


Figure 1: Setting site collection administrator in central administration site.

Auto login the user

Now say you to auto login user when someone try with the url http://myserver.com/customlogin.aspx?token=xxxxx. Here you use this token to validate with membership provider. For this create a custom aspx page and in the page load event take the token from querystring and validate with the membership provider. The following code in the page load event will of check the token with membership provider.
string token=Request.QueryString["token"];
if (string.IsNullOrEmpty(token))
{
   Response.Redirect("AccessDenied.aspx");
}
else
{
   if (Membership.Provider.ValidateUser(token, string.Empty))
   {
      UserCollection users=Membership.Provider.FindUsersByName(token,......);
      FormsAuthentication.RedirectFromLoginPage(users[0].UserName, true);
   }
}


In the above code block once the token is validated, we get the user by the FindUsersByName method then we redirect from login page passing the user name.

To deploy the custom login page you can put in the web service virtual directory and you also need to change the markup of the aspx file as shown below:
<%@ Assembly Name="K2.UI.Utils, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c2c2b5c92b3495f9" %>
<%@ Page Language="C#" AutoEventWireup="true" Inherits="K2.UI.Utils.MyLoginPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div> 
    </div>
    </form>
</body>
</html>

In the above code snippet, the assembly  tag defines that assembly where the code behind of the page exists.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.