简体   繁体   中英

Azure RateCard “AuthenticationFailed”"

I want to get a Azure RateCard via Billing Api with a Java Application. First of all I create an AccessToken what works correctly. But when I want to use this AccessToken to get a RateCard I get an authentication error. Here is my java code:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

public class TestingAzure {

public static String getAccessToken(String tenantId, String clientId, String clientSecret)
        throws MalformedURLException, IOException {
    String endpoint = String.format("https://login.microsoftonline.com/%s/oauth2/token", tenantId);
    String postBody = String.format("grant_type=client_credentials&client_id=%s&client_secret=%s&resource=%s",
            clientId, clientSecret, "https://management.azure.com/");
    HttpURLConnection conn = (HttpURLConnection) new URL(endpoint).openConnection();
    conn.setRequestMethod("POST");
    conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    conn.setDoOutput(true);
    conn.getOutputStream().write(postBody.getBytes());
    conn.connect();
//      If you want to see the response content, please use the commented code below.
//      BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
//      StringBuilder builder = new StringBuilder();
//      String line = null;
//      while ((line = reader.readLine()) != null) {
//          builder.append(line);
//      }
//      reader.close();
//      System.out.println(builder.toString());
//      The output for access token is {"token_type":"Bearer","expires_in":"3600","ext_expires_in":"3600","expires_on":"1550660092","not_before":"1550656192","resource":"https://management.azure.com/","access_token":"eyJ0eXAiOiJKV1QiL...."}
    JsonFactory factory = new JsonFactory();
    JsonParser parser = factory.createParser(conn.getInputStream());
    String accessToken = null;
    while (parser.nextToken() != JsonToken.END_OBJECT) {
        String name = parser.getCurrentName();
        if ("access_token".equals(name)) {
            parser.nextToken();
            accessToken = parser.getText();
        }
    }
    return accessToken;
}

public static String getRateCard(String subscriptionId, String apiVersion, String offerId, String currency,
        String locale, String region, String accessToken) throws MalformedURLException, IOException {
    String endpoint = String.format(
            "https://management.azure.com/subscriptions/%s/providers/Microsoft.Commerce/RateCard?api-version=%s&$filter=OfferDurableId eq '%s' and Currency eq '%s' and Locale eq '%s' and RegionInfo eq '%s'",
            subscriptionId, apiVersion, offerId, currency, locale, region).replaceAll(" ", "%20");
    HttpURLConnection conn = (HttpURLConnection) new URL(endpoint).openConnection();
    conn.setRequestMethod("GET");
    conn.addRequestProperty("Authorization", "Bearer " + accessToken);
    conn.addRequestProperty("Content-Type", "application/json");
    conn.connect();
    BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    StringBuilder builder = new StringBuilder();
    String line = null;
    while ((line = reader.readLine()) != null) {
        builder.append(line);
    }
    reader.close();
    return builder.toString();
}

public static void main(String[] args) throws MalformedURLException, IOException {
    String tenantId = "*****";
    String clientId = "*****";
    String clientSecret = "*****";
    clientSecret=java.net.URLEncoder.encode(clientSecret,"UTF-8");
    System.out.println(clientSecret);
    String accessToken = getAccessToken(tenantId, clientId, clientSecret);
    System.out.println(accessToken);
    String subscriptionId = "*****";
    String apiVersion = "2015-06-01-preview";
    String offerId = "****";
    String currency = "EUR";
    String locale = "de-DE";
    String region = "DE";
    String rateCardResp = getRateCard(subscriptionId, apiVersion, offerId, currency, locale, region, accessToken);
    System.out.println(rateCardResp);
}

}

In Eclipse the error is:

Exception in thread "main" java.io.IOException: Server returned HTTP response code: 403 for URL: https://management.azure.com/subscriptions/*subscriptionID*/providers/Microsoft.Commerce/RateCard?api-version=2015-06-01-preview&$filter=OfferDurableId%20eq%20'MS-AZR-0017P'%20and%20Currency%20eq%20'EUR'%20and%20Locale%20eq%20'de-DE'%20and%20RegionInfo%20eq%20'DE'
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at com.nttdata.altemista.TestingAzure.getRateCard(TestingAzure.java:60)
at com.nttdata.altemista.TestingAzure.main(TestingAzure.java:84)

When I search for the URL I get the following message:

{"error":{"code":"AuthenticationFailed","message":"Fehler bei der Authentifizierung. Der Authorization-Header fehlt."}}

Actually I had the highest role to work with this subscription. I don't know what I can try.

In your sample , Have you given sufficent permission to your service principal, which is permission to access Windows Azure Service Management APIs.

Here is very good example , how to configure an app in Azure AD if you want to access management resources in Java

https://blogs.msdn.microsoft.com/azureossds/2015/06/23/authenticating-azure-resource-management-rest-api-requests-using-java/

Alternatively , Here is how you can configure the native app to use the Azure Rate card Api Step 1: Configure a Native Client application in your AAD tenant

Before you can run the sample application, you will need to allow it to access your AAD tenant for authentication and authorization to access the Billing APIs. If you already have a Native Client Application configured that you would like to use (and it is configured according to the steps below), you can jump to Step 2.

To configure a new AAD application:

  1. Sign in to the Azure portal, using credentials that have been granted service administrator/co-administrator access on the subscription which is trusting your AAD tenant, and granted Global Administrator access in the AAD tenant. See Manage Accounts, Subscriptions, and Administrative Roles for details on managing the service administrator and co-administrators.

  2. Select the AAD tenant you wish to use, and go to the "Applications" page.

  3. From there, you can use the "Add" feature to "Add a new application my organization is developing".

  4. Provide a name (ie: ConsoleApp-Billing-RateCard or similar) for the new application.

  5. Be sure to select the "Native Client Application" type, then specify a valid URL for "Redirect URI" (which can be http://localhost/ for the purposes of this sample), and click the check mark to save.

  6. After you've added the new application, select it again within the list of applications and click "Configure" so you can make sure the sample app will have permissions to access the Windows Azure Service Management APIs, which is the permission used to secure the Billing APIs.

  7. Scroll down to the to the "Permissions to other applications" section of your newly created application's configuration page. Then click the "Add Application" button, select the "Windows Azure Service Management" row, and click the check mark to save. After saving, hover the "Delegated Permissions" area on the right side of the "Windows Azure Service Management" row, click the "Delegated Permissions" drop down list, select the "Access Azure Service Management (preview)" option, and click "Save" again.

NOTE : the "Windows Azure Active Directory" permission "Enable sign-on and read users' profiles" is enabled by default. It allows users to sign in to the application with their organizational accounts, enabling the application to read the profiles of signed-in users, such as their email address and contact information. This is a delegation permission, and gives the user the ability to consent before proceeding. Please refer to Adding, Updating, and Removing an Application for more depth on configuring an Azure AD tenant to enable an application to access your tenant.

  1. While you are on this page, also note/copy the "Client ID" GUID and "Redirect URI",

as you will use these in Step #3 below. You will also need your Azure Subscription ID and AAD tenant domain name, both of which you can copy from the "Settings" page in the management portal.

Note :- If you want to use grant_type="Client_credential" and using client id and client_secret, Please ensure you have at least admin/co admin role in the subscription and you application have sufficient permission as mentioned above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM