To make a microservice (ms-A) authenticated and authorized to make a request to another microservice (ms-B) secured with kc you have to properly configure spring security configuration on ms-B.
You can choose to had one or more authorities to a specific path (code 1) or leave all as is and authorize only your endpoint (code 2)
Code 1 - Spring Security
.antMatchers("/api/**").hasAuthority(“myRole-admin”)
Code 2
Spring Security:
.antMatchers("/api/**").authenticated()
Rest Controller:
@PreAuthorize(“hasAuthority(‘myRole-admin’)”)
Once ms-B is configured you have to do just a couple of changes into ms-A
First of all import these maven dependencies:
<dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-admin-client</artifactId> <version>${keycloak-admin-client.version}</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> <version>${resteasy-client.version}</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jackson2-provider</artifactId> <version>${resteasy-client.version}</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-multipart-provider</artifactId> <version>${resteasy-client.version}</version> </dependency>
Tested dependencies version:
<keycloak-admin-client.version>6.0.1</keycloak-admin-client.version>
<resteasy-client.version>3.6.3.Final</resteasy-client.version>
Then before call the endpoint of ms-B you must create the keycloak object authenticated on ms-A’s client, retrieve the access token and it to request headers
Keycloak keycloak = KeycloakBuilder.builder()
.serverUrl("https://my-keycloak-server/auth")
.realm("my-keycloak-realm")
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.clientId("kc-ms-A-client-id")
.clientSecret("kc-ms-A-client-secret")
.build();
AccessTokenResponse accessToken = keycloak.tokenManager().getAccessToken();
once you have an access token you can add it to request headers for example using basic RestTemplate:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set(“Authorization”, "Bearer " + accessToken.getToken());
HttpEntity httpEntity = new HttpEntity(headers);ResponseEntity response = restTemplate.exchange(
“http://ms-B-endpoint/”,
HttpMethod.GET,
httpEntity,
String.class
);
The last important thing you have to do is assign the role of ms-B client to ms-A client Service Account on Keycloak
- Open keycloak
- Go to “Clients” and select ms-A client
- Click on tab “Service Account Roles”
- Choose from “Client Roles” list the ms-B client
- Add the needed rolesPreformatted text