기업 인증 연동 · SSO 연동 실전 · 실습
OIDC 인가 코드 흐름을 손으로 재현하기
목표
실습용 OIDC 제공자를 상대로 인가 코드 흐름을 직접 손으로 수행하고,
ID 토큰을 디코드·서명 검증하고, 검증 체크리스트를 작성할 수 있게 됩니다.
왜 중요한가
OIDC 를 라이브러리로만 써 본 사람은 장애가 났을 때 어디를 봐야 할지 모릅니다.redirect_uri 불일치, state 미검증, nonce 누락, 만료된 코드 재사용 —
전부 흐름을 눈으로 본 적이 있어야 감이 옵니다.
특히 ID 토큰은 base64 라 누구나 디코딩할 수 있다는 사실을 손으로 확인하는 것이
중요합니다. 페이로드를 고쳐도 서명 검증을 안 하면 그대로 통과한다는 것을
직접 재현해 보면, 왜 alg 를 고정해야 하는지가 몸으로 남습니다.
단계
1. 실습용 IdP 를 기동합니다.python3 /opt/lab/fixtures/auth/oidc/idp.py 9000 (백그라운드)
discovery 문서를 받아 /root/oidc/discovery.json 에 저장합니다.
(http://127.0.0.1:9000/.well-known/openid-configuration)issuer, authorization_endpoint, token_endpoint, jwks_uri 가 있어야 합니다.
2. /root/oidc/auth-url.txt 에 authorization URL 한 줄을 적습니다.
필수 파라미터: response_type=code, client_id=labhub-web,redirect_uri=http://127.0.0.1:9100/callback,scope=openid profile email, state=<16자 이상>, nonce=<16자 이상>.
3. 그 URL 을 리다이렉트를 따라가지 않고 호출해 응답의 Location 헤더를/root/oidc/callback.txt 에 저장하고, 거기서 code 값만 뽑아/root/oidc/code.txt 에 저장합니다.
Location 의 state 는 2단계에서 보낸 값과 같아야 합니다.
4. 토큰 엔드포인트로 코드를 교환해 응답 JSON 전체를/root/oidc/token.json 에 저장합니다.client_id=labhub-web, client_secret=labhub-secret 을 함께 보냅니다.access_token, id_token, token_type 이 있어야 하고 token_type 은 Bearer 입니다.
5. id_token 의 페이로드를 디코드해 /root/oidc/claims.json 에 저장합니다.iss, aud, sub, exp, nonce 가 있어야 하고,aud 는 labhub-web, nonce 는 2단계에서 보낸 값과 같아야 합니다.
6. /root/oidc/verify.sh 를 만듭니다. 인자 두 개(ID토큰 공개키PEM)를 받아
서명이 유효하면 종료코드 0, 아니면 0 이 아닌 값으로 끝냅니다.
공개키는 /opt/lab/fixtures/auth/oidc/idp-public.pem 에 있습니다.
7. access_token 으로 userinfo 엔드포인트를 호출해/root/oidc/userinfo.json 에 저장합니다.sub 값이 5단계 claims.json 의 sub 와 같아야 합니다.
8. /root/oidc/checklist.csv 를 만듭니다. 첫 줄은 item,risk.서명, iss, aud, exp, nonce, alg 여섯 항목이 item 에 있어야 하고,risk 에는 그 항목을 검증하지 않으면 가능한 공격/사고를 10자 이상으로 적습니다.
참고
- 리다이렉트 안 따라가기:
curl -s -D - -o /dev/null "<URL>"후Location:줄 확인 - base64url 디코드:
-를+로,_를/로 바꾸고 패딩(=)을 채운 뒤base64 -d - 서명 검증: 서명 대상은
<헤더>.<페이로드>문자열, 알고리즘은 RS256(SHA-256) - 흔한 실수 1: 인가 코드를 두 번 쓰는 것. 일회용이라 두 번째는 실패합니다.
- 흔한 실수 2: base64url 을 그냥
base64 -d로 넘겨 오류가 나는 것. - 흔한 실수 3:
redirect_uri를 토큰 교환 때 authorization 때와 다르게 보내는 것.
openssl dgst -sha256 -verify <공개키> -signature <서명파일> <데이터파일>
두 값이 정확히 같아야 합니다.
단계 8개
- IdP 기동과 discovery 문서
- authorization URL 조립
- 인가 코드 수신
- 토큰 교환
- ID 토큰 페이로드 디코드
- 서명 검증 스크립트
- userinfo 호출
- ID 토큰 검증 체크리스트