[Keycloak] Invalid parameter : redirect_uri 에러

cielo ru·2024년 6월 7일
0

Keycloak

목록 보기
4/6
post-thumbnail

➰ 서론

스프링 부트와 Keycloak 을 연동하며 Redirect uri 에러를 한번도 마주하지 않은 사람은 없을 것이다.

필자는 대부분의 에러가 redircet_uri 에러였고, 어떻게 해결했는지 적어보려 한다.
당시에는 알려진 정보도 없고 버전이 바뀐지 얼마 안되었기 때문에 해결하기 더 어려웠던 것 같다.(2023.04 기준)
(이제는 저 화면들만 봐도 지긋지긋하다..)

➰ 이슈

대부분 redirect_uri가 잘못 설정되어 로그인 및 인증이 제대로 동작하지 않았다.

redirect_uri 에러에도 종류가 여러가지가 있다.

  1. 처음 로그인 화면을 띄울때 발생하는 redirect_uri 에러이다.

  2. 아이디와 비밀번호를 입력하고 로그인을 시도하면 발생하는 redirect_uri 에러이다.

  3. Google 또는 Gihub을 이용한 OAuth 로그인 시 발생하는 redirect_uri 에러이다.

➰ 원인

  1. Keycloak 클라이언트 설정에서 정의한 redirect_uri와 실제 애플리케이션에서 사용하는 redirect_uri가 일치하지 않음
  1. Spring Boot 애플리케이션의 설정에서 redirect_uri가 잘못 설정되어 있음
  1. 로그인 후 리다이렉트 될 키클락 클라이언트 uri을 redirect_uri에 추가해주지 않음
  1. Valid Redirect URI 잘못 설정되어 있음

여기서 키클락 클라이언트란 80 서버에서 동작하는 키클락을 실행시키는 springboot 이다.(헷갈리지 말것 **)
8080 서버에서 동작하는 것이 키클락 서버이다.

➰ 흐름 정리

1. Gateway에서 user-service의 /login 호출 

2. 키클락 서버의 로그인 페이지로 리다이렉트 

3. 로그인 성공 시 키클락 클라이언트의 /auth 경로로 리다이렉트 

4. 인증 성공 시 토큰을 쿠키에 담아서 프론트엔드로 리다이렉트
  • /auth 는 OAuth 2.0 인증을 처리하고, 인증 후 프론트엔드나 다른 서비스로 리다이렉션하는 역할을 한다.

📍 원인 1번의 경우

Keycloak 17 이전 버전

Keycloak 17 이전 버전에서는 전통적인 WildFly 기반 배포 모델을 사용했다.

  • 기본 로그인 인증 엔드포인트
http://localhost:8080/auth/realms/{realm-name}/protocol/openid-connect/auth?response_type=code&client_id=admin-client&redirect_uri={redirect_uri}&scope=openid&nonce=asb3
  • 토큰 엔드포인트 URL 패턴:
http://localhost:8080/auth/realms/{realm-name}/protocol/openid-connect/token
  • 키클락 기본 리다이렉트 URI(로그인 성공 후 키클락 페이지로 리다이렉트 됨)
http://localhost:8080/login/oauth2/code/keycloak

그래서 다음과 같은 URI 패턴을 사용했다.

Keycloak 17 이후 버전

Keycloak 17 버전 이후부터는 Quarkus 기반의 새로운 배포 모델을 도입했다.

이로 인해 URL 패턴에 일부 변경 사항이 발생했다.

  • 기본 로그인 인증 엔드포인트
http://localhost:8080/realms/{realm-name}/protocol/openid-connect/auth?response_type=code&client_id=admin-client&redirect_uri={redirect_uri}&scope=openid&nonce=asb3
  • 토큰 엔드포인트 URL 패턴:
http://localhost:8080/realms/{realm-name}/protocol/openid-connect/token
  • 키클락 기본 리다이렉트 URI(로그인 성공 후 키클락 페이지로 리다이렉트 됨)
http://localhost:8080/login/oauth2/code/keycloak


17 이후 버전부터는 /auth 라는 경로가 사라진 것을 확인할 수 있다.

경로가 변경된 것을 모르고 /auth 경로를 포함해서 계속 리다이렉트 시켰고, 로그인 페이지가 뜨지 않았다. 에러 메시지도 redirect_uri 딱 하나 줘서 며칠씩 해결하느라 고생했던 기억이 있다.

따라서 키클락 17 이후 버전을 사용한다면 변경된 URL 패턴을 사용해야 한다!


➰ 해결

➿ 이슈 1번 해결방법

이슈 1번의 경우, 로그인 화면을 호출할때 변경된 URL 패턴을 적용시켜주어 해결하였다.

=> /auth 제외

