IT/스프링부트

Keycloak 인증이 필요한 Springboot API 를 Swagger 에서 사용해보기

캥거루 2022. 12. 20. 09:45
728x90
반응형

사용환경

• Keycloak 인증서버
• Keycloak 의 OIDC 인증을 사용하는 Springboot 서버 (keycloak-spring-security-adapter 사용)
• Springboot 서버의 API 를 제공하는 Swagger3 UI
• 모두 하나의 서버(도메인은 example.net 으로 지칭)에서 Keycloak(8280포트) 과 Swagger(8180포트) 는 도커 사용, Springboot(9080포트) 서버는 호스트에서 실행

목표

구현하고자 했던 목표는 Springboot 서버에서 Keycloak 인증이 필요한 API 를 Swagger 에서 API 를 호출 해보고자 하는것이다.
예를들면 "내 정보 조회" 라는 API 는 로그인을 하여야 내가 누군지 알 수 있다.
하지만 이 로그인은 다른 SSO 서버인 Keycloak 에서 제공하는 로그인이며,
이 API 를 Swagger 에서 호출하려면 Keycloak 로그인을 하여야 API 를 호출할 수 있다.
각각의 서버들에 대한 구현은 제외하고, 위 목표를 구현하는 방법에 대해서만 작성한다.

Keycloak

Keycloak 에서 OIDC 인증을 사용할 클라이언트를 생성해준다.
Keycloak 을 다른 서버에서 사용하기 위한 설정 또는 데이터는 아래와 같다.
• Clients > Settings > Access Type: confidential
• Clients > Settings > Valid Redirect URIs: http://example.net:8180/*
• Clients > Settings > Web Origins: http://example.net:8180
• Realm Settings > General > Endpoints > OpenID Endpoint Configuration
• Clients > Credentials > Secret
Valid Redirect URIs 는 로그인 이후 Redirect 할 페이지에 대한 URI 를 설정하며, 도메인과 더불어 와일드카드(*)를 함께 사용할 수 있다.
Web Origins 는 와일드카드 단독 사용 혹은 URI 를 정확하게 입력하여야 한다.

Swagger

docker-compose.yml 파일

version: '3.3'  

services:  
  swagger-ui:  
    image: swaggerapi/swagger-ui:v3.43.0  
    ports:  
      - 8180:8080  
    volumes:  
      - /home/docker/docker-stack/swagger3/conf/:/home/swagger3/  
    environment:  
      SWAGGER_JSON: /home/swagger3/test_oas3.yaml  
      BASE_URL: /swagger-ui  
      OAUTH2_REDIRECT_URL: "http://example.net:8180/swagger-ui/oauth2-redirect.html"  
    deploy:  
      mode: replicated  
      replicas: 1
  swagger-editor:  
    image: swaggerapi/swagger-editor:v3.15.6  
    ports:  
      - 8181:8080  
    environment:  
      BASE_URL: /swagger-editor  
      OAUTH2_REDIRECT_URL: "http://example.net:8181/swagger-editor/oauth2-redirect.html"  
    deploy:  
      mode: replicated  
      replicas: 1

test_oas3.yaml 파일 (인증 관련된 코드만 삽입)

openIdConnectUrl 에 Keycloak 의 OpenID Endpoint Configuration 의 url 을 입력하였다.

paths:  
  /auth/getUserInfo:  
    post:  
      tags:  
        - auth  
      summary: 사용자정보 조회  
      security:  
        - openId:  
          - admin  
      responses:  
        200:  
components:  
  securitySchemes:  
    openId: # <--- Arbitrary name for the security scheme. Used to refer to it from elsewhere.  
      type: openIdConnect  
      openIdConnectUrl: http://example.net:8280/auth/realms/master/.well-known/openid-configuration
security:  
  - openId:  
    - admin

Springboot API 서버

의존성

implementation 'org.springframework.boot:spring-boot-starter-security'
implementation group: 'org.keycloak', name: 'keycloak-spring-security-adapter', version: '13.0.1'

Spring security 설정

WebMvcConfigurer 의 CORS 설정 외에도 스프링 시큐리티에 의한 CORS 설정도 추가로 필요하다.

@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
    // 인증관리 객체에 소유권한 프로바이더 추가
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        // GrantedAuthoritesMapper 에서 오는 Role 을 Spring Security 가 인식할 수 있도록 Role Mapping 을 지원
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        // SimpleAutorityMapper 는 "ROLE_" 을 삽입 및 대문자로 변환하는데 사용 (Spring Security Core 모듈의 일부)
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }
    // 세션인증전략 생성
    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }
    // 키클락 설정 리졸버 생성
    @Bean
    public KeycloakConfigResolver keycloakConfigResolver() {
        return new KeycloakConfigResolver() {
            private KeycloakDeployment keycloakDeployment;
            @Override
            public KeycloakDeployment resolve(HttpFacade.Request facade) {
                if (keycloakDeployment = null) {
                    return keycloakDeployment;
                }
                InputStream configInputStream = getClass().getResourceAsStream("/keycloak.json");
                return KeycloakDeploymentBuilder.build(configInputStream);
            }
        };
    }
    // 시큐리티 설정
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
            .cors() // spring security cors
                .configurationSource(request ->
                {
                    CorsConfiguration cors = new CorsConfiguration();
                    cors.setAllowedMethods(
                            Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
                    cors.applyPermitDefaultValues();
                    return cors;
                });
    }
}

keycloak.json

{"realm": "master", "auth-server-url": "http://example.net:8280/auth", "ssl-required": "external", "resource": "springboot-test-app", "credentials": { "secret": "해당 keycloak client 의 secret 키 입력" }, "confidential-port": 0}

728x90
반응형

'IT > 스프링부트' 카테고리의 다른 글

Forward, Redirect 간단하게 정리  (0) 2021.07.15
SpringSecurity 와 Keycloak 비교  (0) 2021.05.11