Keycloak with Spring Boot #3 – How to authorize requests in Swagger UI

featured image

Swagger offers various methods to authorize requests to our Keycloak secured API. I’ll show you how to implement the recommended grant types and why certain flows are advised against in the OAuth 2.0 specification.

Prerequisites

As a result, I have Swagger UI at http://localhost:8080/swagger-ui.html and OpenAPI specification at http://localhost:8080/v3/api-docs. For more information on documenting Spring Boot applications using Springdoc, see the Easy OpenAPI 3 specification for your Spring Boot REST API article.

Authorize Swagger requests in Keycloak

I’ll demonstrate three authorization configurations:

  • Authorization Code which is one of the OAuth 2.0 flows,
  • OpenID Connect Discovery mechanism,
  • Bearer Authentication.

Select the one that better suits the needs of your project. In the end, we want to end up with the Authorize button that will provide authorization options suitable for our API and Keycloak server:

Authorize button in Swagger that will work with Keycloak

Allow access to Swagger endpoints

I’m going to modify my SecurityConfig class to allow Swagger endpoints to be called without authentication:

Provide Keycloak server details

Authorizatin Code and OpenID Connect Disvovery require realm name and the url of the Keycloak server for proper configuration. Although we can provide them as hardcoded strings for testing purposes, I’m going to reuse the data that’s already available in my application.properties file:

To access the properties in the code, I’m going to create the following short record:

That’s all we need to inject these properties into our Swagger config if our project uses a Java version with Record support. Alternatively, follow the Type-safe Configuration Properties::Constructor Binding section in the Spring docs to use a simple class (with getters and @ConstructorBinding annotation).

Thanks to this, I only provide Keycloak details in one place and I don’t have to painstakingly search my configuration classes to update the values. Additionally, the properties will always be in accordance with the selected application profile (dev, production, etc.).

Swagger authorization with the OAuth 2.0 protocol

The example implementation is available in the keycloak-spring-boot repository.

First of all, I’m going to consult the Swagger docs for a quick summary of the authorization flows available:

The flows (also called grant types) are scenarios an API client performs to get an access token from the authorization server. OAuth 2.0 provides several flows suitable for different types of API clients:
– Authorization code,
– Implicit,
– Resource owner password credentials,
– Client credentials.

https://swagger.io/docs/specification/authentication/oauth2/

I’m going to provide the configuration for the Authorization Code Grant as this is the most secure option for my Swagger API calls. The following quote contains a brief explanation of this flow:

When the user authorizes the application, they are redirected back to the application with a temporary code in the URL. The application exchanges that code for the access token. When the application makes the request for the access token, that request can be authenticated with the client secret, which reduces the risk of an attacker intercepting the authorization code and using it themselves.

This also means the access token is never visible to the user or their browser, so it is the most secure way to pass the token back to the application, reducing the risk of the token leaking to someone else.

https://www.oauth.com/oauth2-servers/server-side-apps/authorization-code/

Make sure that the Standard Flow is enabled in Keycloak as it allows us to use the Authorization Code flow:

standard flow enabled in Keycloak

Configuration class

Let’s look at the example configuration documented in Swagger:

In other words, in order to authorize requests in Keycloak, Swagger requires a component containing a security scheme with a particular flow. Based on this, I can provide my own setup in Java. Below you can see the full configuration class:

There are a few things to note:

  1. Components – a collection of reusable objects that define various aspects of the Open API Specification.
  2. SecuritySceme – here we can define our scheme type with the Authorization Code flow.
  3. OAuthflow – an object for specifying the configuration details of the selected flow. We have to follow the list of the required fields for each auth type from the screenshot below:
required fields for Authorization Code Grant in OpenAPI

As a result, we’ll see that the Authiorization Code Grant will be the only available auth option in Swagger UI:

Swagger UI secured with Authorization Code flow for Keycloak

Adding Scopes to the config

In the screenshot with required fields for the OAuth flow, we can read that scopes field is just a map between their names and descriptions:

scopes definition

Therefore, if you want to provide a scope, e.g. address, you need to add it when creating the authorization flow:

As a consequence, the list of scopes will appear in the Swagger authorization window after restarting the application:

scopes in swagger authorization for Keycloak

Another thing to remember is that if you don’t add the openid scope, you’ll get the following warning in the keycloak instance’s logs:

As a result, the requests are still valid OAuth2 requests. However, the behaviour might be unpredictable if you rely on the OIDC standard.

Swagger authorization with the OpenID Connect Discovery mechanism

The example implementation is available in the spring-boot-swagger-ui-keycloak repository.

If you need more security schemes available in Swagger UI, you can easily achieve it with the OIDC discovery mechanism. It takes advantage of the fact that the OpenID server publishes its metadata to a well-known url:

This specification defines a mechanism for an OpenID Connect Relying Party to discover the End-User’s OpenID Provider and obtain information needed to interact with it, including its OAuth 2.0 endpoint locations.

https://openid.net/specs/openid-connect-discovery-1_0.html

In order to find the correct endpoint for your Keycloak realm, select the OpenID Endpoint Configuration option in the realm settings:

realm settings with configuration endpoints

In other words, the http://localhost:8024/auth/realms/keep-growing/.well-known/openid-configuration url contains the data required by the discovery mechanism to identify all available authorization schemes:

openid configuration in Keycloak

Configuration class

Let’s look at the example configuration documented in Swagger:

The config for this security scheme is very short because all necessary information will be automatically acquired form the OpenID configuration endpoint:

As a result, I will see all the available authorizations in my Swagger UI:

Swagger UI secured with OpenID Connect Discovery for Keycloak

Swagger authorization with bearer token

The example implementation is available in the spring-boot-swagger-ui-keycloak repository.

What if we already have access tokens from Keycloak? We can configure Swagger UI to allow us to provide only the bearer token value. Remember to provide the recommended security features for this authorization approach:

Similarly to Basic authentication, Bearer authentication should only be used over HTTPS (SSL).

https://swagger.io/docs/specification/authentication/bearer-authentication/

Configuration class

Let’s look at the example configuration documented in Swagger:

We’re going to create the security scheme with the http type and bearer scheme. The bearerFormat field is optional and mostly used for documentation purposes. You can see my Java configuration below:

As a result, I will see the Bearer Authorization in my Swagger UI:

Bearer authorization in Swagger UI

Make sure that the token contains user roles that your API requires (realm_access or resource_access in the screenshot below):

bearer token containing user realm roles

Why not other flows

Both implicit and password flows increase security risks and are therefore deprecated:

Please note that as of 2020, the implicit flow is about to be deprecated by OAuth 2.0 Security Best Current Practice. Recommended for most use case is Authorization Code Grant flow with PKCE.

https://spec.openapis.org/oas/latest.html#security-scheme-object

Because the client application has to collect the user’s password and send it to the authorization server, it is not recommended that this grant [password] be used at all anymore.

https://oauth.net/2/grant-types/password/

In addition, you can find more information in the Why not other flows section of the Kecloak in Docker #7 – How to authorize requests via Postman article.

Troubleshooting

What to check when API calls don’t work as planned?

The “Available authorizations” list is empty

An empty list of Available authorizations means that Swagger was unable to retrieve configuration from the OpenID server. You can debug the request responsible for loading Swagger UI in the browser:

xsrf header blocks Swagger from open id discovery in Keycloak

This failure was due to the XSRF header attached to the request. If you are using Springdoc with csrf protection enabled, be sure to update the library to at least version 1.6.6. I described this problem in the Is there a way to authorize users using OpenID Connect Discovery when POST endpoints require CSRF protection? issue.

CORS Error

No Access-Control-Allow-Origin header is present on the requested resource” is an example CORS error that may appear in your browser if the Web Origins field is misconfigured in the Keycloak client:

Make sure to configure the Keycloak client to accept connections from the Swagger endpoint as shown in the following screenshot:

web origin in keycloak config

Another reason for this error is missing authorization data. You should see a lock icon next to a secured endpoint:

api endpoint in Swager secured properly

Furthermore, the request should contain a Bearer Token that you can see in the curl window:

authorization token in Swagger UI curl details window

If the endpoints are not secured, make sure that the proper scheme is provided as a SecurityRequirement:

More on how to authorize requests from Swagger UI in Keycloak

Photo by Yan Krukov from Pexels

Leave a Reply

Your email address will not be published.