Wednesday, February 6, 2013

SharePoint : Forms Claims authentication automatically


We have a URL redirect from another external system with username and password in some hash to sharepoint. We needed to validate that user and password and autheticate the user using forms. We created membership and role managers to validate users but to authenticate using security token service, to create a security token and have the session created automatically. This script is verified on SharePoint 2013. PS: Some of the code is borrowed from various posts and customized as required. Followwing are the methods used in the code.

 // Borrowed from Microsoft.SharePoint.IdentityModel.LogonSelector class
        private void RedirectToLoginPage(SPAuthenticationProvider provider)
        {
            string components;
            string url = provider.AuthenticationRedirectionUrl.ToString();

            components = provider is SPWindowsAuthenticationProvider ?
                EnsureUrlSkipsFormsAuthModuleRedirection(HttpContext.Current.Request.Url.GetComponents(UriComponents.Query, UriFormat.SafeUnescaped), true) :
                HttpContext.Current.Request.Url.GetComponents(UriComponents.Query, UriFormat.SafeUnescaped);

            SPUtility.Redirect(url, SPRedirectFlags.Default, Context, components);
        }

        // Borrowed from Microsoft.SharePoint.Utilities.SPUtility class
        private string EnsureUrlSkipsFormsAuthModuleRedirection(string url, bool urlIsQueryStringOnly)
        {
            if (!url.Contains("ReturnUrl="))
            {
                if (urlIsQueryStringOnly)
                {
                    url = url + (string.IsNullOrEmpty(url) ? ((string)"") : ((string)"&"));
                }
                else
                {
                    url = url + ((url.IndexOf('?') == -1) ? ((string)"?") : ((string)"&"));
                }
                url = url + "ReturnUrl=";
            }
            return url;
        }

        // Borrowed from Microsoft.SharePoint.IdentityModel.Pages.IdentityModelSignInPageBase
        private void EstablishSessionWithToken(SecurityToken securityToken)
        {
            if (securityToken == null)
            {
                throw new ArgumentNullException("securityToken");
            }
            SPFederationAuthenticationModule fam = FederatedAuthentication.WSFederationAuthenticationModule as SPFederationAuthenticationModule;
            if (fam == null)
            {
                //ULS.SendTraceTag(0x15d59d, ULSCat.msoulscat_WSS_ClaimsAuthentication, ULSTraceLevel.Verbose, this.LogPrefix + "Federated authentication module is missing for request '{0}'.", new object[] { SPAlternateUrl.ContextUri });
                throw new InvalidOperationException();
            }
            SPSecurity.RunWithElevatedPrivileges(() => fam.SetPrincipalAndWriteSessionToken(securityToken));
        }

To do the authentication here is the code. Make sure authentication and role managers are configured prior to this code execution. To do this, you can refer to my earlier post on creating and configuring these entries using PowerShell
                string strUserName = Request.QueryString["username"];
                string strPassword = Request.QueryString["password"];

                // FBA authentication it is. 
                SPIisSettings iisSettings = SPContext.Current.Site.WebApplication.IisSettings[SPUrlZone.Default];
                SPFormsAuthenticationProvider formsClaimsAuthenticationProvider = iisSettings.FormsClaimsAuthenticationProvider;
                SecurityToken token = SPSecurityContext.SecurityTokenForFormsAuthentication(new Uri(SPContext.Current.Web.Url), formsClaimsAuthenticationProvider.MembershipProvider, formsClaimsAuthenticationProvider.RoleProvider, strUserName, strPassword, SPFormsAuthenticationOption.PersistentSignInRequest);
                if (null != token)
                {
                    EstablishSessionWithToken(token);
                    //base.RedirectToSuccessUrl();
                    var rUrl = Request.QueryString.Get("Source");
                    Response.Redirect(string.IsNullOrEmpty(rUrl) ? "~/SitePages/default.aspx" : rUrl);
                }

2 comments:

  1. Hi,
    It is a great Post. Thank you.
    I have similar situation wherein I have userid password incoming in the initial Request. The code you posted above, where did you put it ?
    Thank you.

    ReplyDelete