Question

I'm trying to check user's Office Store license in SharePoint's provider hosted add-in using GetAppLicenseInformation method:

Microsoft.SharePoint.Client.Utilities.Utility.GetAppLicenseInformation(clientContext, productId)

The only difference is that I'm creating ClientContext using Azure AD AccessToken (example):

ClientContext clientContext = new ClientContext(spSiteUrl);
clientContext.ExecutingWebRequest += (sender, e) =>
{
    e.WebRequestExecutor.WebRequest.Headers["Authorization"] = "Bearer " + accessToken;
};

Regardless permissions set in Azure AD App I'm getting:

Microsoft.SharePoint.Client.ServerException: Access Denied: The app could not be authenticated or is not authorized to query licenses of this Product ID

Interesting fact: there's no problem with getting user's license using classic SharePoint ClientContext from TokenHelper.

Does anyone have idea how could I make it work?

Was it helpful?

Solution

From my understanding it's not possible. Let me explain why.

Access token holds also Id of the app, i.e. ClientId. In order to get licensing info, they are (MS) checking some internal database. I think they are using ClinetId (as well as user identity) in order to find the match.

Your CliendId registered as Azure Ad app and thus license validation process can't find it under licenses store for SharePoint apps and you got an error.

As you understand, the only option is to use access token obtained for this particular sharepoint add-in (not azure).

UPD actually reflector is not a bad idea. I found that all licenses are stored inside App Management database. May be that is the reason why you can't get license - there are no records about your add-in (since it Azure AD) in database.
Here is the code found in Microsoft.SharePoint.dll:

public SPAppLicense[] CheckLicense(Guid productId, string appId, string userKey, bool isExternalCall, out bool appAuthenticationFailed)
{
    SPAppLicense[] result;
    using (new SPMonitoredScope("AppManagementServiceApplicationProxy.CheckLicense"))
    {
        Guid rawPartitionId = this.GetRawPartitionId(SPServiceContext.Current);
        byte[] array = AppManagementServiceDatabase.GenerateCompositeKey(rawPartitionId, AppManagementDataSetType.AppLicensing, productId);
        SPAppLicense[] array2 = null;
        SqlParameter errorCodeParameter = null;
        appAuthenticationFailed = false;
        byte[] compositePartitionKey = array;
        bool? isExternalCall2 = new bool?(isExternalCall);
        using (SPSqlCommand sPSqlCommand = SPStoredProceduresAppMng.proc_AM_CheckLicense(userKey, compositePartitionKey, appId, isExternalCall2, out errorCodeParameter))
        {
            array2 = (SPAppLicense[])SPScaleOutDatabaseCommandExecutor.Execute(delegate(SqlSession sqlSession, SPSqlCommand command, out SPScaleOutDatabaseQueryErrorCode errorCode)
            {
                object result2;
                using (SPSqlDataReader sPSqlDataReader = sqlSession.ExecuteSPReader(command))
                {
                    errorCode = AppManagementServiceApplicationProxy.GetScaleOutDatabaseQueryErrorCode(errorCodeParameter);
                    if (errorCode != SPScaleOutDatabaseQueryErrorCode.None)
                    {
                        result2 = null;
                    }
                    else
                    {
                        result2 = AppManagementServiceApplicationProxy.GetAppLicenseCollectionFromSqlDataReader(sPSqlDataReader);
                    }
                }
                return result2;
            }, this, sPSqlCommand, array);
        }
        if ((int)errorCodeParameter.Value == -11)
        {
            appAuthenticationFailed = true;
        }
        else
        {
            AppManagementServiceApplicationProxy.HandleLicenseErrorCode(errorCodeParameter);
        }
        result = array2;
    }
    return result;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top