Create Bearer Token with Permissions for Azure Data Sync Api Trigger - azure

I have a configured and functioning Azure Data Sync, that I would like to trigger on demand by an API call.
I used the learn.microsoft.com tryit functionality at
https://learn.microsoft.com/en-us/rest/api/sql/2021-11-01/sync-groups/trigger-sync?tabs=HTTP#code-try-0
to build my API call.
That functionality returns a Bearer Token for access and API calls function until the token expires.
I set up a second API to get a new bearer token, by defining an application in my account with a shared secret. That API returns a bearer token, but when I use it in the API to trigger the Data Sync, I receive permission error messages.
In the token request I initally tried my application id in scope to get a token, that resulted in
The access token has been obtained for wrong audience or resource '622....330'. It should exactly match with one of the allowed audiences 'https://management.core.windows.net/','https://management.core.windows.net','https://management.azure.com/','https://management.azure.com
I then changed the scope to be https://management.azure.com
ClientID does not have authorization to perform action 'Microsoft.Sql/servers/databases/syncGroups/triggerSync/action'
over scope '/subscriptions/...fd2e,,,/resourceGroups/Default-SQL-WestUS/providers/Microsoft.Sql/servers/iv...f/databases/dbname/syncGroups/syncname'
I have tried adding permissions for
Access Azure Service Management
Azure SQL Database
Microsoft Graph
with no change in results.
I don't know if this is an issue of selecting the correct scope when requesting the Bearer token or assigning additional / correct permissions to the Application with the shared secret. Or am I approaching getting the Bearer token the wrong way.
Thanks,
Jim

I tried to reproduce the same in my environment and got below results:
I created one Azure AD application and granted API permission like below:
I generated an access token via postman with below parameters
POST
https://login.microsoftonline.com/cdf429fe-37a2-4a79-8e40-XXXXXX/oauth2/v2.0/token
client_id:abbc8b66-7bb9-4901-b04c-xxxxx
scope:https://management.azure.com/.default
client_secret: OzE8QXXXXX
grant_type:client_credentials
Response:
When I try to run the query, I got same error as you like below:
POST https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Sql/servers/{serverName}/databases/{databaseName}/syncGroups/{syncGroupName}/triggerSync?api-version=2021-11-01
To resolve this issue, you need to assign SQL DB contributor role to your application like below.
Go to Azure Portal -> Your subscription -> Access control (IAM) -> Add role assignment
You can assign SQL DB Contributor role role to your application by selecting it as below:
After assigning the role, I generated the token again and got response successfully when I ran the same query.
You can try the same in your environment by assigning SQL DB Contributor role to your application.

Related

how to pass correct scope to app registration to query the azure management service

I am new to azure and
I am trying a simple thing but not able to figure out how to set the correct scopes for a service principal.
I want to start and stop a ML compute using rest API. In order to do so, I would need the right token.
below are the steps I have taken :
create a service principal
created a Oauth query to get the access token
but I get error that
{
"error": {
"code": "InvalidAuthenticationTokenAudience",
"message": "The access token has been obtained for wrong audience or resource 'api://{<!-- -->{id}}'. It should exactly match with one of the allowed audiences 'https://management.core.windows.net/','https://management.core.windows.net','https://management.azure.com/','https://management.azure.com'."
}
}
Now, I am not able to figure out this concept. I have 2 doubts :
how to set this scope at the service principal end (in the portal), I dont see any such option and also I am not able to find the documentation.
how this access works? even if I give some resource level owner access to a service principal, then do I still have to provide access at scope option of app registration?
Please help in coming out of this issue.
Note that: To start/stop a ML compute instance https://management.azure.com/ scope is required not
api://ClientId.
I tried to reproduce the same in my environment and got the results like below:
I created an Azure AD Application and added API permission:
Make sure to grant Admin consent to the Api Permission. As user_impersonation is a delegated permission, you should make use of Authorization Grant Flow or Implicit Flow to generate the token.
I generated the Authorization code by using below parameters:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/authorize?
&client_id=ClientID
&response_type=code
&redirect_uri=RedirectUri
&response_mode=query
&scope=https://management.azure.com/user_impersonation
&state=12345
I generated the access token by using below parameters:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:ClientID
client_secret:ClientSecret
scope:https://management.azure.com/user_impersonation
grant_type:authorization_code
redirect_uri:RedirectUri
code:code
Otherwise, you can also make use of Implicit Grant Flow by running the query like below:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/authorize?client_id=ClientID&response_type=token&redirect_uri=RedirectUri&scope=https://management.azure.com/user_impersonation&response_mode=fragment&state=12345&nonce=678910
Access token will be generated redirecting to your redirect Uri like below:
Any of the above ways will generate the access token with the aud https://management.azure.com which will allow to start/stop the ML compute instance.
References:
Compute - Start - REST API Azure Machine Learning
Compute - Stop - REST API Azure Machine Learning
I figured it out. I selected the option under API permission of a service principal -> https://management.azure.com/user_impersonation
After selecting this, I was able to get the token which was needed to work with management.azure.com but I was not able to figure it out how to find this for a service principal.
I must say that I find azure very confusing. I am not able to find the documents and even if I find it, they seem difficult to me.
Probably, after some months of struggle I will find it easy.

