7

My goal is to setup a SSO-like environment (not fully support SSO), with below behaviour:

  1. User logon in System_A (java)
  2. When user click on a specify link, System_A will generate a security token, timestamp, and redirect the user to System_B (SharePoint with FBA) http://system_b/_forms/default.aspx?u=UserName&tkn=[SECURITY_TOKEN + TIMESTAMP with some encryption....]
  3. System_B implemented custom membership provider, it makes some webservice call to System_A to validate the user session in the ValidateUser(string username, string password) method. Refer: http://blog.sharedove.com/adisjugo/index.php/2011/01/05/writing-a-custom-membership-provider-and-using-it-for-fba-forms-based-authentication-in-sharepoint-2010-from-the-scratch/

Remarks

  • User can ONLY visit System_B by the link generate after logon on System_A, so it's not a real SSO situation.

  • When user logout from System_B, doesn't need to logout System_A vice versa.

Everything is OK, except user unable to logout on SharePoint. here are the findings: 1. If I use normal form login flow (i.e. /_forms/default.aspx, and enter username, password) , it has no problem in logging-out.

  1. In normal form flow, it will write a cookie name FedAUTH=xxxxxxxxxxx

  2. If I use auto-login link, (i.e. /_forms/default.aspx?u=UserName&tkn=[SECURITY_TOKEN + TIMESTAMP with some encryption....]), it will write a cookie name with .ASPXAUTH=xxxxxxxxxx

I customized the /_forms/default.aspx as below:

protected override void OnLoad(EventArgs e) {
    base.OnLoad(e);
    SetLoginInfo();

}

private void SetLoginInfo() {
    if (!IsPostBack) {

        string u = Request.Params["u"];
        string tkn = Request.Params["tkn"];
        if (!String.IsNullOrEmpty(u) && !String.IsNullOrEmpty(tkn)) {

            MembershipProvider mp = Membership.Providers["My Membership Provider"];
            if (mp.ValidateUser(u, tkn)) {
                string spname = GetSPEncodeClaimName(u);
                FormsAuthentication.SetAuthCookie(spname, false);
                Page.Response.Redirect("/", false);
            }

        }
    }
}

protected string GetSPEncodeClaimName(string username) {
    string encodeName = null;
    SPClaimProviderManager mgr = SPClaimProviderManager.Local;
    if (mgr != null) {
        SPClaim claim = new SPClaim(SPClaimTypes.UserLogonName, username, "http://www.w3.org/2001/XMLSchema#string", SPOriginalIssuers.Format(SPOriginalIssuerType.Forms, "My Membership Provider"));
        encodeName = mgr.EncodeClaim(claim);
        encodeName = encodeName.Substring(encodeName.IndexOf(':') + 1);
    }
    return encodeName;
}

The problem seem come from the cookie's name, am I correct? if so, how to change the cookie name? Is there any other better way to implement this logic? Thanks a lot.

1
  • 1
    Did you have a look at OAuth? Maybe you could implement it for your case...
    – hupseb
    May 3, 2013 at 21:04

1 Answer 1

2

I would tell you to look into SAML based authentication and configuring SharePoint to trust your Java application as a trusted provider, but that may not be as easy as it sounds, so here is a quick fix.

  1. Implement an application page (under layouts folder) and inherit from UnsecuredLayoutsPageBase
  2. Setup your Java app to send users to this page with the token in the querystring
  3. Write the following code to autenticate the user:

    protected void Page_Load(object sender, EventArgs e) {
        try {
            if(Request.QueryString["Token"] != null) {
                RedirectToken token = RedirectToken.Fetch(Guid.Parse(Request.QueryString["Token"]));
    
                if(token != null && DateTime.Now.Subtract(token.Issued).TotalMinutes < 10.0) {
                    Logger.Write("Performing auto login for user: {0} [{1}]", token.Username, token.Target);
                    Logger.Write("Current web url: {0}", SPContext.Current.Web.Url);
    
                    SecurityToken st = SPSecurityContext.SecurityTokenForFormsAuthentication(new Uri(SPContext.Current.Web.Url),
                        "<name>", "<name>", token.Username, "DECRYPTED_TOKEN", SPFormsAuthenticationOption.PersistentSignInRequest);
    
                    SPFederationAuthenticationModule.Current.SetPrincipalAndWriteSessionToken(st);
                    Response.Redirect(token.Target);
                }
                else {
                    Response.Write("Invalid token.");
                }
            }
            else {
                Response.Write("Missing token.");
            }           
        }
        catch(ThreadAbortException) {
            // do nothing...
        }
        catch(Exception x) {
            Logger.Write("Error performing auto login.", x);
            Response.Write("Error performing auto login.");
        }
    }
    
  4. Your custom membership provider should be able to take the username and decrypted token and validate your user.

To handle the logout, you need to implement a logout page, and register it through PowerShell. I don't have any code for it, but this should give you an idea:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.