Skip to content

Request to create API key for subuser is not working as expected. Additional SendGrid request headers aren't being passed with the request. #214

Description

@brettcooper

Issue Summary

I have been working with Becca and Ryan at SendGrid to try to fix an issue we have been experiencing where we are trying to create an API key for a SendGrid subuser, but the API key is not associated to that subuser. The CURL command Ryan sent over works fine:

cURL API Keys - on behalf of a subuser

curl -X POST
https://api.sendgrid.com/v3/api_keys
-H 'authorization: Basic [BASE64 PARENT USER/PASS]' \
-H 'content-type: application/json'
-H 'on-behalf-of: SUBUSER USERNAME'
-d '{
"name": "API KEY NAME",
"scopes": [
"mail.send",
"alerts.create",
"alerts.read"
]
}'

But, when trying to perform the same HTTP POST with the SendGrid Java client, this is failing.

Here is the code I wrote to create a SendGrid subuser's API key:

    public String createApiKey(String username) {
        if (StringUtils.isNullOrEmpty(username)) return null;

        ObjectNode objectNode = MAPPER.createObjectNode();
        objectNode.put("name", "API key for " + username);

        ArrayNode scopes = MAPPER.createArrayNode();
        scopes.add("mail.send");

        objectNode.putArray("scopes").addAll(scopes);

        Request sendGridRequest = new Request();
        sendGridRequest.setMethod(Method.POST);
        sendGridRequest.setEndpoint(API_KEYS_ENDPOINT);
        sendGridRequest.setBody(objectNode.toString());
        // HERE!! 
        sendGridRequest.addHeader("on-behalf-of", username);

        try {
            Response response = sendGrid.api(sendGridRequest);
            int responseStatusCode = response.getStatusCode();

            if (responseStatusCode != HttpStatus.SC_CREATED) {
                LOG.error("Error while creating API key for subuser. Http status: {}", responseStatusCode);
                return null;
            }

            String responseBody = response.getBody();

            LOG.debug("SendGrid API key '{}' created for: {}", responseBody, username);

            return responseBody;
        } catch (IOException e) {
            LOG.error("Error while creating API key for subuser: {}", e);
            return null;
        }
    }

But, while debugging through the request, the headers added to the SendGrid request are not being added to the request that actually gets sent to SendGrid:

SendGrid class:

  /**
    * Class api sets up the request to the SendGrid API, this is main interface.
    */
  public Response api(Request request) throws IOException {
    Request req = new Request();
    req.setMethod(request.getMethod());
    req.setBaseUri(this.host);
    req.setEndpoint("/" + version + "/" + request.getEndpoint());
    req.setBody(request.getBody());
    // HERE!! 
    for (Map.Entry <String, String> header : this.requestHeaders.entrySet()) {
      req.addHeader(header.getKey(), header.getValue());
    }
    for (Map.Entry <String, String> queryParam : request.getQueryParams().entrySet()) {
      req.addQueryParam(queryParam.getKey(), queryParam.getValue());
    }

    return makeCall(req);
  }

So the bug is that any headers I add to my SendGrid request object are not being added to the actual request headers sent to SendGrid. To correct this, the headers from the SendGrid request object need to be added to the actual request object being sent to SendGrid.

Fixed SendGrid class:

  /**
    * Class api sets up the request to the SendGrid API, this is main interface.
    */
  public Response api(Request request) throws IOException {
    Request req = new Request();
    req.setMethod(request.getMethod());
    req.setBaseUri(this.host);
    req.setEndpoint("/" + version + "/" + request.getEndpoint());
    req.setBody(request.getBody());
    // HERE!! 
    req.getHeaders().putAll(request.getHeaders);
    for (Map.Entry <String, String> header : this.requestHeaders.entrySet()) {
      req.addHeader(header.getKey(), header.getValue());
    }
    for (Map.Entry <String, String> queryParam : request.getQueryParams().entrySet()) {
      req.addQueryParam(queryParam.getKey(), queryParam.getValue());
    }

    return makeCall(req);
  }

Here is my current workaround until this issue is fixed:

    public String createApiKey(String username) {
        if (StringUtils.isNullOrEmpty(username)) return null;

        ObjectNode objectNode = MAPPER.createObjectNode();
        objectNode.put("name", "API key for " + username);

        ArrayNode scopes = MAPPER.createArrayNode();
        scopes.add("mail.send");

        objectNode.putArray("scopes").addAll(scopes);

        Request sendGridRequest = new Request();
        sendGridRequest.setMethod(Method.POST);
        sendGridRequest.setEndpoint(API_KEYS_ENDPOINT);
        sendGridRequest.setBody(objectNode.toString());
        //sendGridRequest.addHeader("on-behalf-of", username);

        try {
            // HERE!! 
            sendGrid.getRequestHeaders().put("on-behalf-of", username);
            Response response = sendGrid.api(sendGridRequest);


            int responseStatusCode = response.getStatusCode();

            if (responseStatusCode != HttpStatus.SC_CREATED) {
                LOG.error("Error while creating API key for subuser. Http status: {}", responseStatusCode);
                return null;
            }

            String responseBody = response.getBody();

            LOG.debug("SendGrid API key '{}' created for: {}", responseBody, username);

            return responseBody;
        } catch (IOException e) {
            LOG.error("Error while creating API key for subuser: {}", e);
            return null;
        }
    }

Please help us fix this issue!

Steps to Reproduce

  1. This is the first step

Add the "on-behalf-of" header to the SendGrid request object via the .addHeader() method with the subuser's username.

  1. This is the second step

Run the code to create the API key for the subuser. Notice, the "on-behalf-of" header is never sent and the API key created is not associated with the subuser.

Technical details:

  • sendgrid-java Version: 4.0.1
  • Java Version: 1.8.0_74

Metadata

Metadata

Assignees

No one assigned

    Labels

    difficulty: hardfix is hard in difficultystatus: work in progressTwilio or the community is in the process of implementingtype: bugbug in the library

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions