0

I am trying to create an Azure Database programmatically using C# via the HTTP API.

I found this resource (in which he uses App Secret, rather than certificate), but can't get it to work due to a 403: Forbidden error.

If I use the token created in the 'try it' section of the azure docs, the code works fine, so it must be that the token generated doesn't have the permissions I need.

The secret I am trying to use was generated in Portal > Active Directory > App Registrations > {myapp} > Certificates and Secrets.

In API permissions I've added just about everything - though please suggest any I might have missed!

I opened the firewall to my IP and have spent hours looking for the answer, but can't seem to figure it out.

What am I missing please?

Although I believe it's permissions somewhere in Azure, here's my code:

/// <summary>
/// Create a new database
/// </summary>
/// <param name="subscriptionId">See Portal > Subscriptions (pick the right subscription!)</param>
/// <param name="resourceGroupName">The resource group the server was created in</param>
/// <param name="locationName">e.g. UK (South)</param>
/// <param name="sqlServeName">The name of the SQL Server VM created when the first database was created</param>
/// <param name="tenantId">See GetAccessToken</param>
/// <param name="clientId">See GetAccessToken</param>
/// <param name="clientSecret">See GetAccessToken</param>
/// <param name="databaseName">The name of the database to be created</param>
/// <returns></returns>
private async Task CreateDatabaseAsync(string subscriptionId, string resourceGroupName, string locationName, string sqlServeName, string tenantId, string clientId, string clientSecret, string databaseName)
{
    var token = await GetAccessTokenAsync(tenantId, clientId, clientSecret);

    var url = "https://management.azure.com/subscriptions/" + subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Sql/servers/" + sqlServeName + "/databases/" + databaseName + "?api-version=2017-10-01-preview";

    HttpClient httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Remove("Authorization");
    httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
    string requestBody = "{location: \"" + locationName + "\"}";

    HttpResponseMessage response = await httpClient.PutAsync(url, new StringContent(requestBody, Encoding.UTF8, "application/json"));
    var statusCode = response.StatusCode.ToString();
}


/// <summary>
/// Gets and access token with which to call the Azure API
/// </summary>
/// <param name="tenantId">See Portal > Active Directory > Properties > Overview for this value</param>
/// <param name="clientId">See Portal > Active Directory > App Registrations > This App > Overview for this value</param>
/// <param name="clientSecret">See Portal > Active Directory > App Registrations > This App > Certificates & Secrets > Generate Secret </param>
/// <returns></returns>
private async Task<string> GetAccessTokenAsync(string tenantId, string clientId, string clientSecret)
{
    Console.WriteLine("Begin GetAccessToken");
    string authContextURL = "https://login.windows.net/" + tenantId;
    var authenticationContext = new AuthenticationContext(authContextURL);
    var credential = new ClientCredential(clientId, clientSecret);
    var result = await authenticationContext
        .AcquireTokenAsync("https://management.azure.com/", credential);
    if (result == null)
    {
        throw new InvalidOperationException("Failed to obtain the JWT token");
    }
    string token = result.AccessToken;
    return token;
}

1 Answer 1

0

Managed to find the answer in this post/ this Microsoft Article.

What I needed to do was:

  1. Go to Portal > Subscriptions > {my subscription}
  2. Click on Access control (IAM)
  3. Add > Add Role Assignment as shown below (note: 'SqlTest' is the Application I created in Portal > Azure Active Directory > App Registrations)

enter image description here

Then the code works nicely.

Sign up to request clarification or add additional context in comments.

2 Comments

Hi, you can accept(mark) it as answer. This can be beneficial to other community members. Thank you.
@LeonYue. I will. You have to wait 48hrs to do so, so I can't do it yet. Thanks. J

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.