3

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?

  • 1
    Have you tried to check all permissions possible inside Azure AD for SharePoint? Also try to decode access token (because it's just jwt) using for example calebb.net and compare? – Sergei Sergeev Feb 2 '17 at 17:27
  • @SergeiSergeev yes, that's the first thing I did, same result. I will try to decode access token as you suggested and come back with results, thanks! – Grzegorz Ciwoniuk Feb 2 '17 at 20:15
  • @SergeiSergeev so I've checked the token, everything seems correct, even updated ADAL to v3, still no success. That's pretty confusing since I have access to all other SharePoint's resources, except user's license. – Grzegorz Ciwoniuk Feb 3 '17 at 6:17
3

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;
}
  • Sounds reasonable, but the exception says about denied access, and not problems with finding assigned license. Secondly, error appears while getting license information from local SharePoint, not Office Store (validation in the Office 365 services is not called at this point yet). – Grzegorz Ciwoniuk Feb 3 '17 at 9:10
  • I would not pay attention at the message, sometimes the reason for the exception may be completely different. I believe SharePoint holds some license database behind the scene. Of course it's just my assumptions – Sergei Sergeev Feb 3 '17 at 9:33
  • Sure, it might. I believe the only way to check it is to decomplie Microsoft.SharePoint.Client.dll. Thanks Microsoft. – Grzegorz Ciwoniuk Feb 4 '17 at 11:00
  • 1
    Do you have app web? If not, try to create app web for you provider hosted app (by adding empty element into the project for app web) and try to check license again. – Sergei Sergeev Feb 4 '17 at 11:49
  • yep, tried that also, but I'm not sure if the App Web has been actually created. – Grzegorz Ciwoniuk Feb 6 '17 at 21:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.