In a recent project of our agency’s integration team, we built a custom membership provider for Cognito SSO to allow SharePoint 2019 to seamlessly authenticate using OAuth 2.0. In this blog, I’ll share the solution (code available here), outline the approach, and review lessons learned during development.

Generating Component Markup with React in Storybook for HTML

First, let’s explain why we needed to build a custom solution to integrate Amazon Web Services (AWS) Cognito and SharePoint. There are many content management system (CMS) alternatives with native support for OAuth, as well as more obvious options as single sign-on (SSO) providers for SharePoint.

Why use SharePoint on premise

The client already had a SharePoint license and wanted to use SharePoint 2019 as a customer portal that allowed for both public and secured pages. The requirement to host public pages removes SharePoint Online as an option, which would otherwise have been our recommendation.

Why we use Cognito

The primary requirement we had was to provide multi-factor authentication and replace the legacy membership provider (ADLDS). Additionally, predicting future requirements, we wanted to provide a platform that could support SSO, despite currently only needing to support a single application. The obvious choices for this, with SharePoint, would be ADFS or Azure AD B2C.

However, the major factor for settling on Cognito was simply cost. Enabling multi-factor authentication with Azure B2C was significantly more expensive than Cognito, with Azure AD charging per multi-factor authentication (MFA) event, while Cognito only charges its standard SMS rates when SMS MFA is used.

The challenge

Now that we settled on the architecture, the main challenge was that Cognito does not support security assertion markup language (SAML) and SharePoint doesn’t support the OAuth grant types we needed. SharePoint support three basic authentication types:

  • Windows authentication
    • NTLM – new technology local-area network (NT LAN) manager
    • Kerberos – a computer-network authentication protocol
    • Digest
    • Basic
  • Forms-bases authentication (FBA)
    • AD DS – active directory domain services
    • SQL
    • LDAP – lightweight directory access protocol
  • Token-based authentication
    • SAML

Cognito User Pools support OpenID Connect (OIDC)/OAuth.

SharePoint does not support OIDC/OAuth for user authentication. SharePoint on-premise OAuth support is limited to acting as the authorization server in a client credential grant.

Solution overview

Cutting-Edge Retail Technologies American Brands Should Consider

Custom forms-based authentication membership and role providers to support both user authentication, as well as user and group people pickers.

*code available here

Supports

  • Implicit grant

Components

  • Membership provider
    • Token verification
    • People-picker lookup
  • Role provider
    • User-role lookup
    • People-picker lookup
  • Login page
    • Script parses token for username and submits it along with the token as a password.
  • Logout page
    • Clears cookies and/or local storage and redirects to Cognito logout page.

Step-by-step instructions

Download Windows SharePoint package (WSP) from github.

Deployment

  • Install DEG.SP.Cognito.wsp as farm solution:

Add-SPSolution C:\path_to_solution_file\DEG.SP.Cognito.wsp

Install-SPSolution -GACDeployment -Identity DEG.SP.Cognito.wsp

Set sign-out page from SharePoint Management Shell with the following command:

Set-SPCustomLayoutsPage -Identity Signout -RelativePath “/_layouts/15/DEG.SP.Cognito/logout.aspx” -WebApplication <web_application_url>

Add membership and role provider elements to web.configs.

Element in system.web/membership/providers:

<add name=”CognitoMembershipProvider” applicationName=”DEG.SP.Cognito” type=”DEG.SP.Cognito.Providers.CognitoMembershipProvider, DEG.SP.Cognito, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ffacbed595091bcd” />

Element in system.web/roleManager/providers:

<add name=”CognitoRoleProvider” applicationName=”DEG.SP.Cognito” type=”DEG.SP.Cognito.Providers.CognitoRoleProvider, DEG.SP.Cognito, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ffacbed595091bcd” />

Internal information services (IIS) Apps to include:

  • All SharePoint web application requiring providers
  • Central admin web application
  • Security token service application

Set up your Cognito user pool.

Configure farm properties:

AWS_USER_POOL_ID – User Pool Id (us-east-1_aaaaAAAA)

AWS_ACCESS_KEY_SECRET – IAM Access Key Secret

