Blog Post

Microsoft SharePoint Blog
3 MIN READ

Fixing on the fly OAuth issue for Provider Hosted Add-in in GCC High or DOD Tenant

SPDev_Support's avatar
SPDev_Support
Icon for Microsoft rankMicrosoft
May 01, 2019

First published on TECHNET on Oct 31, 2018
This post is a contribution from Mustaq Patel, an engineer with the SharePoint Developer Support team

Requirement: You have low trust Provider Hosted add-in that does on the fly OAuth (request permissions at runtime). You try to use this Provider Hosted add-in on a GCC High or DoD tenant. You see that the add-in does not work and you see an error message which seems to indicate that the add-in is looking for Client Id/Client Secret in wrong tenant.

Issue: when the add-in does on the fly OAuth the TokenHelper class that the add-in uses to get the OAuth process going and retrieve Access Token by validating Client Id and Client Secret in the Azure Active Directory, goes to a wrong AAD (i.e. public AAD) and will come back without any record matching with that Client Id and so the add-in fails. It is due to below hard coded string in the TokenHelper.cs file which is not valid for on the fly OAuth on GCC High/DOD tenants.


To fix this modify this error line as below.

private static string AcsHostUrl = "login.microsoftonline.us";

// Also modify method GetAcsGlobalEndpointUrl as below.
private static string GetAcsGlobalEndpointUrl()
{
    return String.Format(CultureInfo.InvariantCulture, "https://{0}/", AcsHostUrl);
}


These 2 changes will fix the Provider Hosted add-in by causing the OAuth requests to go to correct authentication url for GCCH AAD.

If you are using same Provider Hosted add-in for both GCCH and public cloud or want to maintain same code base for both types of cloud, than we have to do some extra work. The code logic would be to find out the top domain of the sharepoint site and if it is .us than go to login.microsoftonline.us and if it is .com go to accesscontrol.windows.net.

Below is the complete code change.

1. Declare 2 static variables as below (highlighted). 

private static string GlobalEndPointPrefix = "accounts"; 
private static string AcsHostUrl = "accesscontrol.windows.net"; 
private static string GCCHAcsHostUrl = "login.microsoftonline.us"; 
private static string SPTargetUrl = ""; 

2. Modify GetAuthorizationUrl to set SPTargetUrl as below

public static string GetAuthorizationUrl(string contextUrl, string scope, string redirectUri)
{
    SPTargetUrl = contextUrl;
    return string.Format(
    "{0}{1}?IsDlg=1&client_id={2}&scope={3}&response_type=code&redirect_uri={4}",
    EnsureTrailingSlash(contextUrl),
    AuthorizationPage,
    ClientId,
    scope,
    redirectUri);
}

3. Add below method, to get the top domain of the sharepoint url.

private static string GetTopDomainType(Uri uri)
{
    if (!uri.HostNameType.Equals(UriHostNameType.Dns) || uri.IsLoopback)
        return string.Empty; // or throw an exception 
    return String.Format(CultureInfo.InvariantCulture, "{0}", uri.Host.Split('.').Last());
}

4. Modify GetAcsGlobalEndpointUrl as below, to find if SharePoint is in GCC High by checking top domain ( .us

private static string GetAcsGlobalEndpointUrl()
{
    string topDomain = GetTopDomainType(new Uri(SPTargetUrl));
    if (string.Equals(topDomain, "us", StringComparison.OrdinalIgnoreCase))
    {
        AcsHostUrl = GCCHAcsHostUrl;
        return String.Format(CultureInfo.InvariantCulture, "https://{0}/", AcsHostUrl);
    }
    else
    {
        return String.Format(CultureInfo.InvariantCulture, "https://{0}.{1}/", GlobalEndPointPrefix, AcsHostUrl);
    }
}

5. Deploy the Provider Hosted add-in with this code change and test the add-in.

 

Please note that from the Provider Hosted add-in, you have to call GetAuthorizationUrl method to construct the redirecturl for add-in consent.

For more details please refer below article
On the fly oauth - https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/authorization-code-oauth-flow-for-sharepoint-add-ins .
GCC high and DoD - https://docs.microsoft.com/en-us/office365/servicedescriptions/office-365-platform-service-description/office-365-us-government/gcc-high-and-dod .

Updated Sep 01, 2020
Version 5.0
  • XRS_AlJohnson's avatar
    XRS_AlJohnson
    Copper Contributor

    The solution for using the same Provider Hosted web app for both GCCH and public with the static string SPTargetUrl makes me very nervous.  With only a general understanding of ASP.Net and web hosting seems there is a potential that concurrent GCCH users can break the authentication for public and vice versa if the variable isn't set on every call.

    Any reassurance on the use of a static?  Thanks, Al.