Appendix: Creating the Sample Claims-Aware Application

Applies To: Windows Server 2008 R2

You can use the claims-aware application in this appendix to test which claims a Federation Service sends in Active Directory Federation Services (AD FS) security tokens. This appendix includes instructions for setting up a sample claims-aware application on your Web server. By using this sample claims-aware application and the supporting instructions in Step 3: Configuring the Web Server, you can prepare the application for testing on the client computer and complete the Web server setup process.

The sample claims-aware application is made up of the following three files:

  • Default.aspx

  • Web.config

  • Default.aspx.cs

Membership in the local Administrators group of adfsweb is the minimum required to complete the procedures in this step. Review details about using the appropriate accounts and group memberships at Local and Domain Default Groups (https://go.microsoft.com/fwlink/?LinkId=83477).

For this application to function correctly, you must use the following procedures to create each of the required files in order. After you create the files, move them to the D:\inetpub\wwwroot\claimapp directory on the adfsweb computer.

  • Create the Default.aspx file

  • Create the Web.config file

  • Create the Default.aspx.cs file

Create the Default.aspx file

Use the following procedure to create the Default.aspx file.

To create the Default.aspx file

  1. Start Notepad.

  2. Copy and paste the following code into a new Notepad file:

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

    <%@ OutputCache Location="None" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "https://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

    <html xmlns="https://www.w3.org/1999/xhtml" >

    <head>

    <meta http-equiv="Content-Language" content="en-us">

    <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">

    <title>Claims-aware Sample Application</title>

    <style>

    <!--

    .pagetitle { font-family: Verdana; font-size: 18pt; font-weight: bold;}

    .propertyTable td { border: 1px solid; padding: 0px 4px 0px 4px}

    .propertyTable th { border: 1px solid; padding: 0px 4px 0px 4px; font-weight: bold; background-color: #cccccc ; text-align: left }

    .propertyTable { border-collapse: collapse;}

    td.l{ width: 200px }

    tr.s{ background-color: #eeeeee }

    .banner { margin-bottom: 18px }

    .propertyHead { margin-top: 18px; font-size: 12pt; font-family: Arial; font-weight: bold; margin-top: 18}

    .abbrev { color: #0066FF; font-style: italic }

    -->

    </style>

    </head>

    <body>

    <form ID="Form1" runat=server>

    <div class=banner>

    <div class=pagetitle>SSO Sample</div>

    [ <asp:HyperLink ID=SignOutUrl runat=server>Sign Out</asp:HyperLink> | <a href="<%=Context.Request.Url.GetLeftPart(UriPartial.Path)%>">Refresh without viewstate data</a>]

    </div>

    <div class=propertyHead>Page Information</div>

    <div style="padding-left: 10px; padding-top: 10px">

    <asp:Table runat=server ID=PageTable CssClass=propertyTable>

    <asp:TableHeaderRow>

    <asp:TableHeaderCell>Name</asp:TableHeaderCell>

    <asp:TableHeaderCell>Value</asp:TableHeaderCell>

    <asp:TableHeaderCell>Type</asp:TableHeaderCell>

    </asp:TableHeaderRow>

    </asp:Table>

    </div>

    <div class=propertyHead>User.Identity</div>

    <div style="padding-left: 10px; padding-top: 10px">

    <asp:Table CssClass="propertyTable" ID=IdentityTable runat=server>

    <asp:TableHeaderRow>

    <asp:TableHeaderCell>Name</asp:TableHeaderCell>

    <asp:TableHeaderCell>Value</asp:TableHeaderCell>

    <asp:TableHeaderCell>Type</asp:TableHeaderCell>

    </asp:TableHeaderRow>

    </asp:Table>

    </div>

    <div class=propertyHead>(IIdentity)User.Identity</div>

    <div style="padding-left: 10px; padding-top: 10px">

    <asp:Table CssClass="propertyTable" ID=BaseIdentityTable runat=server>

    <asp:TableHeaderRow>

    <asp:TableHeaderCell>Name</asp:TableHeaderCell>

    <asp:TableHeaderCell>Value</asp:TableHeaderCell>

    <asp:TableHeaderCell>Type</asp:TableHeaderCell>

    </asp:TableHeaderRow>

    </asp:Table>

    </div>

    <div class=propertyHead>(SingleSignOnIdentity)User.Identity</div>

    <div style="padding-left: 10px; padding-top: 10px">

    <asp:Table CssClass="propertyTable" ID=SSOIdentityTable runat=server>

    <asp:TableHeaderRow>

    <asp:TableHeaderCell>Name</asp:TableHeaderCell>

    <asp:TableHeaderCell>Value</asp:TableHeaderCell>

    <asp:TableHeaderCell>Type</asp:TableHeaderCell>

    </asp:TableHeaderRow>

    </asp:Table>

    </div>

    <div class=propertyHead>SingleSignOnIdentity.SecurityPropertyCollection</div>

    <div style="padding-left: 10px; padding-top: 10px">

    <asp:Table CssClass="propertyTable" ID=SecurityPropertyTable runat=server>

    <asp:TableHeaderRow>

    <asp:TableHeaderCell>Uri</asp:TableHeaderCell>

    <asp:TableHeaderCell>Claim Type</asp:TableHeaderCell>

    <asp:TableHeaderCell>Claim Value</asp:TableHeaderCell>

    </asp:TableHeaderRow>

    </asp:Table>

    </div>

    <div class=propertyHead>(IPrincipal)User.IsInRole(...)</div>

    <div style="padding-left: 10px; padding-top: 10px">

    <asp:Table CssClass="propertyTable" ID=RolesTable runat=server>

    </asp:Table>

    <div style="padding-top: 10px">

    <table>

    <tr><td>Roles to check (semicolon separated):</td></tr>

    <tr><td><asp:TextBox ID=Roles Columns=55 runat=server/></td><td align=right><asp:Button UseSubmitBehavior=true ID=GetRoles runat=server Text="Check Roles" OnClick="GoGetRoles"/></td></tr>

    </table>

    </div>

    </div>

    </form>

    </body>

    </html>

  3. Save the Notepad file as Default.aspx in the D:\inetpub\wwwroot\claimapp directory.

Create the Web.config file

Use the following procedure to create the Web.config file.

To create the Web.config file

  1. Start Notepad.

  2. Copy and paste the following code into a new Notepad file:

    <?xml version="1.0" encoding="utf-8" ?>

    <configuration>

    <configSections>

    <sectionGroup name="system.web">

    <section name="websso"

    type="System.Web.Security.SingleSignOn.WebSsoConfigurationHandler, System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null" />

    </sectionGroup>

    </configSections>

    <system.web>

    <sessionState mode="Off" />

    <compilation defaultLanguage="c#" debug="true">

    <assemblies>

    <add assembly="System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null"/>

    <add assembly="System.Web.Security.SingleSignOn.ClaimTransforms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null"/>

    </assemblies>

    </compilation>

    <customErrors mode="Off"/>

    <authentication mode="None" />

    <httpModules>

    <add

    name="Identity Federation Services Application Authentication Module"

    type="System.Web.Security.SingleSignOn.WebSsoAuthenticationModule, System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null" />

    </httpModules>

    <websso>

    <authenticationrequired />

    <eventloglevel>55</eventloglevel>

    <auditsuccess>2</auditsuccess>

    <urls>

    <returnurl>https://adfsweb.treyresearch.net/claimapp/</returnurl>

    </urls>

    <cookies writecookies="true">

    <path>/claimapp</path>

    <lifetime>240</lifetime>

    </cookies>

    <fs>https://adfsresource.treyresearch.net/adfs/fs/federationserverservice.asmx</fs>

    </websso>

    </system.web>

    <system.diagnostics>

    <switches>

    <add name="WebSsoDebugLevel" value="0" /> <!-- Change to 255 to enable full debug logging -->

    </switches>

    <trace autoflush="true" indentsize="3">

    <listeners>

    <add name="LSLogListener" type="System.Web.Security.SingleSignOn.BoundedSizeLogFileTraceListener, System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null"

    initializeData="d:\logdir\claimapp.log" />

    </listeners>

    </trace>

    </system.diagnostics>

    </configuration>

  3. Save the Notepad file as Web.config in the D:\inetpub\wwwroot\claimapp directory.

Create the Default.aspx.cs file

Use the following procedure to create the Default.aspx.cs file.

To create the Default.aspx.cs file

  1. Start Notepad.

  2. Copy and paste the following code into a new Notepad file:

    using System;

    using System.Data;

    using System.Collections.Generic;

    using System.Configuration;

    using System.Reflection;

    using System.Web;

    using System.Web.Security;

    using System.Web.UI;

    using System.Web.UI.WebControls;

    using System.Web.UI.WebControls.WebParts;

    using System.Web.UI.HtmlControls;

    using System.Security;

    using System.Security.Principal;

    using System.Web.Security.SingleSignOn;

    using System.Web.Security.SingleSignOn.Authorization;

    public partial class _Default : System.Web.UI.Page

    {

    const string NullValue = "<span class=\"abbrev\" title=\"Null Reference, or not applicable\"><b>null</b></span>";

    static Dictionary<string, string> s_abbreviationMap;

    static _Default()

    {

    s_abbreviationMap = new Dictionary<string, string>();

    //

    // Add any abbreviations here. Make sure that prefixes of

    // replacements occur *after* the longer replacement key.

    //

    s_abbreviationMap.Add("System.Web.Security.SingleSignOn.Authorization", "SSO.Auth");

    s_abbreviationMap.Add("System.Web.Security.SingleSignOn", "SSO");

    s_abbreviationMap.Add("System", "S");

    }

    protected void Page_Load(object sender, EventArgs e)

    {

    SingleSignOnIdentity ssoId = User.Identity as SingleSignOnIdentity;

    //

    // Get some property tables initialized.

    //

    PagePropertyLoad();

    IdentityLoad();

    BaseIdentityLoad();

    SSOIdentityLoad(ssoId);

    SecurityPropertyTableLoad(ssoId);

    //

    // Filling in the roles table

    // requires a peek at the viewstate

    // since we have a text box driving this.

    //

    if (!IsPostBack)

    {

    UpdateRolesTable(new string[] { });

    }

    else

    {

    GoGetRoles(null, null);

    }

    //

    // Get the right links for SSO

    //

    if (ssoId == null)

    {

    SignOutUrl.Text = "Single Sign On isn't installed...";

    SignOutUrl.Enabled = false;

    }

    else

    {

    if (ssoId.IsAuthenticated == false)

    {

    SignOutUrl.Text = "Sign In (you aren't authenticated)";

    SignOutUrl.href = ssoId.SignInUrl;

    }

    else

    SignOutUrl.href = ssoId.SignOutUrl;

    }

    }

    void SecurityPropertyTableLoad(SingleSignOnIdentity ssoId)

    {

    Table t = SecurityPropertyTable;

    if (ssoId == null)

    {

    AddNullValueRow(t);

    return;

    }

    //

    // Go through each of the security properties provided.

    //

    bool alternating = false;

    foreach (SecurityProperty securityProperty in ssoId.SecurityPropertyCollection)

    {

    t.Rows.Add(CreateRow(securityProperty.Uri, securityProperty.Name, securityProperty.Value, alternating));

    alternating = !alternating;

    }

    }

    void UpdateRolesTable(string[] roles)

    {

    Table t = RolesTable;

    t.Rows.Clear();

    bool alternating = false;

    foreach (string s in roles)

    {

    string role = s.Trim();

    t.Rows.Add(CreatePropertyRow(role, User.IsInRole(role), alternating));

    alternating = !alternating;

    }

    }

    void IdentityLoad()

    {

    Table propertyTable = IdentityTable;

    if (User.Identity == null)

    {

    AddNullValueRow(propertyTable);

    }

    else

    {

    propertyTable.Rows.Add(CreatePropertyRow("Type name", User.Identity.GetType().FullName));

    }

    }

    void SSOIdentityLoad(SingleSignOnIdentity ssoId)

    {

    Table propertyTable = SSOIdentityTable;

    if (ssoId != null)

    {

    PropertyInfo[] props = ssoId.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);

    AddPropertyRows(propertyTable, ssoId, props);

    }

    else

    {

    AddNullValueRow(propertyTable);

    }

    }

    void PagePropertyLoad()

    {

    Table propertyTable = PageTable;

    string leftSidePath = Request.Url.GetLeftPart(UriPartial.Path);

    propertyTable.Rows.Add(CreatePropertyRow("Simplified Path", leftSidePath));

    }

    void BaseIdentityLoad()

    {

    Table propertyTable = BaseIdentityTable;

    IIdentity identity = User.Identity;

    if (identity != null)

    {

    PropertyInfo[] props = typeof(IIdentity).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);

    AddPropertyRows(propertyTable, identity, props);

    }

    else

    {

    AddNullValueRow(propertyTable);

    }

    }

    void AddNullValueRow(Table table)

    {

    TableCell cell = new TableCell();

    cell.Text = NullValue;

    TableRow row = new TableRow();

    row.CssClass = "s";

    row.Cells.Add(cell);

    table.Rows.Clear();

    table.Rows.Add(row);

    }

    void AddPropertyRows(Table propertyTable, object obj, PropertyInfo[] props)

    {

    bool alternating = false;

    foreach (PropertyInfo p in props)

    {

    string name = p.Name;

    object val = p.GetValue(obj, null);

    propertyTable.Rows.Add(CreatePropertyRow(name, val, alternating));

    alternating = !alternating;

    }

    }

    TableRow CreatePropertyRow(string propertyName, object propertyValue)

    {

    return CreatePropertyRow(propertyName, propertyValue, false);

    }

    TableRow CreatePropertyRow(string propertyName, object value, bool alternating)

    {

    if (value == null)

    return CreateRow(propertyName, null, null, alternating);

    else

    return CreateRow(propertyName, value.ToString(), value.GetType().FullName , alternating);

    }

    TableRow CreateRow(string s1, string s2, string s3, bool alternating)

    {

    TableCell first = new TableCell();

    first.CssClass = "l";

    first.Text = Abbreviate(s1);

    TableCell second = new TableCell();

    second.Text = Abbreviate(s2);

    TableCell third = new TableCell();

    third.Text = Abbreviate(s3);

    TableRow row = new TableRow();

    if (alternating)

    row.CssClass = "s";

    row.Cells.Add(first);

    row.Cells.Add(second);

    row.Cells.Add(third);

    return row;

    }

    private string Abbreviate(string s)

    {

    if (s == null)

    return NullValue;

    string retVal = s;

    foreach (KeyValuePair<string, string> pair in s_abbreviationMap)

    {

    //

    // We only get one replacement per abbreviation call.

    // First one wins.

    //

    if (retVal.IndexOf(pair.Key) != -1)

    {

    string replacedValue = string.Format("<span class=\"abbrev\" title=\"{0}\">{1}</span>", pair.Key, pair.Value);

    retVal = retVal.Replace(pair.Key, replacedValue);

    break;

    }

    }

    return retVal;

    }

    //

    // ASP.NET server side callback

    //

    protected void GoGetRoles(object sender, EventArgs ea)

    {

    string[] roles = Roles.Text.Split(';');

    UpdateRolesTable(roles);

    }

    }

  3. Save the file as Default.aspx.cs in the D:\inetpub\wwwroot\claimapp directory.