0

I'm trying to implement LWA secret rotation request using "Application Management API v2023-11-30 Use Case Guide".

Here is my test C# code:

public static async Task RotateLWAAsync(
        string ClientId = "{Your client ID}",
        string ClientSecret = "{Your client secret}",
        string grant_type = "client_credentials",
        string scope = "sellingpartnerapi::client_credential:rotation",
        string refreshToken = "{Your refresh token}",
        CancellationToken cancellationToken = default)
{
    try
    {
        var data = string.Empty;

        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri("https://api.amazon.com");
            var byteArray = Encoding.ASCII.GetBytes($"{ClientId}:{ClientSecret}");
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

            Dictionary items = new Dictionary();
            items.Add("grant_type", grant_type);
            items.Add("scope", scope); // ScopeConstants.ScopeMigrationAPI);
            items.Add("client_id", ClientId);
            items.Add("client_secret", ClientSecret);

            FormUrlEncodedContent formUrlEncodedContent = new FormUrlEncodedContent(items);
            var rs = await client.PostAsync("/auth/o2/token", formUrlEncodedContent, cancellationToken);
            data = await rs.Content.ReadAsStringAsync();

            System.Console.WriteLine($"StatusCode = {rs.StatusCode}, Success = {rs.IsSuccessStatusCode}, Msg = {rs.ReasonPhrase}");
        }

        var r = JsonConvert.DeserializeObject(data);
        var json = Newtonsoft.Json.JsonConvert.SerializeObject(r, Formatting.Indented);
        System.Console.WriteLine(json);

        System.Console.WriteLine("---");

        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri("https://sellingpartnerapi-na.amazon.com");

            Dictionary items = new Dictionary();
            items.Add("x-amz-access-token", r.access_token);

            FormUrlEncodedContent formUrlEncodedContent = new FormUrlEncodedContent(items);
            var rs = await client.PostAsync("/applications/2023-11-30/clientSecret", formUrlEncodedContent, cancellationToken);

            System.Console.WriteLine($"StatusCode = {rs.StatusCode}, Success = {rs.IsSuccessStatusCode}, Msg = {rs.ReasonPhrase}");

            data = await rs.Content.ReadAsStringAsync();

            System.Console.WriteLine ($"data = {data}");

        }

        return true;
    }
    catch (Exception ex)
    {
        System.Console.WriteLine($"Run-time Error: {ex.Message}");
    }

    return false;
}

The above code results in the following output:

    StatusCode = OK, Success = True, Msg = OK
    {
        "access_token": "{Correct access token returned}",
        "refresh_token": null,
        "token_type": "bearer",
        "expires_in": 3600,
        "date_Created": "2024-09-23T14:29:32.6320411Z"
    }
    ---
    StatusCode = Forbidden, Success = False, Msg =
    data = {
        "errors": [
        {
            "code": "Unauthorized",
            "message": "Access to requested resource is denied.",
            "details": "Access token is missing in the request header."
        }
        ]
    }

What am I doing wrong with my second HTTP call client.PostAsync(...), which in the case of success should return status code 204?

1 Answer 1

0

Here is the solution, the error with the second Http request was that it passed x-amz-access-token's value in the POST request message body but it should be passed in the request message header.

public static async Task RotateLWAAsync(
        string ClientId = "{Your client ID}",
        string ClientSecret = "{Your client secret}",
        string grant_type = "client_credentials",
        string scope = "sellingpartnerapi::client_credential:rotation",
        string refreshToken = "{Your refresh token}",
        CancellationToken cancellationToken = default)
{
    try
    {
        var data = string.Empty;

        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri("https://api.amazon.com");
            var byteArray = Encoding.ASCII.GetBytes($"{ClientId}:{ClientSecret}");
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

            Dictionary items = new Dictionary();
            items.Add("grant_type", grant_type);
            items.Add("scope", scope);
            items.Add("client_id", ClientId);
            items.Add("client_secret", ClientSecret);

            FormUrlEncodedContent formUrlEncodedContent = new FormUrlEncodedContent(items);
            var rs = await client.PostAsync("/auth/o2/token", formUrlEncodedContent, cancellationToken);
            data = await rs.Content.ReadAsStringAsync();

            System.Console.WriteLine($"StatusCode = {rs.StatusCode}, Success = {rs.IsSuccessStatusCode}, Msg = {rs.ReasonPhrase}");
        }

        var r = JsonConvert.DeserializeObject(data);
        var json = Newtonsoft.Json.JsonConvert.SerializeObject(r, Formatting.Indented);
        System.Console.WriteLine(json);

        System.Console.WriteLine("---");

        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri("https://sellingpartnerapi-na.amazon.com");

            using (var request = new HttpRequestMessage(HttpMethod.Post, "/applications/2023-11-30/clientSecret"))
            {
                request.Headers.Add("x-amz-access-token", r.access_token);

                var rs = await client.SendAsync(request, cancellationToken);

                System.Console.WriteLine($"StatusCode = {rs.StatusCode}, Success = {rs.IsSuccessStatusCode}, Msg = {rs.ReasonPhrase}");

                data = await rs.Content.ReadAsStringAsync();

                System.Console.WriteLine($"data = {data}");
            }

        }

        return true;
    }
    catch (Exception ex)
    {
        System.Console.WriteLine($"Run-time Error: {ex.Message}");
    }

    return false;
}

The above code results in the following output:

    StatusCode = OK, Success = True, Msg = OK
    {
        "access_token": "{Correct access token returned}",
        "refresh_token": null,
        "token_type": "bearer",
        "expires_in": 3600,
        "date_Created": "2024-09-23T14:29:32.6320411Z"
    }
    ---
    StatusCode = NoContent, Success = True, Msg =
    data = 
Sign up to request clarification or add additional context in comments.

Comments

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.