Compare commits

..
6 changed files with 101 additions and 0 deletions
@@ -0,0 +1,6 @@
# Keycloak receives HTTP only from the trusted reverse proxy.
KC_HTTP_ENABLED=true
KC_PROXY_HEADERS=xforwarded
KC_HOSTNAME=https://auth.example.test
KC_HOSTNAME_STRICT=true
+14
View File
@@ -0,0 +1,14 @@
server {
listen 8080;
server_name auth.example.test;
location / {
proxy_pass http://keycloak:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
+24
View File
@@ -0,0 +1,24 @@
# Google redirect URI policy
Google에 등록하는 redirect URI는 애플리케이션 SPA callback이 아니라 Keycloak
broker endpoint다.
```text
https://auth.example.test/realms/keycloak-patterns/broker/google/endpoint
```
규칙:
- production URI는 HTTPS와 고정된 public Keycloak origin을 사용한다.
- wildcard, path prefix, 임시 tunnel hostname을 production OAuth client에
등록하지 않는다.
- 개발·스테이징·운영은 Google OAuth client를 분리한다.
- reverse proxy가 있더라도 Google이 보는 URI와 Keycloak이 생성하는 URI가
byte-for-byte 같아야 한다.
- `configure-google-idp.sh`가 출력하는 URI를 Google Console의 Authorized
redirect URI와 대조한다.
```sh
PUBLIC_KEYCLOAK_URL=https://auth.example.test \
./scripts/verify-google-redirect-uri-policy.sh
```
+15
View File
@@ -0,0 +1,15 @@
# Reverse proxy headers
TLS를 reverse proxy에서 종료하면 Keycloak은 브라우저가 사용한 외부 origin을
정확히 알아야 한다. 배포 예제는 다음 계약을 함께 적용한다.
- nginx는 `Host`, `X-Forwarded-Host`, `X-Forwarded-Port`,
`X-Forwarded-Proto`, `X-Forwarded-For`를 덮어쓴다.
- Keycloak은 `KC_PROXY_HEADERS=xforwarded`로 그 헤더 형식을 명시한다.
- `KC_HOSTNAME`은 외부 HTTPS URL로 고정하고 strict hostname 검증을 켠다.
- Keycloak의 8080 포트는 public으로 publish하지 않고 proxy network에서만
접근시킨다. 신뢰되지 않은 클라이언트가 forwarded header를 직접 넣을 수
있으면 안 된다.
`scripts/verify-reverse-proxy-headers.sh`는 양쪽 설정의 짝과 nginx 구문을
검증한다.
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env sh
set -eu
realm="${KEYCLOAK_REALM:-keycloak-patterns}"
public_keycloak_url="${PUBLIC_KEYCLOAK_URL:-https://auth.example.test}"
expected="$public_keycloak_url/realms/$realm/broker/google/endpoint"
case "$public_keycloak_url" in
https://*) ;;
*)
echo "PUBLIC_KEYCLOAK_URL must use https outside the local mock environment" >&2
exit 1
;;
esac
case "$public_keycloak_url" in
*\** | */)
echo "PUBLIC_KEYCLOAK_URL must be an exact origin without wildcard/trailing slash" >&2
exit 1
;;
esac
test "$expected" = "https://auth.example.test/realms/keycloak-patterns/broker/google/endpoint"
echo "Google redirect URI policy verified: $expected"
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env sh
set -eu
config=deploy/reverse-proxy/nginx-keycloak.conf
env_file=deploy/reverse-proxy/keycloak.env.example
grep -q 'proxy_set_header X-Forwarded-Host' "$config"
grep -q 'proxy_set_header X-Forwarded-Port 443' "$config"
grep -q 'proxy_set_header X-Forwarded-Proto https' "$config"
grep -q '^KC_PROXY_HEADERS=xforwarded$' "$env_file"
grep -q '^KC_HOSTNAME=https://' "$env_file"
docker run --rm \
--add-host keycloak:127.0.0.1 \
-v "$PWD/$config:/etc/nginx/conf.d/default.conf:ro" \
nginx:1.29-alpine nginx -t
echo "Reverse-proxy header and Keycloak hostname contracts verified"