TransWikia.com

Redirect to Keycloak login page only for specific endpoints by extending KeycloakConfigResolver

Stack Overflow Asked by Pavel Fadeev on February 18, 2021

I have two endpoints: /v1/host-service/auth and /v1/host-service/employee-profile. When a user is not authorized, I want to open Keycloak login page only for request which is sent to /v1/host-service/auth and get 401 for all other endpoints without redirection to login page.

For some reason I dont’t want to extend KeycloakWebSecurityConfigurerAdapter and trying to solve the problem using multitenancy with extended KeycloakConfigResolver and using and changing bearer-only property

So when I use followed configuration after successfull login I am always getting 401 from all endpoint except /v1/host-service/auth. I can confirm that I have JWT-token in my cookies. The only difference between followed json files is "bearer-only" property

redirect_to_login_page.json

{
  "realm": "myrealm",
  "resource": "platform",
  "auth-server-url": "http://keycloak:32400/auth",
  "bearer-only": false,
  "public-client": false,
  "credentials": {
    "secret": "b4e70446-f9b4-47ed-a4f2-804783ce06ee"
  },
  "token-store": "cookie"
}

401.json

{
  "realm": "myrealm",
  "resource": "platform",
  "auth-server-url": "http://keycloak:32400/auth",
  "bearer-only": true,
  "public-client": false,
  "credentials": {
    "secret": "b4e70446-f9b4-47ed-a4f2-804783ce06ee"
  },
  "token-store": "cookie"
}
import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
import org.keycloak.adapters.OIDCHttpFacade;
import org.springframework.context.annotation.Configuration;

import java.io.InputStream;

@Configuration
public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {

    @Override
    public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
        String configFileName;
        if (request.getRelativePath().contains("auth")) {
            configFileName = "/redirect_to_login_page.json";
        } else {
            configFileName = "/401.json";
        }
        InputStream is = getClass().getResourceAsStream(configFileName);
        return KeycloakDeploymentBuilder.build(is);
    }

}

My controller class


import org.keycloak.KeycloakPrincipal;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.representations.AccessToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(path = "/v1/host-service")
public class HostController {

    @GetMapping(path = "/auth")
    public void auth() {
    }

    @GetMapping("/employee-profile")
    public EmployeeProfileResponse getEmployeeProfile(KeycloakPrincipal<KeycloakSecurityContext> principal) {
        KeycloakSecurityContext context = principal.getKeycloakSecurityContext();
        AccessToken token = context.getToken();
        String fullName = token.getGivenName();
        return new EmployeeProfileResponse(fullName);
    }
}

Additionally if I don’t have this part in application.yml then all my endpoints are not secured.

keycloak:
  security-constraints:
    - auth-roles:
        - '**'
      security-collections:
        - patterns:
            - /*

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP