일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 기술적 채무
- 그거봤어?
- 와썹맨
- Dynamic Programmin
- 프로그래머스
- mysql #numa #swap #memory
- Unique Paths
- Python
- LongestPalindromicSubstring
- 리트코드
- 블린이
- 알고리즘
- minimum path sum
- 아마조니언
- 독후감
- 동적 프로그래밍
- Envoy
- 삼성역량테스트
- 파이썬
- 나는 아마존에서 미래를 다녔다
- 리스트의 리스트
- leetcode
- 규칙없음
- No Rules Rules
- 트리
- technical debt
- BFS
- 김태강
- 삼성인 아마조니언 되다
- list of list
- Today
- Total
개발자가 되고 싶은 준개발자
[OAuth2 인증] OAuth2 인증 과정에서 Redirect URL 확인 방법 (로컬 환경에서 주의 사항) 본문
이번 포스팅은 nginx가 구성되어 있는 개발/상용에서는 잘 되던 인증이 nginx가 없는 로컬에서는 왜 안 되었는지 원인을 정리하고 기록하는 포스팅이다...
인증은 볼때마다 새롭다...ㅎㅎ
OAuth2 인증은 주로 클라이언트 애플리케이션이 리소스 소유자(사용자)의 승인을 받아 리소스 서버의 데이터에 접근할 수 있도록 허가를 요청하는 프로세스이다.
- Authorization Request: 클라이언트가 인증 서버에 권한 부여 요청을 보냄.
- User Authentication: 사용자가 인증을 통해 권한을 승인함.
- Authorization Code Issuance: 인증 서버가 클라이언트에게 Authorization Code를 발급함.
- Token Exchange: 클라이언트가 Authorization Code를 사용하여 액세스 토큰을 요청함.
- Token Usage: 액세스 토큰을 사용하여 리소스 서버에 요청을 보냄.
Redirect URL 확인 로직
Redirect URL은 인증 서버가 인증 결과를 클라이언트 애플리케이션에 전달할 때 사용하는 주소이다. 인증 서버는 이를 사용해서 요청이 올바른 애플리케이션으로 돌아가도록 보장한다.
주요 구현 과정:
- Redirect URL 등록:
- 클라이언트 애플리케이션은 OAuth2 인증 서버에 사전 등록된 Redirect URL을 제공.
- 이는 인증 서버가 신뢰할 수 있는 URL로만 응답을 전송하게 보장.
- Authorization Request에서의 Redirect URL:
- 클라이언트가 인증 요청을 보낼 때 redirect_uri 파라미터를 포함할 수 있음.
- 이 값이 등록된 URL과 일치하는지 인증 서버가 검증.
- 검증 로직:
- 인증 서버는 아래와 같은 방식으로 검증합니다:
- 정확한 일치: 클라이언트가 요청한 redirect_uri가 사전에 등록된 URL과 완벽히 일치하는지 확인.
- 검증이 실패하면 인증 요청은 거부
- 인증 서버는 아래와 같은 방식으로 검증합니다:
- 코드 전달:
- 검증이 성공하면 인증 서버는 사용자 인증 완료 후 Authorization Code를 클라이언트의 redirect_uri로 전송.
상용 환경에서는 nginx를 통해 프론트가 3000번, 백이 8080 포트를 사용할때 특정 포트로 들어오는 요청을 알아서 보내주는데,
로컬의 경우에는 이런 nginx가 없다.
이 경우에 front에서 login 요청이 오면 인증서버를 거쳐서 백앤드로 리다이렉트 url을 입력해 보내는데,
리다이렉트 URL에 포트 번호가 달라지면서 로컬에서만 인증을 실패했다...!!
(원인을 찾는게 너무 힘들었는데, 일단 인증서버에서는 로깅이 잘 안되어 요청이 success로 떨어지나, 백에서 인증이 실패했다...ㅎ)
원인은
OAuth2 인증 서버는 redirect_uri를 검증할 때 프로토콜, 도메인, 포트가 정확히 일치해야 한다다. 이로 인해 인증 서버가 요청을 거부할 수 있어서였다.
- 프론트엔드는 http://localhost:3000에서 실행되고, 인증 서버는 redirect_uri로 http://localhost:8080/callback 등을 사용하도록 설정되어 있다면, 인증 서버는 localhost:3000에서 온 요청을 거부할 수 있다.
- 인증 서버는 redirect_uri와 요청된 URI를 정확히 일치시키므로, 포트 번호가 다르면 인증 오류가 발생할 수 있다.
이를 해결하려면,
코드에서 프론트와 백의 port 불일치를 처리하는 로직을 로컬에만 추가해야 한다!
프론트엔드에서 리다이렉트 URI 수정
- 프론트엔드에서 인증 요청을 보낼 때 리다이렉트 URL을 3000번 포트로 설정하지 않고, 백엔드 8080번 포트로 리다이렉트하도록 설정.
- 예를 들어, 인증 요청 시 리다이렉트 URI를 http://localhost:8080/callback으로 설정하면, 인증 서버는 이를 받아들일 것.
// 백엔드에서 인증 서버로 리다이렉트 요청을 보낼 때
const redirectUri = 'http://localhost:8080/callback'; // 백엔드 포트로 설정
const authUrl = `https://auth-server.com/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=${redirectUri}&response_type=code&scope=YOUR_SCOPES`;
내 경우에는 redirectUri가 /callback으로만 되어 있어서
브라우저는 현재 URL을 기준으로 해당 경로를 자동으로 붙여서 리다이렉트를 처리했다.
그래서 프론트엔드가 localhost:3000에서 실행되고 있으니, redirect_uri가 /callback으로 설정되면 **http://localhost:3000/callback**으로 리다이렉트된 것이다!! (뚜둥!!)
왜 그렇게 되냐면??
- 브라우저는 리다이렉트 URL을 상대 경로로 받으면, 현재 페이지 URL(프론트엔드의 주소)을 기준으로 경로를 자동으로 붙인다.
- 이때, 상대 경로(/callback)는 현재 페이지(즉, http://localhost:3000)를 기준으로 해석되어 http://localhost:3000/callback으로 리다이렉트된다.
그러면 nginx가 어떤 역할을 하길래 개발/상용에서는 위 현상이 안 일어난 거지??
Nginx는 클라이언트에서 들어오는 요청을 프론트엔드(3000번 포트)와 백엔드(8080번 포트)로 라우팅하도록 해놓아서
클라이언트가 http://yourdomain.com으로 요청을 보내면, Nginx는 이를 프론트엔드 서버(3000번 포트)로 전달하고, API 요청은 백엔드 서버(8080번 포트)로 전달하도록 세팅해 놓았다.
redirect_uri = /callback이라면, 인증 서버는 이를 현재 도메인과 포트를 기준으로 리다이렉트를 처리한다.
클라이언트가 http://yourdomain.com에서 요청을 시작했으면, 리다이렉트 URI는 **http://yourdomain.com/callback**로 해석된다.
Nginx가 리버스 프록시로 동작하면서, 프론트엔드가 3000번 포트에서 요청을 받더라도, 클라이언트는 Nginx가 처리하는 도메인을 기준으로 백엔드로 리다이렉트된다.
Nginx는 클라이언트 요청을 받아 적절한 포트로 전달하는 역할을 하므로, 인증 서버는 Nginx의 도메인과 포트를 기반으로 리다이렉트를 처리하게 된다.
한 마디로 정리해 보면.
Nginx는 도메인 기반으로 요청을 처리하며, 실제로 요청이 어느 포트로 가야 할지에 대한 정보를 내부적으로 관리하고 라우팅한다. 인증 서버는 도메인까지만 인식하고, Nginx가 실제로 해당 요청을 어떤 포트로 보낼지 결정해서 로컬에서 생겼던 문제가 상용 환경에서는 안 생겼던 것이다...!!!!