콘텐츠로 이동
Study NoteKeycloak 실습

Client를 연결하고 로그인 확인하기

결론부터
정확한 client와 callback 계약을 먼저 적용하고, redirect 하나를 깨뜨렸다 복구하면 앱 로그인에서 Keycloak과 앱의 책임 경계가 보인다.

guided base에는 realm과 local-user만 있고 app-a client나 앱 service는 없다. 공개 JSON을 읽고 적용해야 앱이 Authorization Code를 받아 자기 session을 만들 수 있다. 앱 A는 브라우저에서 도는 SPA가 아니라 Node server 앱이라 로그인에는 사용자 브라우저·앱 A server·Keycloak 셋이 참여한다. 이 흐름과 각 값이 막는 공격은 OAuth 2.0과 OIDC 로그인의 다이어그램과 보호 장치 표가 정본이다.

이 장에서 처음 나오는 말2개
redirect URI
Keycloak이 authorization code를 돌려보내도록 client에 미리 허용한 정확한 callback 주소.
PKCEProof Key for Code Exchange
로그인 시작 시 만든 verifier와 challenge를 code 교환에 묶는 보호 장치.
  1. ./scripts/status.sh에서 mode=guided stage=base와 기반 세 service를 확인한다.

  2. app-a.json을 읽는다. confidential client이고 Standard Flow만 켜며 callback은 /callback 하나, PKCE는 S256이다.

  3. 설정을 적용하고 실제 로그인 흐름을 검사한다.

    터미널 창
    ./scripts/apply.sh app-a
    ./scripts/verify.sh app-a
  4. Admin Console의 Clients → app-a → Settings에서 Client authentication, Standard flow, Valid redirect URIs를 공개 JSON과 대조한다.

  5. 브라우저에서 앱 A https://app-a.keycloak.test:30081/를 열고 Sign in with Keycloak을 누른다. Keycloak 로그인 화면에 local-user와 아래 파일의 비밀번호를 넣는다.

    터미널 창
    cat .state/secrets/keycloak-local-user-password # labs/keycloak에서

    로그인 뒤 앱 A 화면에 token claims·User API·Admin API 링크가 보이고, https://app-a.keycloak.test:30081/session이 authenticated: true와 username: local-user를 반환하면 성공이다.

검사 container는 브라우저 역할로 로그인을 두 번 해 본다. 정상 password는 callback과 앱 session까지 성공해야 하고, 오답은 callback에 도달하지 못하고 로그인 폼으로 돌아와야 한다. 시도마다 새 cookie jar — 브라우저의 cookie 보관함으로, private 창을 새로 여는 것과 같다 — 로 시작해서 이전 로그인의 Keycloak session이 비밀번호 검사를 건너뛰게 하지 않는다. 성공 경로에서는 authorization 요청의 Code·PKCE S256·state·nonce·redirect URI가 공개 JSON·앱 코드와 맞는지 본다. code를 token으로 바꾸는 쪽은 앱 A server라서 client secret은 브라우저 역할인 검사 container에 아예 전달되지 않는다.

  1. keycloak/clients/app-a.json의 redirectUris에서 /callback을 /wrong-callback으로 바꾼다.
  2. ./scripts/apply.sh app-a를 다시 실행한다. 앱 코드는 여전히 원래 /callback을 요청한다.
  3. 새 private window에서 앱 A /login을 열고 Keycloak이 등록되지 않은 redirect를 거부하는지 본다. 기존 앱·Keycloak session을 결과로 재사용하지 않는다.
  4. JSON을 정확한 https://app-a.keycloak.test:30081/callback으로 되돌리고 다시 apply·verify한다.
터미널 창
./scripts/apply.sh app-a
./scripts/verify.sh app-a

wildcard를 넓히거나 HTTPS 검증을 끄는 것은 복구가 아니다. 설정 원본과 앱 callback 계약을 다시 맞춘다.

server.mjs의 /login, /callback, /session만 이어 읽는다. 첫 route가 transaction을 만들고, callback이 code를 교환해 access token을 앱 session에 넣으며, session endpoint는 token 원문 없이 로그인 결과만 보여 준다.

  • client의 flow·PKCE·redirect는 앱이 보내는 authorization request와 정확히 맞아야 한다.
  • app-a를 적용하기 전에는 client와 앱 service가 없고, 적용 성공 뒤에만 stage가 올라간다.
  • redirect 실패는 wildcard나 TLS 우회가 아니라 공개 JSON을 원래 callback으로 복구해 해결한다.

다음은 두 앱 SSO와 API 권한 실습에서 별도 client의 SSO와 API 인가를 붙인다.