<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Adventurous Identity</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/adventurousidentity/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/adventurousidentity/feed.xml</link>
    <description>Thoughts and practices on Cloud Identity</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:38:31 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>ACS v2 OAuth 2.0 Delegation Support Explained</title>
      <link>https://docs.microsoft.com/archive/blogs/adventurousidentity/acs-v2-oauth-2-0-delegation-support-explained</link>
      <pubDate>Sun, 18 Sep 2011 09:04:00 GMT</pubDate>
      <dc:creator><![CDATA[Xuehai Zhang - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/adventurousidentity/2011/09/18/acs-v2-oauth-2-0-delegation-support-explained/</guid>
      <description><![CDATA[ACS v2's support of&nbsp;OAuth 2.0 (hereafter referred as "OAuth2") delegation authorization...]]></description>
      <content:encoded><![CDATA[<p><span>ACS v2's support of&nbsp;<span><span><span>OAuth</span></span></span> 2.0 (hereafter referred as "OAuth2") delegation authorization scenarios has been <a href="https://blogs.objectsharp.com/cs/blogs/steve/archive/2011/04/11/windows-azure-access-control-services-v2-rtw.aspx">blogged</a>&nbsp;and illustrated by a code sample (<a href="https://msdn.microsoft.com/en-us/library/windowsazure/gg185937.aspx"><span><span>msdn</span> article</span></a>, <a href="https://connect.microsoft.com/site1168/Downloads/DownloadDetails.aspx?DownloadID=35417">source code</a>). However,&nbsp;</span>the mechanisms to develop the necessary integration points from various OAuth2's roles (e.g. Client, Authorization Server, and Resource Server etc) to ACS haven't been extensively described and I want to use today's blog to fill this gap.</p>
<h3>Definition of OAuth2 Delegation</h3>
<p>The OAuth2 protocol that ACS v2 conforms and implements is <a href="https://tools.ietf.org/html/draft-ietf-oauth-v2-13"><span>The <span>OAuth</span> 2.0 Authorization Protocol, draft-<span>ietf</span>-<span>oauth</span>-v2-13</span></a>&nbsp;(hereafter referred as "draft 13"). However, comparing to its heavy usage in ACS v2 documentations, "delegation" is not considered as a standard term by OAuth2 protocol specs (appears only once in "Introduction" section). To clarify, in most cases, ACS v2 OAuth2 delegation refers to the authorization flow and scenarios using the "authorization code" authorization grant (section <a href="https://tools.ietf.org/html/draft-ietf-oauth-v2-13#section-1.4">1.4.1</a> and <a href="https://tools.ietf.org/html/draft-ietf-oauth-v2-13#section-4.1">4.1</a>&nbsp;in draft 13).</p>
<h3>The Parsley.com-access-Acme bank-on-behalf-of-Mary Example</h3>
<p><a href="https://www.youtube.com/watch?v=LRNg4tDtrkE">"OAuth2.0 - Part 1-4"</a><span>&nbsp;is one of my favorite screen-cast series which nicely explain how OAuth2 works in 10 min. The <span>screencasts</span> are around a story that Parsley.com, an online personal financial organizer, to access Acme.com, an online bank, for bank account data on behalf of Mary, who is the owner of these banking accounts at Acme.com (hereafter referred as the P.A.M example). I will borrow this as the showcase example to explain ACSv2's OAuth2 delegation support.</span></p>
<h3>Delegation Deep Dive</h3>
<p>First, let's sort out how various OAuth2 roles are mapped in the P.A.M example. The following table describes the mappings.&nbsp;</p>
<table border="1">
<tbody>
<tr>
<td><strong>OAuth2 draft 13</strong></td>
<td><strong>the P.A.M Example</strong></td>
</tr>
<tr>
<td>Resource Owner</td>
<td>Mary</td>
</tr>
<tr>
<td>Protected Resource</td>
<td>Mary's account information with Acme.com</td>
</tr>
<tr>
<td>Resource Server</td>
<td>Acme.com/accounts</td>
</tr>
<tr>
<td>Client</td>
<td>Parsley.com</td>
</tr>
<tr>
<td>Authorization Server</td>
<td><span>Acme.com/<span>authserver</span> (use the same server as the resource server)</span></td>
</tr>
<tr>
<td>Resource Owner's Authentication credential with Client</td>
<td><span>Mary@<span>gmail</span>.com</span></td>
</tr>
<tr>
<td>Resource Owner's Authentication Credential with Authorization Server</td>
<td><span>Mary@<span>hotmail</span>.com</span></td>
</tr>
</tbody>
</table>
<p>Now, let's break down the delegation process into flows and steps, examine the interactions between involved roles in greater details and highlight the ACS integration tasks.</p>
<p>In draft 13's section 4.1, there is an "Authorization Code Flow" diagram illustrating the major authorization flow steps. I took it and expanded to the following set of flow diagrams, which are tailored to the&nbsp;P.A.M example and capture several important flows missed in the original diagram, including the steps for the client to obtain its client credentials, the steps for the client to request protected resources from the resource server and the steps for the client to renew the access token.</p>
<h4>Client Registration Flow</h4>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/0020.oauth2flow1.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/0020.oauth2flow1.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/0020.oauth2flow1.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/0020.oauth2flow1.PNG" width="450" /></a></p>
<p></p>
<p>The client registration flow illustrated in above diagram includes the following steps:</p>
<p><strong>(A) The administrator of Parsley.com (the client) registers Parsley.com with Acme.com/register/ (the application registration portal of Acme.com who runs the authorization server and resource server) by providing information about the client as well as a redirection URI.</strong></p>
<p><span>Parsley.com's admin must provide a redirection URI for Acme.com's authorization server to redirect the user agent back in the "authorization code &amp; access token flow" (described next) once authorization is obtained. The redirect URI conforms the requirements in </span><a href="https://tools.ietf.org/html/draft-ietf-oauth-v2-13#section-2.1">draft 13 section 2.1.1</a>.</p>
<p><strong><span style="color: #008000;">ACS Integration Points:</span></strong>&nbsp;&nbsp;none.</p>
<p><strong>(B) Assuming Acme.com/register/ approves the request of Parsley.com to be a registered client, it responds back with client credentials (a pair of client identifier and client secret) to Parsley.com.</strong></p>
<p><span>As you may find out later in the next "Authorization Code &amp; Access Token Flow" section, Acme.com's authorization server offloads the OAuth2 delegation protocol implementation and processing to ACS. With ACS, Acme.com has created a </span><a href="https://msdn.microsoft.com/en-us/library/gg185908.aspx">service namespace</a><span>&nbsp;(say "<span>acmebank</span>") and a </span><a href="https://msdn.microsoft.com/en-us/library/gg185906.aspx">relaying party (hereafter referred as "RP") application</a><span>&nbsp;representing its account service servicing the protected resources on the resource server.&nbsp;Acme.com/register/ uses ACS to handle Parsley.com's client registration as well, by calling ACS's </span><a href="https://msdn.microsoft.com/en-us/library/gg185945.aspx">service identity</a><span>&nbsp;management service <span>APIs</span>. Internally, ACS records Parsley.com's registration and its credentials in a service identity&nbsp;instance.&nbsp;Upon receipt of the client credentials from ACS, Acme.com/register/ makes this data available to Parsley.com's admin.</span></p>
<p><span style="color: #008000;"><strong>ACS Integration Points:</strong></span></p>
<p><span style="color: #008000;"><strong>#1: <span style="color: #008000;">Create a service identity in ACS as the client credentials representation</span></strong></span></p>
<p>The service identity can be created via the ACS management &nbsp;portal at <a href="https://acmebank.accesscontrol.windows.net/v2/mgmt/web/ServiceIdentity"><span>https://<span>acmebank</span>.<span>accesscontrol</span>.windows.net/v2/<span>mgmt</span>/web/<span>ServiceIdentity</span></span></a>&nbsp;as the following. The client credentials' client identifier and client secret are represented by the Name and Password values respectively.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/6082.addsi.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/6082.addsi.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/6082.addsi.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/6082.addsi.PNG" width="450" /></a>&nbsp;</p>
<p>Alternatively, Acme.com/register/ can call ACS manag<span>ement service OData&nbsp;<span>APIs&nbsp;</span>to programmatically create a service identity. The following is the code snippet using the&nbsp;</span><span class="Apple-style-span" style="font-family: monospace; white-space: pre;">Common.ACS.Management.ManageService </span><span class="Apple-style-span" style="white-space: pre;">APIs provided in <a href="https://acs.codeplex.com/releases/view/57595">ACS 2.0 Samples</a> at codeplex.</span>&nbsp;</p>
<div style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: silver 1px solid; padding: 4px;" id="codeSnippetWrapper">
<pre class="csharpcode"><span class="rem">//Create a service identity</span>
ManagementService svc = ManagementServiceHelper.CreateManagementServiceClient();
ServiceIdentity sid = <span class="kwrd">new</span> ServiceIdentity()
{
    Name = <span class="str">"Parsley.com"</span>
};

ServiceIdentityKey key = <span class="kwrd">new</span> ServiceIdentityKey()
{
    Type = <span class="str">"Password"</span>,
    Usage = <span class="str">"the client secret"</span>,
    Value = <span class="str">"xxxxxx"</span>,
    DisplayName = <span class="str">"the client secret"</span>
};

svc.AddToServiceIdentities(sid);
svc.AddRelatedObject(
    sid,
    <span class="str">"ServiceIdentityKeys"</span>,
    key);
svc.SaveChanges();
</pre>
</div>
<p><span class="Apple-style-span" style="color: #008000;"><b>#2: Configure created Service Identity's RedirectAddress property</b></span></p>
<p>The value of the service identity's RedirectAddress property is mandatory for enabling OAuth2 delegation scenarios and the client&rsquo;s redirect URI&nbsp;parameter must exactly match this value.&nbsp;</p>
<p>Currently, there is no way to view, edit and update the RedirectAddress property of a service identity through ACS management portal&nbsp;and these tasks have to be conducted programmatically &nbsp;through ACS management service OData APIs.</p>
<p>If the service identity is created through the portal in integration point #1, you may use code similar to the following to configure the&nbsp;RedirectAddress property.</p>
<div style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: silver 1px solid; padding: 4px;" id="codeSnippetWrapper">
<pre class="csharpcode"><span class="rem">//Update a service identity's RedirectAddress</span>
ManagementService svc = ManagementServiceHelper.CreateManagementServiceClient();

ServiceIdentity serviceIdentity = svc.ServiceIdentities.Where(si =&gt; si.Name == name).FirstOrDefault();

<span class="kwrd">if</span> (serviceIdentity == <span class="kwrd">null</span>)
{
    <span class="rem">// TODO: throw exception</span>
}

serviceIdentity.RedirectAddress = redirectAddress;
svc.UpdateObject(serviceIdentity);
svc.SaveChanges();
</pre>
</div>
<p>If in #1 you already create the service identity&nbsp;programmatically, you can simply initialize the&nbsp;RedirectAddress property in the service identity's constructor.</p>
<h4>Authorization Code &amp; Access Token Flow</h4>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/4428.oauth2flow2.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/4428.oauth2flow2.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/4428.oauth2flow2.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/4428.oauth2flow2.PNG" width="450" /></a></p>
<p></p>
<p>The authorization code &amp; access token flow illustrated in above diagram includes the following steps:</p>
<p><strong>(C) Parsley.com (the client), initiates the flow by directing Mary (the resource owner)'s Internet Explorer (user-agent) to Acme.com/authserver/auth (the authorization server's authorization endpoint). </strong></p>
<p>Mary logs into Parsley.com using credentials Mary@gmail.com and chooses to add her Acme.com accounts on the dashboard page. She is redirected to Acme.com authorization server's authorization page to log in with her credentials with Acme.com, Mary@hotmail.com. The redirect request also includes Parsley.com's client identifier, requested scope, local state, and a redirection URI to which Acme.com's authorization server will send the Internet Explorer back once access is granted (or denied) by Mary.</p>
<p><span style="color: #008000;"><strong>ACS Integration Points:</strong></span>&nbsp;&nbsp;none.</p>
<p><strong>(D) Acme.com/authserver/ authenticates Mary (via the Internet Explorer) and establishes whether Mary grants or denies Parsley.com's access request.</strong></p>
<p>After logging in, Acme.com/authserver/ shows Mary an UI for her to approve or deny Parsley.com's access to her account data with Acme.com.&nbsp;</p>
<p><span style="color: #008000;"><strong>ACS Integration Points:</strong></span>&nbsp;&nbsp;none.</p>
<p><strong>(E) Assuming Mary grants access, Acme.com/authserver/ redirects the Internet Explorer back to Parsley.com using the redirection URI provided in step (C). The redirection URI includes an authorization code.</strong></p>
<p>If Mary has granted the access, Acme.com's authorization server will make a request to ACS for a new authorization code by providing Parsley.com's client identifier, the name of RP for the Acme.com's account service, and Mary's credentials with the authorization server in the request. Upon receipt of this request, ACS will create a <a href="https://msdn.microsoft.com/en-us/library/windowsazure/hh180762.aspx">Delegation</a>&nbsp;instance internally to represent the tri-party delegation relationship between Parsley.com, Acme.com/accounts/ and Mary. &nbsp;This delegation object comes with an AuthorizationCode property, which is populated with a Base64 encoded, random sequence of 16 bytes. ACS returns this code to&nbsp;the authorization server's authorization endpoint and the latter redirects to the redirection URI passed by Parsley.com in step (C) and append the code to the query parameter.</p>
<p><span style="color: #008000;"><strong>ACS Integration Points:</strong></span></p>
<p><span style="color: #008000;"><strong>#3:&nbsp;Create a delegation and return the authorization code</strong></span></p>
<p>The following code snippets show how to create the delegation representing the {service identity name or client name, RP name, user name} triplet and returns the authorization code value of the created delegation object via ACS management service OData APIs.&nbsp;</p>
<div style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: silver 1px solid; padding: 4px;" id="codeSnippetWrapper">
<pre class="csharpcode"><span class="rem">// Create a delegation and return the authorization code</span>
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> GetAuthorizationCode(<span class="kwrd">string</span> serviceIdentityName, <span class="kwrd">string</span> relyingPartyName, <span class="kwrd">string</span> userName, <span class="kwrd">string</span> identityProvider)
{
    ServiceIdentity serviceIdentity;
    RelyingParty relyingParty;
    Delegation delegation;
    <span class="kwrd">string</span> code = <span class="kwrd">null</span>;

    <span class="kwrd">try</span>
    {
        serviceIdentity = GetServiceIdentityByName(serviceIdentityName);
        relyingParty = GetRelyingPartyByName(relyingPartyName);
        <span class="kwrd">if</span> (serviceIdentity != <span class="kwrd">null</span> &amp;&amp; relyingParty != <span class="kwrd">null</span>)
        {
            delegation = CreateDelegation(serviceIdentity.Id, relyingParty.Id, userName, identityProvider);
            <span class="kwrd">if</span> (delegation != <span class="kwrd">null</span>)
            {
                code = delegation.AuthorizationCode;
            }
        }
    }
    <span class="kwrd">catch</span> (Exception)
    {
        <span class="rem">// delegation failed</span>
        code = <span class="kwrd">null</span>;
    }

    <span class="kwrd">return</span> code;
}

<span class="kwrd">public</span> <span class="kwrd">static</span> ServiceIdentity GetServiceIdentityByName(<span class="kwrd">string</span> name)
{
    ManagementService svc = ManagementServiceHelper.CreateManagementServiceClient();

    ServiceIdentity identity = svc.ServiceIdentities.AddQueryOption(<span class="str">"$filter"</span>, <span class="str">"Name eq '"</span> + name + <span class="str">"'"</span>).FirstOrDefault();

    <span class="kwrd">return</span> identity;
}

<span class="kwrd">public</span> <span class="kwrd">static</span> RelyingParty GetRelyingPartyByName(<span class="kwrd">string</span> name)
{
    ManagementService svc = ManagementServiceHelper.CreateManagementServiceClient();

    RelyingParty relyingParty = svc.RelyingParties.Where(m =&gt; m.Name == name).FirstOrDefault();

    <span class="kwrd">return</span> relyingParty;
}

<span class="kwrd">public</span> <span class="kwrd">static</span> Delegation CreateDelegation(<span class="kwrd">long</span> serviceIdentityId, <span class="kwrd">long</span> relyingPartyId, <span class="kwrd">string</span> userName, <span class="kwrd">string</span> identityProvider)
{
    ManagementService svc = ManagementServiceHelper.CreateManagementServiceClient();

    Delegation delegation = <span class="kwrd">new</span> Delegation()
    {
        NameIdentifier = userName,
        IdentityProvider = identityProvider,
        RelyingPartyId = relyingPartyId,
        ServiceIdentityId = serviceIdentityId,
    };

    svc.AddToDelegations(delegation);
    svc.SaveChanges();

    <span class="kwrd">return</span> delegation;
}</pre>
</div>
<p><strong>(F) Parsley.com requests an access token from Acme.com/authserver/token (the authorization server's token endpoint) by authenticating using its client credentials, and includes the authorization code received in step (E).</strong></p>
<p>After Parsley.com receives the authorization code, it can use the authorization code in exchange for an access token and an refresh token from Acme.com authorization server's token endpoint. Beside the authorization code, the request should also include Parsley.com's client credentials, a redirect URI for Parsley.com to receive the access/refresh tokens.</p>
<p><span style="color: #008000;"><strong>ACS Integration Points:</strong></span>&nbsp;&nbsp;none.</p>
<p><strong>(G) Acme.com/authserver/ validates Parsley.com's client credentials and the authorization code and if valid, responds back with an access token and a refresh token.</strong></p>
<p>Upon receipt of the access token request, Acme.com's authorization server will send a HTTP POST request to "acmebank" service namespace's ACS OAuth2 endpoint (https://acmebank.accesscontrol.windows.net/v2/OAuth2-13). ACS will return a refresh token and a short-lived acces token in a JSON object back to Parsley.com.</p>
<p><span style="color: #008000;"><strong>ACS Integration Points:</strong></span></p>
<p><span style="color: #008000;"><strong>#4: POST a HTTP request to ACS OAuth2 endpoint for an access token</strong></span></p>
<p>Clients such as Parsley.com can programmatically create an HTTP POST request containing the client credentials, the authorization code obtained in previous step, a redirect URI, and a grant type fixed to "authorization_code". The request may look like:</p>
<div style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: silver 1px solid; padding: 4px;" id="codeSnippetWrapper">
<pre class="csharpcode">POST /v2/OAuth2-13 HTTP/1.1
Host: acmebank.accesscontrol.windows.net
Content-Type: application/x-www-form-urlencoded

code=xxxxxxxxxxxxxx&amp;
client_id=Parsley.com&amp;
client_secret=xxxxxxxxxxxxxx&amp;
redirect_uri=https://www.parsley.com/back&amp;
grant_type=authorization_code
</pre>
</div>
<p>ACS returns the access token and refresh token in a JSON object in the response to the above request. The JSON object may look like:</p>
<div style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: silver 1px solid; padding: 4px;" id="codeSnippetWrapper">
<pre class="csharpcode">{
  "access_token":"xxxxxxxxxxxxxxxxxx",
  "expires_in":3920,
  "token_type":"Bearer",
  "refresh_token":"xxxxxxxxxxxxxxxxxxxx"
}</pre>
</div>
<p><span class="Apple-style-span" style="font-weight: bold;">Protected Resource Access Flow</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/2476.oauth2flow3.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/2476.oauth2flow3.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/2476.oauth2flow3.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/2476.oauth2flow3.PNG" width="450" /></a></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/7506.oauth2flow.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/7506.oauth2flow.PNG"></a>The protected resource access flow illustrated in above diagram includes the following steps:</p>
<p><strong>(H) Parsley.com retrieves Mary's account information (the protected resource) from Acme.com/accounts/ (the resource server) by providing the access token received in step (G).</strong></p>
<p>After receiving the access token, Parsley.com can use it to call Acme.com's account service to fetch the protected resources, i.e. Mary's account data with Acme.com, on behalf of Mary. It sends an HTTPS GET request by including the access token as part of the query parameter (alternatively, Parsley.com can embed the token in the HTTP request's "Authorization" header).</p>
<p><span style="color: #008000;"><strong>ACS Integration Points:</strong></span>&nbsp;&nbsp;none.</p>
<p><strong>(I) Acme.com/accounts validates Parsley.com's account access request and the access token and if valid, responds back with the request account information belonging to Mary.</strong></p>
<p>Upon receipt of the account data request from Parsley.com, Acme.com's account service will parse the access token from the incoming request (either from the query parameter or the "Authorization" HTTP header) and validate the parsed token. On successful validation, it will return the requested account data back to Parsley.com.</p>
<p><span style="color: #008000;"><strong>ACS Integration Points:</strong>&nbsp;</span></p>
<p><span style="color: #008000;"><strong>#5: Validate access token in the account access request</strong></span></p>
<p>Critically speaking, there is no ACS integration required in this step and it is Acme.com account service's sole responsibility to handle the access token parsing and validation. However, to bring a better develop experience to ACS OAuth2 delegation application developers, ACS would provide APIs to handle the parsing and validation of various ACS tokens embedded in the access token, such as <a href="https://groups.google.com/group/WRAP-WG/attach/dad50fbc0c13b689/SWT-v0.9.4.2.pdf?part=5">Simple Web Token</a> (SWT). (<em>Note: even though ACS v2 still heavily uses SWT as a token format, there is not any official specification about SWT published.)</em></p>
<p>For example, in&nbsp;<a href="https://blogs.msdn.com/controlpanel/blogs/posteditor.aspx/ACS OAuth2 delegation samplehttps:/connect.microsoft.com/site1168/Downloads/DownloadDetails.aspx?DownloadID=35417">ACS OAuth2 delegation sample</a>, it provides a&nbsp;<span class="Apple-style-span" style="font-family: monospace; white-space: pre;">SimpleWebTokenHandler </span>and&nbsp;<span class="Apple-style-span" style="font-family: monospace; white-space: pre;">SimpleWebToken </span>classes to help with handling SWT-typed access token processing.</p>
<h4><span class="Apple-style-span" style="font-weight: bold;">Access Token Renew Flow</span></h4>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/0216.oauth2flow3.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/0216.oauth2flow3.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/0216.oauth2flow3.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/0216.oauth2flow3.PNG" width="450" /></a></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/7506.oauth2flow.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/7506.oauth2flow.PNG"></a>The access token renew flow illustrated in above diagram includes the following steps:</p>
<p><strong>(J) Parsley.com (the client) sends the renew access token request to Acme.com/authserver/auth (the authorization server's authorization endpoint). Parsley.com includes its client credentials, the redirection URI and the refresh token received in step (G).</strong></p>
<p><span>When the access token returned in step (G) expires, Acme.com's account service endpoint will respond with HTTP 401 Unauthorized. Parsley.com can use the refresh token (also returned in step (G)) to request a new short-lived access token from Acme.com authorization server's token endpoint.&nbsp;</span></p>
<p><span style="color: #008000;"><strong>ACS Integration Points:</strong></span></p>
<p><span style="color: #008000;"><strong>#6: POST a HTTP request to ACS OAuth2 endpoint to renew the access token</strong></span></p>
<p>Parsley.com can programmatically create an HTTP POST request containing the client credentials, the refresh token obtained in step (G), and a grant type fixed to "refresh_token" in exchange for a new set of access token and refresh token. The request may look like:</p>
<div style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: silver 1px solid; padding: 4px;" id="codeSnippetWrapper">
<pre class="csharpcode">POST /v2/OAuth2-13 HTTP/1.1
Host: acmebank.accesscontrol.windows.net
Content-Type: application/x-www-form-urlencoded

code=xxxxxxxxxxxxxx&amp;
client_id=Parsley.com&amp;
client_secret=xxxxxxxxxxxxxx&amp;
grant_type=refresh_token
</pre>
</div>
<p><strong>(K) Acme.com/authserver/ validates Parsley.com's client credentials and the refresh token and if valid, responds back with a new access token and a new refresh token.</strong></p>
<p>Similar to above integration point #4, ACS returns the access token and refresh token in a JSON object in the response to the above renewal request.&nbsp;</p>
<p><strong><br /></strong></p>]]></content:encoded>
    </item>
    <item>
      <title>The PHP Way of Federated Login with ACS</title>
      <link>https://docs.microsoft.com/archive/blogs/adventurousidentity/the-php-way-of-federated-login-with-acs</link>
      <pubDate>Fri, 02 Sep 2011 14:38:00 GMT</pubDate>
      <dc:creator><![CDATA[Xuehai Zhang - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/adventurousidentity/2011/09/02/the-php-way-of-federated-login-with-acs/</guid>
      <description><![CDATA[Today's post introduces a PHP ACS Federation (ACSFed)&nbsp;library&nbsp;to assist PHP developers to...]]></description>
      <content:encoded><![CDATA[<p>Today's post introduces a PHP ACS Federation (ACSFed)&nbsp;library&nbsp;to assist PHP developers to enable federated <span><span>login and&nbsp;Single Sign On (SSO)</span></span>&nbsp;for their sites using <a href="https://msdn.microsoft.com/en-us/library/gg429786.aspx" target="_blank">Windows Azure <span><span>AppFabric</span></span> Access Control Service </a>(ACS) 2.0.</p>
<p>If you are not&nbsp;<span>familiar</span><span> with ACS's role as the Federated Provider (FP) to support federated authentication,&nbsp;</span>Eugenio explained it nicely in a series of blogs and you can find the very first post <a href="https://blogs.msdn.com/b/eugeniop/archive/2011/02/08/access-control-service-as-a-federation-provider.aspx" target="_blank">here</a>.</p>
<p>Let's start with a tour&nbsp;of a&nbsp;demo PHP site built with ACSFed lib and then revisit the configurations, logic and code&nbsp;behind the scene.</p>
<h3>AcsFedDemo&nbsp;RP&nbsp;Site</h3>
<p>We use <a href="https://adventurousid.phpfogapp.com/acsfeddemo/">https://adventurousid.phpfogapp.com/acsfeddemo/</a>, a very simple demo&nbsp;site deployed and running on <a href="https://phpfog.com/" target="_blank">PHP Fog</a>&nbsp;to showcase the ACSFed lib. PHP Fog is a cloud platform hosting PHP site. It has&nbsp; a very <a href="https://www.heroku.com/" target="_blank">heroku</a>-alike experience and&nbsp;uses <a href="https://github.com/">Git</a> as version control tool as well.</p>
<p>Since it is your first time visiting the AcsFedDemo site, the site identifies you are not authenticated and redirects you to a login page. The login page shows a list of available Identity Providers (IdPs) for you to choose to authenticate with (see below). These IdPs are preconfigured by the site owner (me in this case) in ACS and we will cover the configuration details later.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/4137.login.JPG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/4137.login.JPG"><img border="0" alt="" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/4137.login.JPG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/4137.login.JPG" width="442" height="85" /></a></p>
<p>Pick one of the IdPs, say Yahoo!, to continue. You will be redirected to the Yahoo! login portal. You may notice the highlighted&nbsp;"adventurousid.accesscontrol.windows.net" in the red box, this is the ACS Security Token Service (STS) endpoint taking AcsFedDemo site as one of its RPs to manage. As&nbsp;mentioned&nbsp;earlier, it is configured to trust the Yahoo IdP&nbsp;to authentication the user. Now input your Yahoo! ID ("<em>php.adventurousid@yahoo.com</em>" in this case) and password and continue to sign in.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/6320.yahoo1.JPG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/6320.yahoo1.JPG"><img border="0" alt="" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/6320.yahoo1.JPG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/6320.yahoo1.JPG" width="321" height="266" /></a>&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/4341.yahoo2.JPG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/4341.yahoo2.JPG"></a><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/8117.yahoo1.JPG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/8117.yahoo1.JPG"></a></p>
<p>Next you will be prompted to give permission to sign in to the ACS STS endpoint and share the information of your Yahoo! account.</p>
<p><br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/4341.yahoo2.JPG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/4341.yahoo2.JPG"><img border="0" alt="" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/4341.yahoo2.JPG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/4341.yahoo2.JPG" width="293" height="193" /></a></p>
<p>Once you allow the access, you successfully&nbsp;finish the federated login with the AcsFedDemo site and your browser will be redirected to the site's home page, as shown below. For exhibition purpose, the fact that you federated-login through Yahoo! as well as your Yahoo! identity information are&nbsp;reflected explicitly in the page (see the highlighted texts).&nbsp;</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/4428.rp.JPG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/4428.rp.JPG"><img border="0" alt="" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/4428.rp.JPG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/4428.rp.JPG" /></a></p>
<h3>&nbsp;Under the Hood</h3>
<p>A couple of tasks have been done to bring the federated login support to the AcsFedDemo site and we now discuss them in details below.</p>
<p>First, the site owner needs to configure ACS to enable federated authentication with the RP site.</p>
<h4>Configuring ACS</h4>
<p>The ACS configuration process for AcsFedDemo site is very much alike the process used to install ACS WordPress Plugin and you may find the detailed step-by-step explanation at <a href="https://acs.codeplex.com/wikipage?title=WordPress%20Plugin">https://acs.codeplex.com/wikipage?title=WordPress%20Plugin.</a></p>
<p>The primary differences are the <em>Realm</em> and <em>Return URL</em> settings in the <em>Relying Party Applications</em> setup step and the following screenshot captures them as highlights. Same as the ACS WordPress Plugin, we configure the ACS STS endpoint to issue Simple Web Token (SWT) to AcsFedDemo RP site as well.</p>
<p>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/5344.acsconfig.JPG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/5344.acsconfig.JPG"><img border="0" alt="" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/5344.acsconfig.JPG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/5344.acsconfig.JPG" width="357" height="344" /></a></p>
<p>Secondly, the site owner needs to integrate AcsFed lib into the RP site implementation. We will describe the AcsFed lib API briefly first and then examine the integration points in the AcsFedDemo implentation.</p>
<h4>AcsFed Library</h4>
<p>AcsFed library is developed based on the code base of <a href="https://wordpress.org/extend/plugins/acs-plugin-for-wordpress/" target="_blank">ACS Plugin for WordPress</a>, which is heavily abstracted and refactored.&nbsp;Its design goal&nbsp;is to be&nbsp;delivered as a general-purposed library to easily integrate with any PHP site to provide federated login with ACS support.</p>
<p>The libaray is&nbsp;organized as the following (the directory hierarchy is designed to match the hierarchy&nbsp;of the namespaces, which&nbsp;haven't&nbsp;not been implemented yet in the current code).</p>
<p>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/0020.lib1.JPG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/0020.lib1.JPG"><img border="0" alt="" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/0020.lib1.JPG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/0020.lib1.JPG" width="229" height="365" /></a><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/1803.lib1.JPG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/1803.lib1.JPG"></a><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/46/82/2677.lib1.JPG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-82/2677.lib1.JPG"></a></p>
<ul>
<li><em><strong>ms/acs: </strong></em>This namespace holds the classes for ACS common entities, supported protocols and token handlers.</li>
<ul>
<li><strong><em>ms/acs/common</em>: </strong>ACS supported claim types (represented in URLs) and token types are defined here.</li>
<li><strong><em>ms/acs/protocols</em>: </strong>WSFederationHandler.php primarily&nbsp;deals with the WS-Federation <span style="font: small/16px arial, sans-serif; color: #000000; text-transform: none; text-indent: 0px; letter-spacing: normal; word-spacing: 0px; white-space: normal; orphans: 2; widows: 2; font-size-adjust: none; font-stretch: normal; background-color: #ffffff; -webkit-text-size-adjust: auto; -webkit-text-decorations-in-effect: none; -webkit-text-stroke-width: 0px;" class="Apple-style-span">RequestSecurityTokenResponse<span class="Apple-converted-space">&nbsp;(RSTR) messages.</span></span></li>
<li><strong><em>ms/acs/tokens</em>:</strong> This namespace contains&nbsp;an interface for all token handlers to implement and a factory class to generate a specific token handler based on the token format type. In addition, it defines a concrete token handler to process Simple Web Token (SWT).</li>
</ul>
<li><em><strong>ms/acsfed: </strong></em>This namespace holds the classes and resources to integrate with the RP site to enable federated login.</li>
<ul>
<li><em><strong>AcsFed.php</strong></em>: It offers two primary APIs to assist the RP site to create the federation login page and parse the WS-Federation RSTR to extract ACS token and then the embedded claims.</li>
<li><em><strong>AcsFedConfig.php</strong></em>: It defines the following configuration&nbsp;data&nbsp;required in the federated login process. Some of the data, such as the&nbsp;token signing keys, are&nbsp;sensitive and should be kept in a secure way.</li>
<ul>
<li>SERVICE_NAMESPACE</li>
<li>RELYING_PARTY_APPLICATION_REALM</li>
<li>TOKEN_SIGNING_KEY and TOKEN_SIGNING_KEY_OLD</li>
<li>TOKEN_TYPE</li>
<li>HOME_REALM_DISCOVERY_FEED_URL</li>
</ul>
<li><strong>.<em>htaccess</em></strong>: It is used to protected the sensitive data in AcsFedConfig.php.</li>
<li><em><strong>ms/acsfed/css</strong></em>: Contains ACS-specific style sheet required to render the federated login widget.</li>
<li><em><strong>ms/acsfed/js</strong></em>: Contains JavaScripts required to render the federated login widget.</li>
</ul>
</ul>
<p>Next, we show&nbsp;several code snippets (<span style="font-size: x-small;">syntax highlighted by <a href="https://tohtml.com/">https://tohtml.com/</a></span>)&nbsp;to&nbsp;capture&nbsp;the major integration points to integrate PHP ACS Federation Library with&nbsp;the AcsFedDemo RP site.</p>
<h4>RP Site Integration&nbsp;</h4>
<ul>
<li><em><strong>&nbsp;AcsFedDemo's login page</strong></em></li>
</ul>
<p style="padding-left: 30px;"><strong><em></em></strong>&nbsp;The login page, redirected from the&nbsp;home page on an&nbsp;unauthenticated access, is&nbsp;responsible for rendering the federated login widget for the user to authenticate with&nbsp;RP site's&nbsp;supported IdPs. As illustrated in the following highlights, it makes use of the acs_fed.css CSS style sheet and acs_fed.js Javascript in the web head&nbsp;and calls AcsFed::createLoginForm() to render the widget in the web body.</p>
<pre style="color: #000020; padding-left: 30px; background-color: #f6f8ff;"><span style="color: #0057a6; background-color: #cceeee;">&lt;?php</span><span style="color: #000000; background-color: #cceeee;"> </span>
<span style="color: #200080; font-weight: bold; background-color: #cceeee;">require_once</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #1060b6; background-color: #cceeee;">'ms/acsfed/AcsFed.php'</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #400000; background-color: #cceeee;">session_start</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #0057a6; background-color: #cceeee;">?&gt;</span>

<span style="color: #0057a6;">&lt;</span><span style="color: #200080; font-weight: bold;">html</span><span style="color: #0057a6;">&gt;</span>
 <span style="color: #0057a6;">&lt;</span><span style="color: #200080; font-weight: bold;">head</span><span style="color: #0057a6;">&gt;</span>
  <span style="color: #0057a6;">&lt;</span><span style="color: #200080; font-weight: bold;">title</span><span style="color: #0057a6;">&gt;</span>Federated Login via ACS<span style="color: #0057a6;">&lt;/</span><span style="color: #200080; font-weight: bold;">title</span><span style="color: #0057a6;">&gt;</span>
  <span style="color: #0057a6;">&lt;</span><span style="color: #200080; font-weight: bold;">link</span><span style="color: #474796;"> </span><span style="color: #074726;">href</span><span style="color: #308080;">=</span><span style="color: #1060b6;">"<span style="background-color: #ffcc00;">ms/acsfed/css/acs_fed.css</span>"</span><span style="color: #474796;"> </span><span style="color: #074726;">rel</span><span style="color: #308080;">=</span><span style="color: #1060b6;">"stylesheet"</span><span style="color: #474796;"> </span><span style="color: #074726;">type</span><span style="color: #308080;">=</span><span style="color: #1060b6;">"text/css"</span><span style="color: #0057a6;">&gt;</span>
  <span style="color: #0057a6;">&lt;</span><span style="color: #200080; font-weight: bold;">script type="text/javascript" src="<span style="background-color: #ffcc00;">ms/acsfed/js/acs_fed.js</span>"</span><span style="color: #0057a6;">&gt;</span><span style="color: #0057a6;">&lt;/</span><span style="color: #200080; font-weight: bold;">script</span><span style="color: #0057a6;">&gt;</span>
 <span style="color: #0057a6;">&lt;/</span><span style="color: #200080; font-weight: bold;">head</span><span style="color: #0057a6;">&gt;</span>
 <span style="color: #0057a6;">&lt;</span><span style="color: #200080; font-weight: bold;">body</span><span style="color: #0057a6;">&gt;</span>
     <span style="color: #0057a6;">&lt;</span><span style="color: #200080; font-weight: bold;">p</span><span style="color: #0057a6;">&gt;</span>
<span style="color: #0057a6;">&lt;</span><span style="color: #200080; font-weight: bold;">h2</span><span style="color: #0057a6;">&gt;</span>Demo RP Site using <span style="color: #0057a6;">&lt;</span><span style="color: #200080; font-weight: bold;">a</span><span style="color: #474796;"> </span><span style="color: #074726;">href</span><span style="color: #308080;">=</span><span style="color: #1060b6;">"https://blogs.msdn.com/b/adventurousidentity/"</span><span style="color: #0057a6;">&gt;</span>PHP ACS Fed Lib<span style="color: #0057a6;">&lt;/</span><span style="color: #200080; font-weight: bold;">a</span><span style="color: #0057a6;">&gt;</span><span style="color: #0057a6;">&lt;/</span><span style="color: #200080; font-weight: bold;">h2</span><span style="color: #0057a6;">&gt;</span>
     <span style="color: #0057a6; background-color: #cceeee;">&lt;?php</span><span style="color: #000000; background-color: #cceeee;"> </span>
<span style="background-color: #ffcc00;"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AcsFed</span><span style="color: #308080;">::</span><span style="color: #007d45;">createLoginForm</span><span style="color: #308080;">(</span><span style="color: #308080;">)</span><span style="color: #406080;">;</span><span style="color: #000000;"> </span></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0057a6; background-color: #cceeee;">?&gt;</span> 
 <span style="color: #0057a6;">&lt;/</span><span style="color: #200080; font-weight: bold;">body</span><span style="color: #0057a6;">&gt;</span>
<span style="color: #0057a6;">&lt;/</span><span style="color: #200080; font-weight: bold;">html</span><span style="color: #0057a6;">&gt;</span></pre>
<ul>
<li><strong><em>AcsFedDemo's auth page</em></strong></li>
</ul>
<p style="padding-left: 30px;">The auth page, whose URL is configured as the <em>Return URL</em> value in RP site's corresponding ACS RP configuration,&nbsp;will be posted with the WS-Federated RSTR containing ACS SWT token by RP site's ACS STS endpoint. It utilizes AcsFed::parseTokenAndExtractClaims(RSTR) to validate the RSTR, extract the ACS token and further extract the embedded claims.&nbsp;</p>
<pre style="color: #000020; padding-left: 30px; background-color: #f6f8ff;"><span style="color: #0057a6; background-color: #cceeee;">&lt;?php</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #200080; font-weight: bold; background-color: #cceeee;">function</span><span style="color: #000000; background-color: #cceeee;"> authenticate</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #007d45; background-color: #cceeee;">$username</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #1060b6; background-color: #cceeee;">""</span><span style="color: #308080; background-color: #cceeee;">,</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$password</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #1060b6; background-color: #cceeee;">""</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #000000; background-color: #cceeee;"> </span>
<span style="color: #406080; background-color: #cceeee;">{</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #595979; background-color: #cceeee;">//Check to see if a token is being posted from ACS (using the WS-Federation protocol)</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="background-color: #ffff00;"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45;">$rstr</span><span style="color: #000000;"> </span><span style="color: #308080;">=</span><span style="color: #000000;"> </span><span style="color: #406080;">@</span><span style="color: #007d45;">$_POST</span><span style="color: #308080;">[</span><span style="color: #1060b6;">'wresult'</span><span style="color: #308080;">]</span><span style="color: #406080;">;</span><span style="color: #000000;"></span> </span><span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">if</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #007d45; background-color: #cceeee;">$rstr</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #000000; background-color: #cceeee;"> </span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">{</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #595979; background-color: #cceeee;">//Decode the response if it was reposted as part of the account creation form (see below)</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$rstr</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #400000; background-color: #cceeee;">array_key_exists</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #1060b6; background-color: #cceeee;">'user_login'</span><span style="color: #308080; background-color: #cceeee;">,</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$_POST</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #406080; background-color: #cceeee;">?</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #400000; background-color: #cceeee;">urldecode</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #007d45; background-color: #cceeee;">$rstr</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #406080; background-color: #cceeee;">:</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$rstr</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">try</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">{</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="background-color: #ffff00;"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45;">$claims</span><span style="color: #000000;"> </span><span style="color: #308080;">=</span><span style="color: #000000;"> AcsFed</span><span style="color: #308080;">::</span><span style="color: #007d45;">parseTokenAndExtractClaims</span><span style="color: #308080;">(</span><span style="color: #007d45;">$rstr</span><span style="color: #308080;">)</span><span style="color: #406080;">;</span><span style="color: #000000;"></span> </span><span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">}</span><span style="color: #000000; background-color: #cceeee;"> </span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">catch</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">Exception</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$e</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #000000; background-color: #cceeee;"> </span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">{</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">new</span><span style="color: #000000; background-color: #cceeee;"> Error</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #1060b6; background-color: #cceeee;">'login_error'</span><span style="color: #308080; background-color: #cceeee;">,</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$e</span><span style="color: #308080; background-color: #cceeee;">-</span><span style="color: #308080; background-color: #cceeee;">&gt;</span><span style="color: #000000; background-color: #cceeee;">getMessage</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">return</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">}</span><span style="color: #000000; background-color: #cceeee;"> </span>
<span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #595979; background-color: #cceeee;">//check for required UUID and IDP claims</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$user_uuid</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$claims</span><span style="color: #308080; background-color: #cceeee;">[</span><span style="color: #000000; background-color: #cceeee;">AcsClaimType</span><span style="color: #406080; background-color: #cceeee;">:</span><span style="color: #406080; background-color: #cceeee;">:</span><span style="color: #007d45; background-color: #cceeee;">$UUID</span><span style="color: #308080; background-color: #cceeee;">]</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$user_idp</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$claims</span><span style="color: #308080; background-color: #cceeee;">[</span><span style="color: #000000; background-color: #cceeee;">AcsClaimType</span><span style="color: #406080; background-color: #cceeee;">:</span><span style="color: #406080; background-color: #cceeee;">:</span><span style="color: #007d45; background-color: #cceeee;">$IDP</span><span style="color: #308080; background-color: #cceeee;">]</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">if</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">empty</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #007d45; background-color: #cceeee;">$user_uuid</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">{</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">new</span><span style="color: #000000; background-color: #cceeee;"> Error</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #1060b6; background-color: #cceeee;">'login_error'</span><span style="color: #308080; background-color: #cceeee;">,</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #1060b6; background-color: #cceeee;">'No user ID was returned from the selected identity provider'</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">return</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">}</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">elseif</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">empty</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #007d45; background-color: #cceeee;">$user_idp</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">{</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">new</span><span style="color: #000000; background-color: #cceeee;"> Error</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #1060b6; background-color: #cceeee;">'login_error'</span><span style="color: #308080; background-color: #cceeee;">,</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #1060b6; background-color: #cceeee;">'No identity provider claim was returned'</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">return</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"> </span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">}</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$user_name</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$claims</span><span style="color: #308080; background-color: #cceeee;">[</span><span style="color: #000000; background-color: #cceeee;">AcsClaimType</span><span style="color: #406080; background-color: #cceeee;">:</span><span style="color: #406080; background-color: #cceeee;">:</span><span style="color: #007d45; background-color: #cceeee;">$NAME</span><span style="color: #308080; background-color: #cceeee;">]</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$user_email</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$claims</span><span style="color: #308080; background-color: #cceeee;">[</span><span style="color: #000000; background-color: #cceeee;">AcsClaimType</span><span style="color: #406080; background-color: #cceeee;">:</span><span style="color: #406080; background-color: #cceeee;">:</span><span style="color: #007d45; background-color: #cceeee;">$EMAIL</span><span style="color: #308080; background-color: #cceeee;">]</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> UserFactory</span><span style="color: #308080; background-color: #cceeee;">::</span><span style="color: #007d45; background-color: #cceeee;">Create</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #007d45; background-color: #cceeee;">$user_idp</span><span style="color: #308080; background-color: #cceeee;">,</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user_uuid</span><span style="color: #308080; background-color: #cceeee;">,</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user_name</span><span style="color: #308080; background-color: #cceeee;">,</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user_email</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"> </span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">return</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">}</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">else</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">{</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">new</span><span style="color: #000000; background-color: #cceeee;"> Error</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #1060b6; background-color: #cceeee;">'login_error'</span><span style="color: #308080; background-color: #cceeee;">,</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #1060b6; background-color: #cceeee;">'no ACS token'</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">return</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #406080; background-color: #cceeee;">}</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #406080; background-color: #cceeee;">}</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> authenticate</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #200080; font-weight: bold; background-color: #cceeee;">if</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #200080; font-weight: bold; background-color: #cceeee;">instanceof</span><span style="color: #000000; background-color: #cceeee;"> User</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #406080; background-color: #cceeee;">{</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #400000; background-color: #cceeee;">session_start</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$_SESSION</span><span style="color: #308080; background-color: #cceeee;">[</span><span style="color: #1060b6; background-color: #cceeee;">'userName'</span><span style="color: #308080; background-color: #cceeee;">]</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #308080; background-color: #cceeee;">-&gt;</span><span style="color: #007d45; background-color: #cceeee;">name</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$_SESSION</span><span style="color: #308080; background-color: #cceeee;">[</span><span style="color: #1060b6; background-color: #cceeee;">'userEmail'</span><span style="color: #308080; background-color: #cceeee;">]</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #308080; background-color: #cceeee;">-&gt;</span><span style="color: #007d45; background-color: #cceeee;">email</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$_SESSION</span><span style="color: #308080; background-color: #cceeee;">[</span><span style="color: #1060b6; background-color: #cceeee;">'userIdP'</span><span style="color: #308080; background-color: #cceeee;">]</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #308080; background-color: #cceeee;">-&gt;</span><span style="color: #007d45; background-color: #cceeee;">idp_fname</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007d45; background-color: #cceeee;">$_SESSION</span><span style="color: #308080; background-color: #cceeee;">[</span><span style="color: #1060b6; background-color: #cceeee;">'userUuid'</span><span style="color: #308080; background-color: #cceeee;">]</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #308080; background-color: #cceeee;">=</span><span style="color: #000000; background-color: #cceeee;"> </span><span style="color: #007d45; background-color: #cceeee;">$user</span><span style="color: #308080; background-color: #cceeee;">-&gt;</span><span style="color: #007d45; background-color: #cceeee;">uuid</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp; </span><span style="color: #400000; background-color: #cceeee;">header</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #1060b6; background-color: #cceeee;">"HTTP/1.1 301 Moved Permanently"</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #000000; background-color: #cceeee;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #400000; background-color: #cceeee;">header</span><span style="color: #308080; background-color: #cceeee;">(</span><span style="color: #1060b6; background-color: #cceeee;">"Location: index.php"</span><span style="color: #308080; background-color: #cceeee;">)</span><span style="color: #406080; background-color: #cceeee;">;</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #406080; background-color: #cceeee;">}</span><span style="color: #000000; background-color: #cceeee;"></span>
<span style="color: #0057a6; background-color: #cceeee;">?&gt;</span></pre>
<h3><span style="color: #0057a6; background-color: #cceeee;"><strong><em><span style="color: #000000; background-color: #ffffff;" color="#000000">Code Download</span></em></strong></span></h3>
<p><span style="color: #0057a6; background-color: #cceeee;"><span style="color: #000000; background-color: #ffffff;" color="#000000">Currently we are still figuring the appropriate channel and license to distribute the&nbsp;PHP ACS Federation Library&nbsp;code. Once settled, we will publish&nbsp;its&nbsp;download&nbsp;link as well as the AcsFedDemo RP site's source code. Keep tuned in!</span></span></p>]]></content:encoded>
    </item>
  </channel>
</rss>