AWS_ACCESS_KEY_ID – IAM Access Key Id

AWS_CLIENT_ID – User Pool App Id (aaaaaaaaaaaaaaaa0000000000)

AWS_HOSTED_UI – Hosted UI hostname (aaaaaaaa.auth.us-east-1.amazoncognito.com)

Sample farm property configuration for prod (access key and secret removed for security, but needs to be generated/added from identify and access management (IAM) service user. User UBGRetire-MembershipProvider created with proper access).

$farm = Get-SPFarm

$farm.Properties.Add(“AWS_USER_POOL_ID”, “us-east-1_aaaaAAAA”)

$farm.Properties.Add(“AWS_CLIENT_ID “, “aaaaaaaaaaaaaaaa0000000000”)

$farm.Properties.Add(“AWS_HOSTED_UI”, “aaaaaaaa.auth.us-east-1.amazoncognito.com”)

$farm.Properties.Add(“AWS_ACCESS_KEY_ID”, “”)

$farm.Properties.Add(“AWS_ACCESS_KEY_SECRET”, “”)

$farm.Update()

Sample for SharePoint Web Application

<membership defaultProvider=”i”>

<providers>

<add name=”i” type=”Microsoft.SharePoint.Administration.Claims.SPClaimsAuthMembershipProvider, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” />

<add name=”CognitoMembershipProvider” applicationName=”DEG.SP.Cognito” type=”DEG.SP.Cognito.Providers.CognitoMembershipProvider, DEG.SP.Cognito, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ffacbed595091bcd” />

</providers>

</membership>

<roleManager defaultProvider=”c” enabled=”true” cacheRolesInCookie=”false”>

<providers>

<add name=”c” type=”Microsoft.SharePoint.Administration.Claims.SPClaimsAuthRoleProvider, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” />

<add name=”CognitoRoleProvider” applicationName=”DEG.SP.Cognito” type=”DEG.SP.Cognito.Providers.CognitoRoleProvider, DEG.SP.Cognito, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ffacbed595091bcd” />

</providers>

</roleManager>

Sample for Central Admin Web Application (role provider not needed)

<roleManager>

<providers>

</providers>

</roleManager>

<membership>

<providers>

<add name=”CognitoMembershipProvider” applicationName=”DEG.SP.Cognito” type=”DEG.SP.Cognito.Providers.CognitoMembershipProvider, DEG.SP.Cognito, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ffacbed595091bcd” />

</providers>

</membership>

Sample for Security Token Service Application (entire system.web block may need to be added)

<system.web>

<membership>

<providers>

<add name=”CognitoMembershipProvider” applicationName=”DEG.SP.Cognito” type=”DEG.SP.Cognito.Providers.CognitoMembershipProvider, DEG.SP.Cognito, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ffacbed595091bcd” />

</providers>

</membership>

<roleManager>

<providers>

<add name=”CognitoRoleProvider” applicationName=”DEG.SP.Cognito” type=”DEG.SP.Cognito.Providers.CognitoRoleProvider, DEG.SP.Cognito, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ffacbed595091bcd” />

</providers>

</roleManager>

</system.web>

Configure Authentication Providers on Web Application

Check Enable anonymous access

Uncheck Enable Windows Authentication

Check Enable Forms Based Authentication (FBA)

Set membership provider to CognitoMembershipProvider

Set role provider to CognitoRoleProvider

Select Custom Sign In Page

Set value to /_layouts/15/DEG.SP.Cognito/login.aspx

Challenges and lessons learned

Four Most Exciting SharePoint Features at Microsoft Ignite

  • Cognito API paginates by using a pagination token that gives you the next page if one exists. SharePoint uses a page index for getting all users, potentially necessitating iterating over multiple API calls to Cognito for each call to the membership provider GetAllUsers method. This could, in theory, cause a performance bottleneck if a large number of people-picker queries were made simultaneously.
  • Roles are case sensitive.
  • Enable email as login is locked in.
  • Email is case sensitive.
  • Manual SMS budget increase and email sandbox mode, allow 24 hours.

Keep in touch.

Stay up-to-date on the latest digital trends, DEG news, and upcoming events by subscribing to DEG's newsletter.

Subscribe

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Comments