I am receiving StatusCode: 403, ReasonPhrase: 'Forbidden' for an HTTP Post:
URL: $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{appName}/functions/{functionName}/listkeys?api-version=2022-03-01";
StatusCode: 403, ReasonPhrase: 'Forbidden'
Client:
The following is my client code:
let tenantId = "<some_tenant_id>"
let clientId = "<some_client_id>"
let secret = "<some_secret>"
let scope = "<some_scope>"
let token = BearerToken.Create(tenantId, clientId, secret, scope).Result
let tokenRequestBody = Dictionary<string, string>()
tokenRequestBody.Add("grant_type" , "client_credentials")
tokenRequestBody.Add("client_id" , clientId)
tokenRequestBody.Add("client_secret", secret)
tokenRequestBody.Add("scope" , scope)
let content = new FormUrlEncodedContent(tokenRequestBody);
let httpKeysClient = new HttpClient();
httpKeysClient.DefaultRequestHeaders.Authorization <- new AuthenticationHeaderValue("Bearer", token);
httpKeysClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
let subscriptionId = "<some_scubscription_id>"
let resourceGroupName = "<some_resource_group_name>"
let appName = "<some_function_app_name>"
let functionName = "<some_function_name>"
let apiKeyUrl = $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{appName}/functions/{functionName}/listkeys?api-version=2022-03-01";
let response = httpKeysClient.PostAsync(apiKeyUrl, content).Result;
response.IsSuccessStatusCode |> should equal true // ** StatusCode: 403, ReasonPhrase: 'Forbidden' **
Appendix:
The code for creating an authorization token works:
public static class BearerToken
{
public async static Task<string> Create(string tenantId, string clientId, string clientSecret, string scope)
{
var tokenRequestBody = new Dictionary<string, string> {
{ "grant_type" , "client_credentials" },
{ "client_id" , clientId },
{ "client_secret", clientSecret },
{ "scope" , scope }
};
var url = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
var client = new HttpClient() { BaseAddress = new Uri(url) };
var content = new FormUrlEncodedContent(tokenRequestBody);
var response = await client.PostAsync("", content);
if (response.IsSuccessStatusCode)
{
var tokenResponse = await response.Content.ReadAsStringAsync();
var valueFor = JsonConvert.DeserializeObject<JsonSupport.AccessToken.Root>(tokenResponse);
return valueFor.access_token;
}
throw new Exception(response.ReasonPhrase);
}
}
CodePudding user response:
I tried to reproduce the same in my environment via Postman and got below results
I have one service principal having Reader
role under my subscription like below:
Now I generated access token using client credentials flow with below parameters:
POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
grant_type:client_credentials
client_id: <appID>
client_secret: <secret_value>
scope: https://management.azure.com/.default
Response:
When I used the above token to list keys, I got 403 Forbidden
error like below:
POST https://management.azure.com/subscriptions/<subID>/resourceGroups/Sri/providers/Microsoft.Web/sites/<name>/functions/<functionname>/listkeys?api-version=2022-03-01
Authorization: Bearer <token>
Response:
To resolve the error, I assigned Contributor
role to that service principal like below:
Go to Azure Portal -> Subscriptions -> Your Subscription -> Access control (IAM) -> Add role assignment
After assigning that role, I generated access token again and got the results successfully when I used that in below query:
POST https://management.azure.com/subscriptions/<subID>/resourceGroups/Sri/providers/Microsoft.Web/sites/<name>/functions/<functionname>/listkeys?api-version=2022-03-01
Authorization: Bearer <token>
Response:
In your case, make sure to assign Contributor
role to your service principal that resolves the issue.