Share via


AD FS 2.x: When a User is Not Authorized Access to a Relying Party, Redirect the User to a Specific Location

Overview

Consider the following scenario:

  • You have deployed AD FS 2.x, and you wish to provide granular access to specific relying parties by utilizing Issuance Authorization Rules on each Relying Party Trust
  • As an example, you have Contoso SharePoint as a relying party, and you wish to only allow users in the Active Directory group Sales Staff to access the Contoso SharePoint relying party
  • All other users should be denied access to Contoso SharePoint, and these users should be redirected to a Forefront Identity Manager web service in order to request access to the Sales Staff group

 

Applies To

 

  • SAML 2.0 WebSSO IdP-initiated sign-on (/adfs/ls/idpinitiatedsignon.aspx)

  • WS-Federation passive SP-initiated sign-on

    Note: This sample does not apply to SAML 2.0 WebSSO SP-initiated sign-on

Implementation Details

 

Viewing the Relying Party Trust Identifier(s)

  • Right-click the Contoso SharePoint relying party trust in AD FS 2.x Management, and select Properties
  • Select the Identifiers tab and note all URI values in the list box

Create an Issuance Authorization Rule to Restrict Access to Contoso SharePoint

  1. Right-click the Contoso SharePoint relying party trust in AD FS 2.x Management, and select Edit Claim Rules
  2. Select the Issuance Authorization Rules tab
  3. Remove all Issuance Authorization Rules from that list that no longer apply
  4. Add a new Issuance Authorization Rule by clicking the Add Rule button
  5. Claim rule template: Permit or Deny Users Based on an Incoming Claim, and click Next
  6. Claim rule name: Permit Only Sales Staff Members
  7. Incoming claim type: Group SID
  8. Incoming claim value: Click the Browse button and resolve the Active Directory group Sales Staff
  9. Select Permit access to users with this incoming claim
  10. Click Finish and click OK

Edit error.aspx.cs

Note: Do not copy/paste any code samples from this page directly. You should either type the code sample manually, or first paste the code sample into a text editor where there is no special character formatting.

a. In Windows Explorer, explore to: C:\inetpub\adfs\ls
b. Make a backup copy of the original error.aspx.cs file
c. Open error.aspx.cs for editing in a text editor (i.e. - Notepad)
d. Find the following lines of code:

protected void Page_Load( object sender, EventArgs e )
{
    AuthorizationFailedException authorizationException = Exception as AuthorizationFailedException;
    AuthenticationFailedException authenticationException = Exception as AuthenticationFailedException;
    if( authorizationException != null )
    {

e. Move your cursor to the next line down, and replace the following code:

//
// To provide customized authorization error messages, inspect the RequestedRelyingParty
// property of the authorizationException.  It will contain the identifier of
// the Relying Party Trust for whom the user is not authorized.
//
ExceptionMessageLabel.Visible = true;
ExceptionMessageLabel.Text = Resources.CommonResources.UnauthorizedText;
Title = Resources.CommonResources.AccessDeniedTitle;

With the following code:

//
// To provide customized authorization error messages, inspect the RequestedRelyingParty
// property of the authorizationException.  It will contain the identifier of
// the Relying Party Trust for whom the user is not authorized.
//
 
if (0 == Uri.Compare(authorizationException.RequestedRelyingParty, new Uri("https://sharepoint.contoso.com/"), UriComponents.Host | UriComponents.Path, UriFormat.UriEscaped, StringComparison.OrdinalIgnoreCase))
{
    Response.Redirect("https://FIM.adatum.com/requestAccess.aspx", true);
}
else
{
    ExceptionMessageLabel.Visible = true;
    ExceptionMessageLabel.Text = Resources.CommonResources.UnauthorizedText;
    Title = Resources.CommonResources.AccessDeniedTitle;
}

You should now have the following code:

//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
 
using System;
 
using Microsoft.IdentityServer.Web;
using Microsoft.IdentityServer.Web.UI;
 
/// <summary>
/// Shows the error page
/// </summary>
public partial class Error : ErrorPage
{
    protected void Page_Load( object sender, EventArgs e )
    {
        AuthorizationFailedException authorizationException = Exception as AuthorizationFailedException;
        AuthenticationFailedException authenticationException = Exception as AuthenticationFailedException;
        if( authorizationException != null )
        {
            //
            // To provide customized authorization error messages, inspect the RequestedRelyingParty
            // property of the authorizationException.  It will contain the identifier of
            // the Relying Party Trust for whom the user is not authorized.
            //
 
            if (0 == Uri.Compare(authorizationException.RequestedRelyingParty, new Uri("https://sharepoint.contoso.com/"), UriComponents.Host | UriComponents.Path, UriFormat.UriEscaped, StringComparison.OrdinalIgnoreCase))
            {
                Response.Redirect("https://FIM.adatum.com/requestAccess.aspx", true);
            }
            else
            {
                ExceptionMessageLabel.Visible = true;
                ExceptionMessageLabel.Text = Resources.CommonResources.UnauthorizedText;
                Title = Resources.CommonResources.AccessDeniedTitle;
            }
        }
        else if( authenticationException != null )
        {
            ExceptionMessageLabel.Visible = true;
            ExceptionMessageLabel.Text = Resources.CommonResources.UnauthenticatedText;
        }
        else
        {
            ExceptionMessageLabel.Visible = System.Web.Configuration.WebConfigurationManager.AppSettings[ "displayExceptions"  ] != null;
            ExceptionMessageLabel.Text = Exception != null ? Exception.Message : String.Empty;
        }
    }
}

Test Access

a. Attempt sign-in as a user in the Sales Staff group
    Expected result: Access granted to Contoso SharePoint

b. Attempt sign-in as a user who is not a member of the Sales Staff group
    Expected result: Access denied to Contoso SharePoint, and the user should land on the redirect page (i.e. - FIM)

Notes:

a. If you find that everyone is allowed or everyone is denied, go back and take a look at your Issuance Authorization Rule for issues

b. If you find that, when access has been denied, the user lands on a blank white screen, this likely indicates that error.aspx.cs failed to compile, and you have an issue in your code

c. If your relying party has multiple identifiers or you would like to implement this solution for multiple relying parties, add additional condition statements to error.aspx.cs like this:

 *          *


if (0 == Uri.Compare(authorizationException.RequestedRelyingParty, new Uri("https://RP1.contoso.com/"), UriComponents.Host | UriComponents.Path, UriFormat.UriEscaped, StringComparison.OrdinalIgnoreCase))
          {
              Response.Redirect("https://FIM.adatum.com/requestAccess.aspx", true);
          }
           else if (0 == Uri.Compare(authorizationException.RequestedRelyingParty, new Uri("https://RP2.contoso.com/"), UriComponents.Host | UriComponents.Path, UriFormat.UriEscaped, StringComparison.OrdinalIgnoreCase))
          {
              Response.Redirect("http://www.bing.com", true);
          }
           else if (0 == Uri.Compare(authorizationException.RequestedRelyingParty, new Uri("https://RP3.contoso.com/"), UriComponents.Host | UriComponents.Path, UriFormat.UriEscaped, StringComparison.OrdinalIgnoreCase))
          {
              Response.Redirect(http://contoso.com/RP3DeniedCustom.aspx, true);
          }
          else
          {
              ExceptionMessageLabel.Visible = true;
              ExceptionMessageLabel.Text = Resources.CommonResources.UnauthorizedText;
              Title = Resources.CommonResources.AccessDeniedTitle;
          }