How to automatically add the api key to the request headers (i.e. without providing it in the UI)

4,882 views
Skip to first unread message

j3d

unread,
Aug 4, 2014, 5:20:53 AM8/4/14
to swagger-sw...@googlegroups.com
Dear all,

Maybe in my other post it was not really clear what my problem is... so it is worth creating a new thread where I'll try to be more clear :-)

Let me provide you with some background info. Any request sent to my REST API should always contain at least the following 3 headers:
  • Api_key: an UUID identifying the API consumer (App) that sent the request
  • Signature: the signature generated by applying the secret associated with the Api_key
  • Token: the Json Web Token (JWT) that identifies the user session
Api_key and Signature have nothing to do with user sessions (user authentication/authorization are managed with the Token header)... they just ensure only authorized/registerd API consumers (Apps) access the REST API.

That said, I see Swagger UI as an API consumer for which I have an Api_Key/Secret pair in my database, and as for any other API consumer, Swagger should always use its Secret to sign the requests and add the resulting Signature along with its Api key to the request headers. As for any other API consumer (client app), the Api_Key and Secret could be hardcoded somewhere in the code... and this is what I'm trying to do.

Here is how my index.html looks like:

  <script type="text/javascript">
    $(function () {
      window.swaggerUi = new SwaggerUi({
      url: "http://localhost:9000/api-docs",
      dom_id: "swagger-ui-container",
      supportedSubmitMethods: ['get', 'patch', 'post', 'put', 'delete'],
      onComplete: function(swaggerApi, swaggerUi){
        log("Loaded SwaggerUI");
        $('pre code').each(function(i, e) {
          hljs.highlightBlock(e)
        });
      },
      onFailure: function(data) {
        log("Unable to Load SwaggerUI");
      },
      docExpansion: "none",
      sorter: "alpha"
    });

    var key = "f333e99c-8765-123b-aa66-1234abcd2299";
    log("added key " + key);
    window.authorizations.add("key", new ApiKeyAuthorization("api_key", key, "header"));

    $('#input_authToken').change(function() {
      key = $('#input_authToken')[0].value;
      if (key && key.trim() != "") {
        log("added key " + key);
        window.authorizations.add("key", new ApiKeyAuthorization("Authorization", "Token " + key, "header"));
      }
    })
    window.swaggerUi.load();
  });
  </script>
</head>
...

I've modified the Swagger UI CSS since the user only needs to provide the session Token (lines in green) returned by the SignIn API, while the the Api_key (lines in red) should always be added to the request headers automatically.

Unfortunately what I did above doesn't work. The request headers only contain the Token header but not the Api Key header. I've tried everything I could:

1) Added the apiKey parameter to SwaggerUi

2) Added the Api_key to Swagger's configuration:
  val apikey = ApiKey("Api_key", "header")
  ConfigFactory.config.authorizations = List(apiKey)

3) Added the Authorizations annotation to my controller:

  @Api(value = "/myApi", description = "My API", authorizations = Array(new Authorization(value = "Api_key")))
  object MyController extends Controller {
    ...
  }

4) Added the Authorizations annotation to my operation:

  @Api(value = "/myApi", description = "My API", authorizations = Array(new Authorization(value = "Api_key")))
  object MyController extends Controller {

  @ApiOperation(
    httpMethod = "POST",
    nickname = "doSomething",
    value = "Does something...",
    response = classOf[Void], authorizations = Array(new Authorization(value = "Api_key")))
  @ApiResponses(Array(
    new ApiResponse(code = 400, message = "Invalid data"),
    new ApiResponse(code = 401, message = "Request not authorized"),
    ...
  )
  def doSomething = ...

  }

No way... for sure I'm missing something or at least it's not 100% clear to me how to configure Swagger. Any help, doc reference, or whatever else would be really appreciated.

Thank you very much,
j3d

Ron

unread,
Aug 4, 2014, 6:21:50 AM8/4/14
to swagger-sw...@googlegroups.com
Hi j3d,

I'm sure Tony would provide you with the information on how to solve the issue with regards to the UI.

I'd like to take a moment and clarify the details regarding the declaration of the authorization headers from the code and spec point of view.
You're describing 3 authorization headers in your text, but your code describes only the Api_key header. It sounds like you'd want to add Signature and Token as well.
Those would be separate authorizations you'd add to
ConfigFactory.config.authorizations

After that, there's no need to define the authorizations on both the controller and the operation. Authorizations are inherited, so it's enough to declare them on the resource/controller itself.
If you add the additional headers declarations, you'd need them to the Authorizations list of the @Api/@ApiOperation as well.

This does not necessarily affect the UI, but rather produces a Swagger Specification file that actually describes your API as you want it.


--
You received this message because you are subscribed to the Google Groups "Swagger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggers...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

j3d

unread,
Aug 4, 2014, 1:59:28 PM8/4/14
to swagger-sw...@googlegroups.com
Hi Ron,

The code I added to index.html to enable the auth_token from the UI seems to be OK:

    $('#input_authToken').change(function() {
      key = $('#input_authToken')[0].value;
      if (key && key.trim() != "") {
        log("added key " + key);
        window.authorizations.add("key", new ApiKeyAuthorization("Authorization", "Token " + key, "header"));
      }
    })

In the UI I've replaced the api_key box with the auth_token box... and this works as expected ;-)

Now, what I really need is adding headers Api_key and Signature to each request automatically (the value of these headers should be hardcoded somewhere in the Swagger code)... and since I've tried everything I could but without success, I'm just wondering where I'm wrong.

Anyway, thank you for your post.
j3d
To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggersocket+unsub...@googlegroups.com.

j3d

unread,
Aug 4, 2014, 6:44:42 PM8/4/14
to swagger-sw...@googlegroups.com
OK, it works... and eventually I've understood the concept behind authorizations injection ;-)
I think the is just this open point: https://github.com/wordnik/swagger-core/issues/607 ... but I was unable to figure out the workaround.

Anyway, it's fine.
j3d

Ron

unread,
Aug 5, 2014, 4:16:34 AM8/5/14
to swagger-sw...@googlegroups.com
Is your application based on the Play Framework?


To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggers...@googlegroups.com.

j3d

unread,
Aug 5, 2014, 12:58:54 PM8/5/14
to swagger-sw...@googlegroups.com
Yes :-)
To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggersocket+unsubscri...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Ron

unread,
Aug 5, 2014, 1:19:17 PM8/5/14
to swagger-sw...@googlegroups.com
Haven't tested it myself (never really used Play), but if the issue exists as the link says, then that's an actual bug and there's no real workaround for it besides fixing the code.


To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggers...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages