question

DJDG avatar image
0 Votes"
DJDG asked RakeshJagatap-4451 commented

Principal does not have access to API/Operation error returned trying to access Text Analytics when using access token generated through an authorization code

I have tried following the process similar to as noted in this article - https://docs.microsoft.com/en-us/graph/auth-v2-user

  1. First I create an app using Azure AD App registrations. With this app, I created a secret password (Under certificates and secrets)

  2. Then go to Azure AD, Authentication tab and add a new platform configuration of type web with redirect URL as https://localhost:5555/azuredemo. This is the return URL where you will receive the authorization code.

  3. Next, goto API permissions, Add a permission, select from "APIs my organization uses" and choose Microsoft Cognitive Services. Selected Delegated Permissions and add added user_impersonations
    4.Create a sample html page to generate an authorization code request using authorize url
    <!DOCTYPE html>
    <html>
    <title> Client Authorization page </title>
    <body>
    <form action="https://login.microsoftonline.com/{my-tenant-id}/oauth2/v2.0/authorize" action="post">
    Client ID: <input type="field" name="client_id" value="xxx"/> <br/>
    Client Secret: <input type="field" name="client_secret" value="yyy"/> <br/>
    Scope: <input type="field" name="scope" value="https://cognitiveservices.azure.us/user_impersonation"/>; <br/>
    Response Type: <input type="field" name="response_type" value="code"/> <br/>
    Redirect URL: <input type="field" name="redirect_url" value="https://localhost:5555/azuredemo"/> <br/>
    <input type="submit" value="Authorize client"/> <br/>
    </form>
    </body>
    </html>

  4. authorization code was returned.

  5. Take this authorization code to get access token
    https://login.microsoftonline.com/{my-tenant-id}/oauth2/v2.0/token


  6. Usin the returned access token generated in the previous get token response, i added it to the authorization header. However I get the Principal does not have access to API/Operation error error