LoginController

  • /login에서는 /login 을 호출했을 때 키클락 서버의 로그인 페이지로 리다이렉트한다.
    @GetMapping("/login")
    public void login(Principal principal, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        response.sendRedirect(keycloakServerUrl
                + "/realms/master/protocol/openid-connect/auth?response_type=code&client_id=admin-client&redirect_uri="
                + keycloakClientUrl + "/auth&scope=openid&nonce=asb3"
        );
    }
  • 여기서 redirect_uri은 로그인 성공 후 springboot에서 인증이 진행 될 경로를 지정한다.

application.yml

keycloak:
  realm: master
  client-url: http://localhost
  server-url: http://localhost:8080

➿ 이슈 2번 해결방법

아이디와 비밀번호를 입력하고 로그인을 시도하면 발생하는 redirect_uri는 Valid Redirect URL 주소와 스프링 부트에서 redirect_uri를 수정해야 한다.

  1. Keycloak 관리자 페이지 접속 - Client - Valid Redirect URI
http://localhost:80/*
http://localhost:8080/login/oauth2/code/keycloak
  1. LoginController에서 리다이렉트 되는 URL에서 로그인 성공 후 리다이렉트될 URL을 설정하기 위해 ?redirect_url 을 아래와 같이 설정
keycloakServerUrl
                + "/realms/master/protocol/openid-connect/auth?response_type=code&client_id=admin-client&redirect_uri="
                + keycloakClientUrl + "/auth&scope=openid&nonce=asb3


=> 이렇게 하면 로그인 성공 시 위에서 설정한 localhost:80/auth 경로로 리다이렉트 되고, 인증 코드를 사용하여 액세스 토큰을 요청하고, 토큰을 쿠키에 저장한 후, 프론트엔드로 리다이렉션한다.

➿ 이슈 3번 해결방법

OAuth Login 시에도 마찬가지로 로그인 성공하면 인증 경로(http://localhost:80/auth)로 리다이렉트 되어야 했다. 이와 관련된 설정을 해주지 않아 인증 오류 혹은 리다이렉트 에러가 났다.

Google
Google Cloud Platform 접속 - API 및 서비스 - 사용자 인증 정보 - 생성한 프로젝트 선택

  • 지워진 부분은 배포된 도메인 주소이다.
  • 승인된 JavaScript 원본에 클라이언트 Origin을 추가한다.
http://localhost:80
  • 승인된 리다이렉션 URI에 리다이렉션 될 클라이언트 URL를 추가한다.

**그 외의 Github 등 Identity provider도 동일하게 진행한다.

➿ 그래도 에러가 난다면?

application-local.yml

server:
  port: 80

spring:
  application:
    name: SSO-service
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://localhost:8080/realms/master
          jwk-set-uri: ${spring.security.oauth2.resourceserver.jwt.issuer-uri}/protocol/openid-connect/certs
      client:
        provider:
          github:
            authorization-uri: https://github.com/login/oauth/authorize
            token-uri: https://github.com/login/oauth/access_token
            user-info-uri: https://api.github.com/user
            user-name-attribute: login
          keycloak:
            issuer-uri: http://localhost:8080/realms/master
            user-name-attribute: preferred_username
        registration:
          google:
            client-id: ----
            client-secret: ---
            scope:
              - email
              - profile
            redirect-uri: "http://localhost:8080/realms/master/broker/google/endpoint"
            client-name: Google
            provider: google
          keycloak:
            provider: keycloak
            client-id: SSOService
            client-secret: ---
            scope: openid
            authorization-grant-type: authorization_code
            redirect-uri: '{baseUrl}/login/oauth2/code/keycloak'
          github:
            client-id: --
            client-secret: ---
            authorization-grant-type: authorization_code
            redirect-uri: "http://localhost:8080/realms/master/broker/github/endpoint"
            client-name: GitHub
            provider: github


jwt:
  auth:
    converter:
      resource-id: SSOService
      principal-attribute: preferred_username

keycloak:
  realm: master
  client-url: http://localhost
  server-url: http://localhost:8080
  auth-server-url: http://localhost:8080/auth
  ssl-required: external
  resource: admin-client
  credentials:
    secret: admin-secret
  use-resource-role-mappings: true
  bearer-only: true
  logout-url: http://localhost:8080/realms/master/protocol/openid-connect/logout
  logout-redirect-url: http://localhost:8080/realms/master/protocol/openid-connect/logout?post_logout_redirect_uri=http://socoa.online/&client_id=admin-client

mykeycloak:
  client:
    id: admin-cli
  admin:
    name: --
    password: ---

socoa:
  domain: localhost
  gateway:
    url: http://localhost:8000

코드를 참고하여 잘못된 부분은 없는지 확인하길 바란다.


➰ 참고

profile
Cloud Engineer & BackEnd Developer

0개의 댓글