how to create access_token to access ARM API for a user and not the service principal

I need to secure my ML endpoints in azure based on user credentials and user accesses.
Right now, we are authorising based on service principal account but now we want to test for each user.
I can see the documentation for REST API to get the access_token to make Rest API requests to ARM (azure resource manager) for a service principal account but not for any azure user.
So any pointers on whether this can be achieved or not?
so, basically what I am trying to do is this :
when a user tries to access the endpoint, its his credentials which needs to be validated whether he can access the API or not,
so what I see it that any number of users can be added to a workspace but not all user might have access to the scoring endpoint request.
in that case, only allowed user should be able to make the request and other users should be denied.
To generate access token based on user credentials, you can make use of ROPC flow.
While calling API with that token, validation will be done depending on Azure user's roles or permissions.
I tried to reproduce the same in my environment and got below results:
I created one Azure AD application and granted consent to API permissions like below:
I got the access token successfully via Postman using user credentials with parameters like below:
POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
client_id:44xxxx450-xxxx-4be1-axxb-e7xxxxxxxx
grant_type:password
scope:https://management.azure.com/.default
username:sricontri#tenant.onmicrosoft.com
password:xxxxxxxxx
Response:
Using the above access token, user can make Rest API requests to Azure Resource Manager successfully like below:
//To fetch list of resource groups present in the subscription
GET https://management.azure.com/subscriptions/<subscriptionID>/resourceGroups?api-version=2021-04-01
Response:
Please note that, the above user has Contributor role on the subscription that allowed user to make the request.
Now, I generated token for different Azure user via Postman in the same way as below:
POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
client_id:44xxxx450-xxxx-4be1-axxb-e7xxxxxxxx
grant_type:password
scope:https://management.azure.com/.default
username:sridemo#tenant.onmicrosoft.com
password:xxxxxxxxx
Response:
When the user included above token to make the same request, access is denied with 403 Forbidden error like below:
GET https://management.azure.com/subscriptions/<subscriptionID>/resourceGroups?api-version=2021-04-01
Response:
Please note that, the above user doesn't have required roles or permissions to access Azure resources that denied the request.

How to get Azure subscription state via Azure API in C# or Postman

