Chapter 5. ActiveDocs and OAuth ActiveDocs allows your users to test and call your OAuth-enabled API from one place. Prerequisites You need to have a Red Hat single sign-on or Red Hat build of Keycloak instance set up, and OpenID Connect integration configured. See OpenID Connect integration documentation for information on how to set it up. Additionally, you need to be familiar with how to set up ActiveDocs - see Adding ActiveDocs to 3scale and Creating an OpenAPI specification . 5.1. Example of client credentials and resource owner flows in a 3scale API Management specification This first example is for an API using the OAuth 2.0 client credentials flow in a 3scale specification. This API accepts any path and returns information about the request (path, request parameters, headers, and more). The Echo API is accessible only by using a valid access token. Users of the API are able to call it only after they have exchanged their credentials ( client_id and client_secret ) for an access token. For users to be able to call the API from ActiveDocs, they must request an access token. Since this is just a call to an OAuth authorization server, you can create an ActiveDocs specification for the OAuth token endpoint. This allows calls to this endpoint from within ActiveDocs. In this case, for a client credentials flow, the Swagger JSON specification looks like this: For a resource owner OAuth flow, add parameters for a username and password and other parameters that you require in order to issue an access token. For this client credentials flow example, you are sending the client_id and client_secret , which can be populated from the 3scale values for signed-in users, as well as the grant_type. Then in the ActiveDocs specification for the Echo API, add the access_token parameter instead of the client_id and the client_secret . You can then include your ActiveDocs in the Developer Portal as usual. In this case, since you want to specify the order in which they display to have the OAuth endpoint first, it looks like this: 5.2. Publishing ActiveDocs in the Developer Portal By the end of this tutorial, you will have published your ActiveDocs in your Developer Portal and your API documentation will be automated. Prerequisites An OpenAPI Specification (OAS) compliant specification for your REST API is required to power ActiveDocs on your Developer Portal. Procedure Add the following snippet to the content of any page of your Developer Portal. You must do this through the 3scale Admin Portal. Note SERVICE_NAME should be the system name of the service specification, which is pet_store in the example. Developer Portal configuration using OAS 3.0 {% content_for javascripts %} {{ 'active_docs.js' | javascript_include_tag }} {% endcontent_for %} {% assign spec = provider.api_specs.first %} <h1>Documentation</h1> <div class="swagger-section"> <div id="message-bar" class="swagger-ui-wrap"></div> <div id="swagger-ui-container" class="swagger-ui-wrap"></div> </div> <script type="text/javascript"> (function () { var url = "{{spec.url}}"; var serviceEndpoint = "{{spec.api_product_production_public_base_url}}" SwaggerUI({ url: url, dom_id: "#swagger-ui-container" }, serviceEndpoint); }()); </script> Developer Portal configuration using OAS 2.0 <h1>Documentation</h1> <p>Use our live documentation to learn about Echo API</p> {% active_docs version: "2.0" services: "SERVICE_NAME" %} {% cdn_asset /swagger-ui/2.2.10/swagger-ui.js %} {% cdn_asset /swagger-ui/2.2.10/swagger-ui.css %} {% include 'shared/swagger_ui' %} <script type="text/javascript"> USD(function () { {% comment %} // you have access to swaggerUi.options object to customize its behavior // such as setting a different docExpansion mode window.swaggerUi.options['docExpansion'] = 'none'; // or even getting the swagger specification loaded from a different url window.swaggerUi.options['url'] = "http://petstore.swagger.io/v2/swagger.json"; {% endcomment %} window.swaggerUi.load(); }); </script> These are some additional considerations when publishing ActiveDocs in the Developer Portal: You can specify only one service on one page. If you want to display multiple specifications, the best way is to do it on different pages. This snippet requires jQuery, which is included by default in the main layout of your Developer Portal. If you remove the jQuery dependency from the main layout, you must add this dependency on the page containing ActiveDocs. Make sure you have Liquid tags enabled on the Admin Portal. The version used in the Liquid tag for OAS 2.0 {{ '{% active_docs version: "2.0" ' }}%} should correspond to that of the Swagger spec. If you want to fetch your specification from an external source, change the JavaScript code as follows: USD(function () { window.swaggerUi.options['url'] = "SWAGGER_JSON_URL"; window.swaggerUi.load(); }); Note that the line containing the source of the specification, window.swaggerUi.options['url'] = "SWAGGER_JSON_URL"; , is outside the comments block. Verification steps After you have created an OpenAPI specification and you have added it to 3scale , it is time to publish the specification and link it on your Developer Portal to be used by your API developers.

Commands:
{ "swagger": "2.0", "info": { "version": "v1", "title": "OAuth for Echo API", "description": "OAuth2.0 Client Credentails Flow for authentication of our Echo API.", "contact": { "name": "API Support", "url": "http://www.swagger.io/support", "email": "support@swagger.io" } }, "host": "red-hat-sso-instance.example.com", "basePath": "/auth/realms/realm-example/protocol/openid-connect", "schemes": [ "http" ], "paths": { "/token": { "post": { "description": "This operation returns the access token for the API. You must call this before calling any other endpoints.", "operationId": "oauth", "parameters": [ { "name": "client_id", "description": "Your client id", "type": "string", "in": "query", "required": true }, { "name": "client_secret", "description": "Your client secret", "type": "string", "in": "query", "required": true }, { "name": "grant_type", "description": "OAuth2 Grant Type", "type": "string", "default": "client_credentials", "required": true, "in": "query", "enum": [ "client_credentials", "authorization_code", "refresh_token", "password" ] } ] } } } }
{ "swagger": "2.0", "info": { "version": "v1", "title": "Echo API", "description": "A simple API that accepts any path and returns information about the request", "contact": { "name": "API Support", "url": "http://www.swagger.io/support", "email": "support@swagger.io" } }, "host": "echo-api.3scale.net", "basePath": "/v1/words", "schemes": [ "http" ], "produces": [ "application/json" ], "paths": { "/{word}.json": { "get": { "description": "This operation returns information about the request (path, request parameters, headers, etc.), "operationId": "wordsGet", "summary": "Returns the path of a given word", "parameters": [ { "name": "word", "description": "The word related to the path", "type": "string", "in": "path", "required": true }, { "name": "access_token", "description": "Your access token", "type": "string", "in": "query", "required": true } ] } } } }
{% active_docs version: "2.0" services: "oauth" %} <script type="text/javascript"> USD(function () { window.swaggerUi.load(); // <-- loads first swagger-ui // do second swagger-ui var url = "/swagger/spec/echo-api.json"; window.anotherSwaggerUi = new SwaggerUi({ url: url, dom_id: "another-swagger-ui-container", supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'], onComplete: function(swaggerApi, swaggerUi) { USD('#another-swagger-ui-container pre code').each(function(i, e) {hljs.highlightBlock(e)}); }, onFailure: function(data) { log("Unable to Load Echo-API-SwaggerUI"); }, docExpansion: "list", transport: function(httpClient, obj) { log("[swagger-ui]>>> custom transport."); return ApiDocsProxy.execute(httpClient, obj); } }); window.anotherSwaggerUi.load(); }); </script>
{% content_for javascripts %} {{ 'active_docs.js' | javascript_include_tag }} {% endcontent_for %} {% assign spec = provider.api_specs.first %} <h1>Documentation</h1> <div class="swagger-section"> <div id="message-bar" class="swagger-ui-wrap"></div> <div id="swagger-ui-container" class="swagger-ui-wrap"></div> </div> <script type="text/javascript"> (function () { var url = "{{spec.url}}"; var serviceEndpoint = "{{spec.api_product_production_public_base_url}}" SwaggerUI({ url: url, dom_id: "#swagger-ui-container" }, serviceEndpoint); }()); </script>
<h1>Documentation</h1> <p>Use our live documentation to learn about Echo API</p> {% active_docs version: "2.0" services: "SERVICE_NAME" %} {% cdn_asset /swagger-ui/2.2.10/swagger-ui.js %} {% cdn_asset /swagger-ui/2.2.10/swagger-ui.css %} {% include 'shared/swagger_ui' %} <script type="text/javascript"> USD(function () { {% comment %} // you have access to swaggerUi.options object to customize its behavior // such as setting a different docExpansion mode window.swaggerUi.options['docExpansion'] = 'none'; // or even getting the swagger specification loaded from a different url window.swaggerUi.options['url'] = "http://petstore.swagger.io/v2/swagger.json"; {% endcomment %} window.swaggerUi.load(); }); </script>
USD(function () { window.swaggerUi.options['url'] = "SWAGGER_JSON_URL"; window.swaggerUi.load(); });