Here is the sample POSTMAN request/response
POST https://my-cs-resource.cognitiveservices.azure.com/text/analytics/v3.0/languages: {
"Network": {
"addresses": {
"local": {
"address": "masked",
"family": "IPv4",
"port": 51447
},
"remote": {
"address": "masked",
"family": "IPv4",
"port": 443
}
},
"tls": {
"reused": false,
"authorized": true,
"authorizationError": null,
"cipher": {
"name": "masked",
"standardName": "masked",
"version": "TLSv1/SSLv3"
},
"protocol": "TLSv1.2",
"ephemeralKeyInfo": {},
"peerCertificate": {
"subject": {
"country": "US",
"stateOrProvince": "WA",
"locality": "Redmond",
"organization": "Microsoft Corporation",
"commonName": ".cognitive.microsoft.com",
"alternativeNames": "DNS:
.api.cognitive.microsoft.com, DNS:.cognitiveservices.azure.com, DNS:.dev.cognitive.microsoft.com, DNS:.cognitive.microsoft.com"
},
"issuer": {
"country": "US",
"organization": "Microsoft Corporation",
"commonName": "Microsoft Azure TLS Issuing CA 02"
},
"validFrom": "Jul 27 22:28:10 2021 GMT",
"validTo": "Jul 22 22:28:10 2022 GMT",
"fingerprint": "masked",
"serialNumber": "masked"
}
}
},
"Request Headers": {
"authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Imwzc1EtNTBjQ0g0eEJWWkxIVEd3blNSNzY4MCIsImtpZCI6Imwzc1EtNTBjQ0g0eEJWWkxIVEd3blNSNzY4MCJ9.eyJhdWQiOiJodHRwczovL2NvZ25pdGl2ZXNlcnZpY2VzLmF6dXJlLmNvbS8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9mYzhkNzZlNC0xMTIyLTRmZTgtYjUxOS00NzIyYjMxNGNmZmMvIiwiaWF0IjoxNjMwODE4NTkyLCJuYmYiOjE2MzA4MTg1OTIsImV4cCI6MTYzMDgyMjQ5MiwiYWNyIjoiMSIsImFpbyI6IkFXUUFtLzhUQUFBQXYxclF1eUtxWld0d3hDcGRZQWtHQXk4UVVMM1d4VGJuZTNqeVFDOUNXNDdxWVhRV1c3cVhPU3FNcis5NUJnZzh3T3cySTI0Y0FwSnd6cW9XSXFhaUYzVDhGWWpROE9tcEdsQ2tPL2dZYmJ4R3FGeG16SW5pVWMrMUdleWdxZGlrIiwiYWx0c2VjaWQiOiIxOmxpdmUuY29tOjAwMDExQkE3NEMzMTJBMTgiLCJhbXIiOlsicHdkIiwibWZhIl0sImFwcGlkIjoiYzczMzJiYmItNGU0Mi00MmY3LTg5NDMtMjc1NWI5M2Y5MTUyIiwiYXBwaWRhY3IiOiIxIiwiZW1haWwiOiJkdXNoeWFudGdAaG90bWFpbC5jb20iLCJmYW1pbHlfbmFtZSI6IkdvZHNlIiwiZ2l2ZW5fbmFtZSI6IkR1c2h5YW50IiwiZ3JvdXBzIjpbImFlNDNiNGQyLTVhYmMtNDdlOC04YTU4LTcwMzYxYWIxZmE2YyJdLCJpZHAiOiJsaXZlLmNvbSIsImlwYWRkciI6IjczLjIyMy4yNS43MiIsIm5hbWUiOiJEdXNoeWFudCBHb2RzZSIsIm9pZCI6IjcyY2JlN2E5LWMwYjMtNDA0Ny04MmI0LWNmMjg4Y2QxNGY4MCIsInB1aWQiOiIxMDAzMjAwMENERUMwNjJDIiwicmgiOiIwLkFWb0E1SGFOX0NJUjZFLTFHVWNpc3hUUF9Mc3JNOGRDVHZkQ2lVTW5WYmtfa1ZKYUFDQS4iLCJzY3AiOiJ1c2VyX2ltcGVyc29uYXRpb24iLCJzdWIiOiItYjl6eVpFbS1DS0QwNkVHd2RRTzVXWDBhY1lhZmFXUUh1M2xoWmFCcGlRIiwidGlkIjoiZmM4ZDc2ZTQtMTEyMi00ZmU4LWI1MTktNDcyMmIzMTRjZmZjIiwidW5pcXVlX25hbWUiOiJsaXZlLmNvbSNkdXNoeWFudGdAaG90bWFpbC5jb20iLCJ1dGkiOiJtMzg1cGlwVDRrMlFPTGFPUnBCb0FBIiwidmVyIjoiMS4wIiwid2lkcyI6WyI2MmU5MDM5NC02OWY1LTQyMzctOTE5MC0wMTIxNzcxNDVlMTAiLCJiNzlmYmY0ZC0zZWY5LTQ2ODktODE0My03NmIxOTRlODU1MDkiXX0.ohYY5JYcBlgGuqm0REadMwjAVekDLcTlxvHjkmcCTF9a8qwcEhSbFt8Auj-L_V9up9LZlxXuXOg-GOS9_0duzYKKBzMAOZJFmcQcR-naCkrUqDT5H1_9-P3cb5pRz9B600-3_mzqIZxBqv_TLFiknBSJcBIgqpBy3dKuxdoTRKX9nI1LbeWQflWRRVdyRk24L12daPwU0ZY7_SYGPYsyfAn5AxXU18cVxc7MZUNHu27E1FRI0Pm0bgqF7ZZmAv3mDuNHPvNf-80q8XtAGHxeVurpbTD0roAIWTkEgp2QNPWvMJG8Chr7Yvmq6XanpRLpRF0C1gXU2v-NvdUOEAA9rw",
"content-type": "application/json",
"user-agent": "PostmanRuntime/7.28.4",
"accept": "
/*",
"postman-token": "a94ce59f-4de5-4b0c-8044-849c31a8aa0e",
"host": "my-cs-resource.cognitiveservices.azure.com",
"accept-encoding": "gzip, deflate, br",
"connection": "keep-alive",
"content-length": "92"
},
"Request Body": "{\"documents\": [{\"countryHint\": \"US\",\"id\": \"1\",\"text\": \"Hello world. How are you today!\"}]}\r\n",
"Response Headers": {
"content-length": "99",
"content-type": "application/json",
"apim-request-id": "xxxxxx",
"strict-transport-security": "max-age=31536000; includeSubDomains; preload",
"x-content-type-options": "nosniff",
"date": "Sun, 05 Sep 2021 05:16:40 GMT"
},
"Response Body": "{\"error\":{\"code\":\"PermissionDenied\",\"message\": \"Principal does not have access to API/Operation.\"}}"
}

Appreciate your assistance to help me know as to why I get Permission denied on this language detection on text analytics response. This works correctly if I were to use the API key instead of access token returned via the delegated authorized code process.
Please help.
thank you.

azure-cognitive-servicesazure-ad-authenticationazure-text-analytics
· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@DJDG The steps to get an authentication token for a cognitive service shared or dedicated resource are mentioned here.
Could you please try the same and check if the token generated using this steps works with your application?


0 Votes 0 ·
DJDG avatar image DJDG romungi-MSFT ·

I am following the steps you provided in the article. I am getting error in the Get a token powershell script. Could you please let me know how can I resolve the error in the powershell script. I believe I am missing some powershell packages but do not have a good handle on how to resolve this.

$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList "https://login.windows.net/my-tenant-id-masked"
New-Object : Cannot find type [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]: verify that the
assembly containing this type is loaded.
At line:1 char:16
+ ... thContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirecto ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand

PS C:\WINDOWS\system32>

I would appreciate your help. thank you.

0 Votes 0 ·

You can add this package and check if it works.

 dotnet add package Microsoft.IdentityModel.Clients.ActiveDirectory --version 5.2.9


0 Votes 0 ·

Hi, if any of the posted answer resolves your question, please mark it as the answer by clicking the check mark. Doing so helps others find answers to their questions.

0 Votes 0 ·
DJDG avatar image
0 Votes"
DJDG answered

I struggled to figure out from where to run dotnet add package. It would be helpful if you can let me know what I will need to install besides dotnet CLI to successfully run the command.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

DJDG avatar image
0 Votes"
DJDG answered

Instead I followed the following steps to install the Azure AD module within my windows powershell

Error returned when you execute the following step
PS C:\WINDOWS\system32> $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList "https://login.windows.net/my-masked-tenant-id"
New-Object : Cannot find type [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]: verify that the assembly containing this type is loaded.
At line:1 char:16
+ ... thContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirecto ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand

This is because Azure AD module is not present in WindowsPowershell module and needed to be installed.

PS>Install-Module -Name AzureAD -AllowClobber
Untrusted repository
You are installing the modules from an untrusted repository. If you trust this repository, change its InstallationPolicy value by running the Set-PSRepository cmdlet. Are you sure you want to install the modules from 'PSGallery'?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A
PS C:\users\dushy\downloads> Import-Module -Name AzureAD

PS C:\users\dushy\downloads> Add-Type -Path "C:\Program Files\WindowsPowerShell\Modules\AzureAD\2.0.2.140\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
PS C:\users\dushy\downloads> $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList "https://login.windows.net/fc8d76e4-1122-4fe8-b519-4722b314cffc"
PS C:\users\dushy\downloads> $SecureStringPassword = ConvertTo-SecureString -String mypasswordString -AsPlainText -Force
PS C:\users\dushy\downloads> $secureSecretObject = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.SecureClientSecret" -ArgumentList $SecureStringPassword

PS C:\users\dushy\downloads> $app = New-AzADApplication -DisplayName my-cs-app -Password $SecureStringPassword
PS C:\users\dushy\downloads> $clientCredential = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential" -ArgumentList $app.ApplicationId, $secureSecretObject
PS C:\users\dushy\downloads> $token=$authContext.AcquireTokenAsync("https://cognitiveservices.azure.com/", $clientCredential).Result
PS C:\users\dushy\downloads> $token


AccessTokenType : Bearer
AccessToken : accesstoken returned value
ExpiresOn : 9/8/2021 2:03:56 AM +00:00
ExtendedLifeTimeToken : False
TenantId :
UserInfo :
IdToken :
Authority : https://login.windows.net/my-masked-tenant-id/

POST https://my-masked-custom-subdomain.cognitiveservices.azure.com/text/analytics/v3.0/languages
Raw body
{
"documents": [
{
"id": "1",
"text": "Bonjour tout le monde"
},
{
"id": "2",
"text": "Hello world. How are you today"
},
{
"id": "3",
"text": "La carretera estaba atascada. Había mucho tráfico el día de ayer."
}
]
}

Use bearer token
Content-type = application/json

Response
{
"documents": [
{
"id": "1",
"detectedLanguage": {
"name": "French",
"iso6391Name": "fr",
"confidenceScore": 0.88
},
"warnings": []
},
{
"id": "2",
"detectedLanguage": {
"name": "English",
"iso6391Name": "en",
"confidenceScore": 1.0
},
"warnings": []
},
{
"id": "3",
"detectedLanguage": {
"name": "Spanish",
"iso6391Name": "es",
"confidenceScore": 1.0
},
"warnings": []
}
],
"errors": [],
"modelVersion": "2021-01-05"
}


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

DJDG avatar image
1 Vote"
DJDG answered

Although I am able to solve this using the powershell script, I would appreciate if you can tell me the alternate method of determining, how I could generate the authorized token using web request since I can pass along the client_id, client_secret, response_type as code, but what I am not sure about is the scope.
Here is my sample HTML code to generate an authorize code request

<!DOCTYPE html>
<html>
<title> Client Authorization page </title>
<body>
<form action="https://login.microsoftonline.com/my-masked-tenant-id/oauth2/v2.0/authorize" action="post">
Client ID: <input type="field" name="client_id" value="my-masked-registered-app-client-id"/> <br/>
Client Secret: <input type="field" name="client_secret" value="my-masked-registered-app-client-secret-password"/> <br/>
Scope: <input type="field" name="scope" value="https://cognitiveservices.microsoft.com/user_impersonation"/>; <br/>
Response Type: <input type="field" name="response_type" value="code"/> <br/>
Redirect URL: <input type="field" name="redirect_url" value="https://localhost:5555/azuredemo"/> <br/>
<input type="submit" value="Authorize client"/> <br/>
</form>
</body>
</html>

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

romungi-MSFT avatar image
0 Votes"
romungi-MSFT answered

@DJDG The alternate or recommended approach as per cognitive service documentation is to use managed identities to use the token. I have tried this scenario with a linux VM by enabling system assigned managed identity on the cognitive resource and the VM from the identity tab on Azure portal for these resources.

After enabling MI on the resources I granted the linux VM the role or scope of "Cognitive Services User" from the IAM tab of the cognitive resource.

130125-image.png

This should enable using the VM to get the access token to the face API resource securely. With the help of this article published by a user on medium I used the sample from this repo to test the AD authentication.

From the sample only update the config to point to the service endpoint URL and the resource endpoint.

 FaceTokenCognitiveServicesEndpoint = https://cognitiveservices.azure.com
 CognitiveFaceApiUrl = https://<resource_name>.cognitiveservices.azure.com


Getting the token using MI:

 def get_face_client_with_mi(config):
   # Create an authenticated FaceClient.
   endpoint = config['Authentication']['CognitiveFaceApiUrl']
   scope = config['Authentication']['FaceTokenCognitiveServicesEndpoint']
   creds = DefaultAzureCredential()
   access_token = creds.get_token(scope)
   #Convert to Dictionary
   dict_token = { "access_token": access_token.token}
   face_client = FaceClient(endpoint, BasicTokenAuthentication(dict_token))
   return face_client

Once the client is returned it is used to make a call to the Face API to get the detected face.
The documentation from Azure identity service provides more options to use as managed identities but I hope this helps.

Credit: Tomer Shaiman





image.png (59.0 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.