Have tried many ways via code and Postman and no luck of getting a state of subscription like you would get via this link: https://learn.microsoft.com/en-us/rest/api/resources/subscriptions/list - here via the site you get a list of subscriptions and their "state": "Enabled" as an example.
Have no problem of getting auth tokens using scopes below but then impossible to get subscriptions list. If I use token from Microsoft site, the call in Postman to get subscriptions works fine.
The site is using Azure Active Directory OAuth2:
Type: oauth2
Flow: implicit
Authorization URL: https://login.microsoftonline.com/common/oauth2/authorize
Using Postman I have tried getting subscriptions using these scopes along with auth token:
api://blah/.default - Invalid Authentication Token Audience
https://graph.microsoft.com/.default - Authentication failed
https://management.azure.com/.default - pass but 0 results
https://management.core.windows.net/.default - pass but 0 results
I guess when using the site you login as a user and password vs in the code using client app and app secret. Is this workflow even possible?
The registered app has all kinds of API permissions. Something this simple should not be so hard. The idea here is to programmatically check via console app if Subscription is "Enabled".
After debugging this via Postman it turns out to be a permissions issue where you have to add the application you created/using to authenticate to the Access Control (IAM) of the subscription. This post describes the error and resolution: The client with object id does not have authorization to perform action 'Microsoft.DataFactory/datafactories/datapipelines/read' over scope
If you have multiple capacities created then you have to add your application to all of those subscriptions. Then you will get a list and can then check each one.

Incomplete bearer token when using authentication-managed-identity tag in azure api management

I've been trying to expose an API through azure API Management and I can't figure out what I'm doing wrong. Here's the situation:
My API is going to be called from an external application
They don't have an Azure Account in the same tenant
I want to enable external calls for my API by just using a subscription key (hence, why I'm using API Management), but also want to keep my actual API secured with Azure AD.
I have an API which is secured with Azure AD using OAuth2 and published into a Windows AppService
I have an App registration for that API, which i use to authenticate (it works from postman, for example)
app registration
I have Managed Identities turned on and permissions set.
I have added the API in API management
I added the authentication-managed-identity inbound rule, used the API Id Uri of the app registration as the resource value for it.
Api Management Config
When testing an endpoint from the APIM interface, I can successfully get a bearer token, but I get a 500 exception from the API which says: Neither scope or roles claim was found in the bearer token
bearer response
Here is the decoded bearer token, it doesn't have a scp attribute
bearer decoded
I'm not sure where I can specify a scope. If I use the full scope uri (api://guid/access.api.management) it will fail when trying to get a bearer token (The resource principal named api://guid/access.api.management was not found in the tenant).
I've even tried adding the Owner role to the APIM Identity for the AppService.
Maybe I'm not using this correctly, I'm pretty new at using Azure cloud and API Management so any suggestions are welcome.
Thanks.
You have expose an api protected by Azure, and currently you have an api application. Next, you need to create another application that represents the client, and then add the client application to the api application.
Next, go to the client application.
Under 'API permissions' click on 'Add permission', then click on the 'My APIs' tab.
Find your api application and select the appropriate scope.
Click 'Add permissions'.
Grant admin consent for your APIs.
Next, you need to use the auth code flow to obtain an access token,which requires you to log in to the user and obtain the authorization code, and then use the authorization code to redeem the access token.
1.Request an authorization code in the browser.
https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/authorize?
client_id={client app client id}
&response_type=code
&redirect_uri={redirect_uri}
&response_mode=query
&scope=api://{api app client id}/{scope name}
&state=12345
2.Redeem token.
Parse the token:
I managed to get it working using the client credentials flow and storing the client secret in key vault.

Azure AAD App can access Admin App without granting permission using a token

I have two Azure Ad Apps:
1) Admin/BackendApp which guards my webapi
2) Consumer APP which will consume my webapi
When i try to access my web api using the token created using below URL passing the required ClientID, ClientSecret, Resource and grant_type=client_credentials
https://login.microsoftonline.com/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/oauth2/token
i get access token from above url and pass that token as Authorization header to my webapi i get successfull response without granting any access to/from admin/backendapp.
You need to check for valid scopes/roles in the token!
Define delegated/app permissions for the API in Azure AD and enforce them in your API. A global check that the token contains at least one valid permission is good to have.
An app in any tenant can acquire a token for your API as long as they know your tenant id and client id.
If you do not check for permissions, your API is vulnerable!
I have an article for how to define and enforce scopes in ASP.NET Core: https://joonasw.net/view/azure-ad-authentication-aspnet-core-api-part-1
Based on your query, the JWT token is created to call the API already have enough permission to call the resources. This looks like a normal scenario

Resources