Microsoft

Blog Categories

Subscribe to RSS feed

Archives

Claims SSO in an Anonymous Access SharePoint Environment

Note: The below method is good for both single sign on and persistent login scenarios in a SharePoint environment with anonymous access enabled.

I recently had to wrestle with implementing single sign on (SSO) between two SharePoint web applications that have anonymous access enabled. If you have read Programming Windows Identity Foundation (I recommend you do if you are planning on implementing claims authentication) you would know that to implement SSO between two secure SharePoint web applications with the same identity provider is not too difficult. If the user is authenticated to one application you can count on the default redirect of non-authenticated users from the second application to your identity provider. The provider will recognize that the user is already authenticated to it (after you program it to) and redirect you back to SharePoint to create the FedAuth cookie you need to access the second application.

Things start to get a little tricky when you throw anonymous access into the mix. The main difference being, you cannot rely on SharePoint to recognize that a new user needs to be authenticated to the STS. This was triggered by an anonymous user trying to access a secure site before, now that your application is anonymous SharePoint does not have this trigger to utilize. That means we are going to have to write some code to create our own trigger.

The solution consists of two parts, a user control on the SharePoint application, and an application page on your custom identity provider (sometimes called an STS or Secure Token Service). The control is going to make a JSON call to the page that lives on the provider. The page on the provider just returns whether or not the current user is authenticated. If the user is authenticated, the control will redirect the user to the provider to be authenticated to the new application.

Let’s take a look at the Render method of the control that will live on our SharePoint application. NOTE: this code is using the jQuery library to make the JSON call.

1: protected override void Render(System.Web.UI.HtmlTextWriter writer) 2: { 3: if (Page.Session.IsNewSession && !HttpContext.Current.User.Identity.IsAuthenticated) 4: { 5: SignInRequestMessage message = TrustedIdentityHelper.CreateTrustedSignInRequestMessage(); 6: 7: string STSUrl = TrustedIdentityHelper.STSUrl(); 8: 9: HttpContext.Current.Response.Write(String.Format(

"<script type="text/javascript">

10: $.getJSON(“{0}{1}”, null, 11: function (data) { 12: { if(data.IsAuthenticated.toLowerCase() == “true”) 13: {{window.location.replace(“{2}”); }} 14: }}) </script>”, 15: STSUrl, 16: “AuthCheck.aspx?Callback=?”, 17: message.RequestUrl)); 18: } 19: 20: base.Render(writer); 21: }

.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode, .ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode pre
{font-size:small;color:black;font-family:consolas, “Courier New”, courier, monospace;background-color:#ffffff;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode pre
{margin:0em;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .rem
{color:#008000;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .kwrd
{color:#0000ff;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .str
{color:#006080;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .op
{color:#0000c0;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .preproc
{color:#cc6633;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .asp
{background-color:#ffff00;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .html
{color:#800000;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .attr
{color:#ff0000;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .alt
{background-color:#f4f4f4;width:100%;margin:0em;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .lnum
{color:#606060;}

You can see that I have a class which assists with creating sign in request messages as well as gives me the URL to my custom provider; I will use both of these if the current user needs to be authenticated. This control outputs javascript on the page that makes a JSON call to AuthCheck.aspx which is located on the identity provider site. If the call returns true (i.e. the user is authenticated to the identity provider) then I redirect the user to the provider to be authenticated. The reason that I only fire this control when it is a new session is because if I took that check out this control would make a JSON call to the STS for every anonymous request. If you have a high traffic site, having a lot of people making frequent JSON calls to your identity provider could cause performance problems.

The AuthCheck.aspx page that receives the JSON call from this control and returns the result is very simple, it is a basic page with a few lines of code in the Page_Load method.

Here is the code for that:

1: protected void Page_Load(object sender, EventArgs e) 2: { 3: Response.ContentType = “text/javascript”; 4: string callback = Request["Callback"]; 5: 6: Response.Write(String.Format(“{0} ({{“IsAuthenticated” : “{1}”}})”, callback, User.Identity.IsAuthenticated.ToString())); 7: }

.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode, .ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode pre
{font-size:small;color:black;font-family:consolas, “Courier New”, courier, monospace;background-color:#ffffff;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode pre
{margin:0em;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .rem
{color:#008000;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .kwrd
{color:#0000ff;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .str
{color:#006080;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .op
{color:#0000c0;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .preproc
{color:#cc6633;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .asp
{background-color:#ffff00;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .html
{color:#800000;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .attr
{color:#ff0000;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .alt
{background-color:#f4f4f4;width:100%;margin:0em;}
.ExternalClassDD2020F98DAE47F59C5986460CDE3F61 .csharpcode .lnum
{color:#606060;}

That is the gist!

Tags:

Leave a Reply