๐๐ป ์๋ก
NEO ํ ์ด ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ์์ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ฒ ๋์์ต๋๋ค.
์ธํฐ๋ท ์์ ๋ง์ ๊ธ์ ์ฝ๊ณ , ๋์์ ๋ง์ด ๋ฐ์์ผ๋ ์ ๋ณด๊ฐ ํ๋ฐ ๋ชจ์ฌ์์ง ์๊ณ ๋ณธ์ธ์ด ๊ฐ์ธ์ ์ผ๋ก ์ดํด๊ฐ ๋์ง ์๋ ๋ถ๋ถ์ด ๋ง์ ๋์ค์ ๋ค์ ๊ตฌํํ ๊ฒฝ์ฐ๋ฅผ ๋๋นํด ๊ธ๋ก ์์ฑํ๊ธฐ๋ก ๋ง์์ ๋จน์์ต๋๋ค.
๋ถ์กฑํ ๋ด์ฉ์ด ์์ ์ ์์ง๋ง ๋ ์ข์ ๋ด์ฉ์ด ์๋ค๋ฉด ๋๊ธ๋ก ๋ฌ์์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค.
์ข์ ํผ๋๋ฐฑ์ ์ธ์ ๋ ํ์์ด๋ฉฐ, ์ ๊ธ์ด ์์ ๋ก๊ทธ์ธ์ ๊ตฌํํ๋ ค๋ ๋๊ตฐ๊ฐ์๊ฒ ์ข์ ๋์์ด ๋์์ผ๋ฉด ํฉ๋๋ค.
๊ธ์ ์งํ์ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ์ด์ด์ง ์์ ์ ๋๋ค.
1. ๋ฐฐ๊ฒฝ์ง์ ์ดํดํ๊ธฐ, ์ ์ฒด ๊ทธ๋ฆผ ์ดํด๋ณด๊ธฐ (OAuth2, JWT Token, ํ๋ก์ ํธ ์ ์ฒด ๋์ํ)
2. Naver, Kakao, Google์ ํ๋ก์ ํธ๋ฅผ OAuth2 Client๋ก ์ค์ ํ๊ธฐ
3. Spring OAuth2.0 Client๋ฅผ ํ์ฉํ OAuth2.0 ํด๋ผ์ด์ธํธ ๋ฐฑ์๋ ๊ตฌํ
4. Redis์ JWT ํ ํฐ์ ์ฌ์ฉํ ์ฐ๋ฆฌ ์๋น์ค์ ๋ํ ์ธ์ฆ๊ณผ ์ธ๊ฐ์ ๊ตฌํ
5. OAuth2.0๊ณผ ํ ์คํธ ์ฝ๋, Spring REST Docs ์์ฑ
๐ NEO ํ๋ก์ ํธ์ ๋ํ ๊ฐ๋จํ ์ค๋ช
์์ ๋ก๊ทธ์ธ ์ ์ฉ๊ณผ ์ธ์ฆ ๋ฐ ์ธ๊ฐ ์ ์ฉ ๋ฐฉ์์ ํ๋ก์ ํธ ๋ณ๋ก ์ฒ์ฐจ๋ง๋ณ์ ๋๋ค. ๋ฐ๋ผ์ ์์ผ๋ก์ ๋ด์ฉ์ ์์ด์ ์ฐจ์ด๊ฐ ์์ ์ ์๊ธฐ์, ์ฐ๋ฆฌ ํ๋ก์ ํธ์ ๋ํด ๊ฐ๋จํ ์ค๋ช ํ๊ณ ๋น์ทํ ์ํฉ์ด๋ผ๋ฉด ์ ๊ฐ ์ ์ฉํ ๋ด์ฉ์ ์ฐธ๊ณ ๋ก ์ฌ๊ฒจ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค.
- NEO๋ ์น์ด ์๋, iOS ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋ค.
- ๋ฐฑ์๋๋ฅผ ๋ณ๋๋ก ๋๊ณ ์์ผ๋ฉฐ, ๋ฐฑ์๋๋ฅผ ํตํด OAuth2 ์ฌ์ฉ์ ์ธ์ฆ์ ๋ฐ์ต๋๋ค (๋ฐฑ์๋๊ฐ OAuth2.0 Client)
- OAuth2 ์ฌ์ฉ์ ์ธ์ฆ์ ํตํด ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ป๊ณ 1์ฐจ ํ์๊ฐ์ ์ ์งํํฉ๋๋ค
- ์ถํ์ ์ฌ์ฉ์ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๋ ฅ ๋ฐ์ 1์ฐจ ํ์๊ฐ์ ๋ ์ฌ์ฉ์์ ๋ํด ์ ๋ณด๋ฅผ ์ถ๊ฐ ์ ๋ฐ์ดํธ ํ ์ ์๋๋ก ์ค๊ณํฉ๋๋ค.
- ๋ก๊ทธ์ธ ๋ ์ฌ์ฉ์์๊ฒ OAuth2 AccessToken์ ์ง์ ์ฃผ์ง ์๊ณ , ๋ฐฑ์๋์์ ์์ฒด์ ์ผ๋ก ๋ฐ๊ธํ๋ JWT Token์ ์ง๊ธํฉ๋๋ค.
- JWT Token์ Access Token๊ณผ Refresh Token์ผ๋ก ์ ๊ณต๋ฉ๋๋ค.
๐ ํ๋ก์ ํธ ํ๊ฒฝ
NEO์์ ์ฌ์ฉ๋ dependency์ ๋๋ค. ํ๊ฒฝ์ ์์ด์ ์ฃผ์ํ ์ ์ ํฌ๊ฒ ๋ ๊ฐ์ง์ ๋๋ค.
- NEO์์ ์ฌ์ฉํ JWT ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋, auth0:java-jwt ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ io:jsonwebtoken:jjwt ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค auth0:java-jwt๋ฅผ ์ ํ
- Spring Security 6.1.2 ๋ฒ์ ์ด๊ธฐ ๋๋ฌธ์, ์ธํฐ๋ท ์์ ๋๋ค์์ ์๋ฃ(๊ตฌ๋ฒ์ )์ ๋นํด Security Config ํํธ์์ ๋ค๋ฅธ ์ฝ๋๊ฐ ์กด์ฌํฉ๋๋ค. (๋น๊ต์ ์ต์ ๋ฒ์ ์ด๊ธฐ ๋๋ฌธ์ ์ด์ ์ ์ฌ์ฉ๋๋ method๊ฐ ๋๋ถ๋ถ deprecated, ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋ง๋ ๋ฉ์๋๋ก ๋๋ถ๋ถ ๋ฐ๋.)
- Java 17
- SpringBoot 3.1.2
- 'com.auth0:java-jwt:4.2.1'
- 'spring-boot-starter-data-redis:3.1.2'
- 'spring-boot-starter-security:3.1.2' (spring-security-web, spring-security-config:6.1.2)
- 'spring-boot-starter-oauth2-client:3.1.2' (spring-security-oauth2-client, oauth2-jose:6.1.2)
๐ OAuth2.0
โ OAuth2.0์ด๋?
'OAuth(Open Authorization)'๋ ์ธํฐ๋ท ์ฌ์ฉ์๋ค์ด ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๊ณตํ์ง ์๊ณ , ๋ค๋ฅธ ์น์ฌ์ดํธ ์์ ์์ ๋ค์ ์ ๋ณด์ ๋ํด ์น์ฌ์ดํธ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๊ทผ ๊ถํ์ ๋ถ์ฌํ ์ ์๋ ๊ณตํต์ ์ธ ์๋จ์ผ๋ก์จ ์ฌ์ฉ๋๋, ์ ๊ทผ ์์์ ์ํ ๊ฐ๋ฐฉํ ํ์ค์ ์๋ฏธํฉ๋๋ค.
์ฌ์ฉ์์ ์์ด๋์ ๋น๋ฐ๋ฒํธ ์์ด ์ ๊ทผ ๊ถํ์ ์์๋ฐ์ ์ ์๋ค๋ ๊ฒ์, ๋ก๊ทธ์ธ ๋ฐ ๊ฐ์ธ์ ๋ณด ๊ด๋ฆฌ ์ฑ ์์ 'Third-Party Application(google, kakao, naver ๋ฑ)'์ ์์ํ ์ ์๋ค๋ ๊ฒ์ผ๋ก, ๋ก๊ทธ์ธ ๋ฐ ๊ฐ์ธ์ ๋ณด ๊ด๋ฆฌ์ ๋ํ ์ฑ ์์ ์์ํ๋ ๊ฒ๋ฟ๋ง ์๋๋ผ, ๋ถ์ฌ๋ฐ์ ์ ๊ทผ ๊ถํ์ ํตํด ์๋ํํฐ ํ๋ก๋ฐ์ด๋๊ฐ ๊ฐ์ง๊ณ ์๋ ์ฌ์ฉ์์ ๋ฆฌ์์ค ์กฐํ ๋ฑ์ ๊ธฐ๋ฅ์ ์ํํ ์ ์์ต๋๋ค.
ํํ ์ฐ๋ฆฌ์๊ฒ๋ '์์ ๋ก๊ทธ์ธ'์ผ๋ก ์ ์๋ ค์ ธ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด '๋ฒ๊ฐ์ฅํฐ' ์ ํ๋ฆฌ์ผ์ด์ ์์๋,
์์ ๊ฐ์ด '๋ฒ๊ฐ์ฅํฐ'์ ๋ ์์ ์ธ ํผ ๋ก๊ทธ์ธ์ ์งํํ์ง ์๋๋ผ๋, '์นด์นด์ค, ํ์ด์ค๋ถ, ๋ค์ด๋ฒ'์ ๊ฐ์ ์๋ํํฐ ํ๋ก๋ฐ์ด๋๋ค์๊ฒ ์ธ์ฆ ๊ณผ์ ์ ์์ํ๊ณ , ์ฌ์ฉ์๋ฅผ ์๋ณํด๋ ๋๋ค.
๊ทธ ์ค, OAuth2๋ผ๊ณ ๋ถ๋ฆฌ์ฐ๋ ์ด์ ๋ ๋น์ฐํ๋ ์ด์ ๋ฒ์ ์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์ '2'๋ผ๋ ๋ช ์นญ์ด ๋ถ์๊ฒ ์ฃ ? 2010๋ IETF์์ 'OAuth 1.0' ๊ณต์ ํ์ค์์ด RFC 5849๋ก ๋ฐํ๋์์ผ๋ฉฐ, OAuth์ ์ธ์ ๊ณ ์ ๊ณต๊ฒฉ์ ๋ณด์ํ 'OAuth 1.0a'๋ฅผ ๊ฑฐ์ณ, ํ์ฌ๋ OAuth์ ๊ตฌ์กฐ์ ์ธ ๋ฌธ์ ์ ์ ํด๊ฒฐํ๊ณ , ํต์ฌ ์์๋ง์ ์ฐจ์ฉํ ์ ์ฌ ํ๋กํ ์ฝ WRAP(Web Resource Access Protocol)์ ๊ธฐ๋ฐ์ผ๋ก ๋ฐํํ 'OAuth 2.0(RFC 6749, RFC 6750)'๊ฐ ๋ง์ด ์ฌ์ฉ๋๊ณ ์์ต๋๋ค.
๋ฐ๋ผ์ ์ฐ๋ฆฌ๋ ์ด๋ฌํ OAuth2.0์ ํตํด ์๋ ํํฐ ํ๋ก๋ฐ์ด๋์๊ฒ ์ธ์ฆ๊ณผ ์ธ๊ฐ๋ฅผ ์์ํจ์ผ๋ก์จ, ํด๋ผ์ด์ธํธ(OAuth2 Client)์ ์ ๊ทผ ํ ํฐ(OAuth2 Access Token)์ ๋ฐ๊ธํ๋ ๊ฒ์ ๋ํ ๊ตฌ์กฐ๋ก ์ดํดํ ์ ์์ต๋๋ค.
โ OAuth2.0์์ ์ฌ์ฉํ๋ ๋จ์ด ์ ๋ฆฌ
OAuth2.0์์ ์ฌ์ฉ๋๋ ๋จ์ด๋ค์ ๋ํด ์ ๋ฆฌ๋ฅผ ํด๋ณด์์ต๋๋ค.
๋จ์ด | ์ค๋ช | ์ถ๊ฐ ์ค๋ช |
Resource Owner | ๋ฆฌ์์ค ์์ ์, ์ฝ๊ฒ ํํํ๋ฉด ํน์ ์๋ํํฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์์ด๋ฉด์, ์ฐ๋ฆฌ์ ์๋น์ค๋ฅผ ์ด์ฉํ๊ณ ์ ํ๋ ์ฌ์ฉ์๋ฅผ ์๋ฏธํฉ๋๋ค. | ์๋ํํฐ ํ๋ก๋ฐ์ด๋์ ๋ณดํธ๋ ์์์ ์ ๊ทผํ ์ ์๋ ์๊ฒฉ์ ๋ถ์ฌํด ์ฃผ๋ ์ฃผ์ฒด์ด๋ฉฐ, OAuth2 ํ๋กํ ์ฝ ํ๋ฆ์์๋ Client๋ฅผ ์ธ์ฆํ๋ ์ญํ ์ ์ํํฉ๋๋ค. ํด๋น ์ธ์ฆ์ด ์๋ฃ๋๋ฉด ๊ถํ ์๋ฒ๋ฅผ ๊ฑฐ์ณ ๊ถํ ํ๋ ์๊ฒฉ์ Client์๊ฒ ๋ถ์ฌํ๊ฒ ๋ฉ๋๋ค. |
Client | ํด๋ผ์ด์ธํธ, OAuth2์ ์ฐ๊ด๋ ์๋ฒ(Authorization Server, Resource Server)์ ๋ํ ์ ๊ทผ์ ์์ฒญํ๋ ์๋น์ค๋ฅผ ์๋ฏธํฉ๋๋ค. | 'ํด๋ผ์ด์ธํธ'๋ผ๋ ์ด๋ฆ ๋๋ฌธ์ ํผ๋์ด ์์ ์ ์์ง๋ง, OAuth2 Server์ ์์ฒญ์ ๋ณด๋ด๋ ์ฃผ์ฒด๊ฐ OAuth2 Client๊ฐ ๋๋ฏ๋ก, ํด๋น ํ๋ก์ ํธ์์๋ NEO ๋ฐฑ์๋ ์๋ฒ๊ฐ Client์ ํด๋นํฉ๋๋ค. |
Provider, Server | ํ๋ก๋ฐ์ด๋, OAuth2 ์๋ฒ(Authorization + Resource)๋ฅผ ๊ตฌํํจ์ผ๋ก์จ OAuth2 ์๋น์ค๋ฅผ ์ ๊ณตํ๋ ์๋ํํฐ ์ ๊ณต์๋ฅผ ์๋ฏธํฉ๋๋ค. | ๋ํ์ ์ผ๋ก naver, kakao, google, facebook, github, okta ๋ฑ์ด ์์ต๋๋ค. |
Authorization Server | ๊ถํ ์๋ฒ, Resource Owner๋ฅผ ์ธ์ฆํ๋ฉฐ Client์๊ฒ Access Token์ ๋ฐ๊ธํด์ค๋๋ค. | ๊ตฌ์ฑ์ ๋ฐ๋ผ Authorization Server์ Resource Server๋ ์ํคํ ์ณ ๋ณ๋ ๊ฐ๋ฅ |
Resource Server | ์์ ์๋ฒ, ์ฌ์ฉ์์ ๋ณดํธ๋ ์์์ ์์งํ๊ณ ์๋ ์๋ฒ๋ก ๊ถํ ์๋ฒ์์ ์ฐ์ Access Token์ ๋ฐ์์ผ ์ ๊ทผ์ด ๊ฐ๋ฅํฉ๋๋ค. | ๊ตฌ์ฑ์ ๋ฐ๋ผ Authorization Server์ Resource Server๋ ์ํคํ ์ณ ๋ณ๋ ๊ฐ๋ฅ |
Authorization Grant | ๊ถํ ํ๋ ์๊ฒฉ, Resource Server์ ์ ๊ทผ ๊ฐ๋ฅํ AccessToken์ ๋ฐ๊ธ ๋ฐ๊ธฐ ์ด์ ์ ๋ฐ๊ธ ๋ฐ๋ ๊ถํ ์น์ธ ์ฝ๋์ ๋๋ค. | ์์ธํ ์ค๋ช ์ ์๋ "OAuth2.0 Authorization Code Grant ๋ฐฉ์" |
Access Token | ์ ๊ทผ ํ ํฐ, ํด๋น ์ ๊ทผ ํ ํฐ์ ํตํด Resource Server๋ก๋ถํฐ Resource Owner์ ์ ๋ณด๋ฅผ ํ๋ํ ์ ์์ต๋๋ค. | NEO์์ ๋ณ๋๋ก ๋ฐ๊ธํ๋ JWT Access Token์ด ์กด์ฌํ๋ฏ๋ก, ๋ ๊ฐ๋ ์ ๋ถ๋ฆฌํ๊ธฐ ์ํด ๊ธ์์๋ 'OAuth2 Access Token'์ผ๋ก ๋ถ๋ฅด๋๋ก ํ๊ฒ ์ต๋๋ค. |
โ OAuth2.0 Authorization Code Grant ๋ฐฉ์
Authorization Code Grant ๋ฐฉ์์ OAuth2.0์์ ๊ฐ์ฅ ๋ณดํธ์ ์ผ๋ก ์ฌ์ฉ๋๋ ์ธ์ฆ ๋ฐฉ์์ ๋๋ค.
์์ ์ธ์ฆ ๋ฐฉ์ ๋์ํ ๊ทธ๋ฆผ์ ์ดํด๋ณด๋ฉด, ์ด ํ๋ก์ธ์ค๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๐๐ป Authorization Code Grant Process
1. OAuth2.0 Client(NEO ๋ฐฑ์๋)๊ฐ Authorization Server์ ์ ๊ทผ ๊ถํ์ ์์ฒญ(API ์์ฒญ)ํฉ๋๋ค.
1-1. ์์ฒญ ์ ๋ฐ๊ธํ client_id, redirect_url, response_type=code๋ฅผ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก ํฌํจํ ์์ฒญ์ ๋ณด๋ ๋๋ค.
1-2. ํ๋ก๋ฐ์ด๋๊ฐ ์ ๊ณตํ๋ ์์ฒด ๋ก๊ทธ์ธ ํผ ํ์ ์ ์ถ๋ ฅํ๊ฒ ๋ฉ๋๋ค. (ex. ์นด์นด์ค ๋ก๊ทธ์ธ ํผ, ๋ค์ด๋ฒ ๋ก๊ทธ์ธ ํผ ๋ฑ.)
2. Resource Owner๊ฐ ํ๋ก๋ฐ์ด๋๊ฐ ๋์ด ๋ก๊ทธ์ธ ํผ์ ํตํด ๋ก๊ทธ์ธ์ ์๋ํฉ๋๋ค.
2-1. Authorization Server๋ ๊ถํ ๋ถ์ฌ ์ฝ๋ ์์ฒญ ์ ์ ๋ฌ๋ฐ์ redirect_uri๋ก Authorization Code(๊ถํ ๋ถ์ฌ ์น์ธ ์ฝ๋)๋ฅผ ์ ๋ฌํฉ๋๋ค.
2-2. ๊ถํ ๋ถ์ฌ ์น์ธ ์ฝ๋๋ฅผ ํตํด ์ฌ์ฉ์ ์ธ์ฆ ๋ฐ ์์์๋ฒ์ ์ ๊ทผํ ๋ ํ์ํ OAuth2 Access Token์ ํ๋ํ ์ ์์ต๋๋ค.
3. ๊ถํ ๋ถ์ฌ ์น์ธ ์ฝ๋๋ฅผ ๊ฐ์ง๊ณ , Authorization Server์ OAuth2 Access Token์ ํจ์ฒญํฉ๋๋ค.
3-1. ์์ฒญ ์ ๋ฐ๊ธํ client_id, redirect_url, grant_type, code(๊ถํ ๋ถ์ฌ ์น์ธ ์ฝ๋)๋ฅผ ์ฟผ๋ฆฌ ํ๋ฆฌ๋ฏธํฐ๋ก ํฌํจํ API ์์ฒญ์ ๋ณด๋ ๋๋ค.
3-2. ์ฑ๊ณต์ ์ผ๋ก ์ธ์ฆ๋๋ฉด, OAuth2 Access Token์ ์ ๋ฌํฉ๋๋ค.
4. OAuth2 Access Token์ ์์งํ Client๋ Resource Server์๊ฒ ๋ณดํธํ๊ณ ์๋ Resource Onwer์ ์ฌ์ฉ์ ์์์ ์์ฒญํฉ๋๋ค.
๐ค Access Token์ ํ๋ํ๋ ๊ณผ์ ์์ Authorization Code ๋ฐ๊ธ ๊ณผ์ ์ด ๋ค์ด๊ฐ ์ด์ ?
[๋ด์ฉ ์ถ์ฒ : https://wildeveloperetrain.tistory.com/247]
Authorization Code๋ฅผ ๋ฐ๊ธ๋ฐ๋ ๊ณผ์ ์ด ์๋ต๋๊ณ OAuth2 Access Token์ ๋ฐ๋ก ๋ฐ๊ธ๋ฐ๋๋ค๋ฉด,
Authorization Server๋ ๊ถํ ๋ถ์ฌ ์ฝ๋ ์์ฒญ ์ ์ ๋ฌ๋ฐ์ redirect_uri๋ก OAuth2 Access Token์ ์ ๋ฌํด์ผ ํฉ๋๋ค.
Redirect URI์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ URI ์์ฒด์ ๋ฐ์ดํฐ๋ฅผ ์ค์ด ์ ๋ฌํ๋ ๋ฐฉ๋ฒ ๋ฐ์ ์์ผ๋ฉฐ, ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด ์ค์ํ ๋ฐ์ดํฐ์ธ OAuth2 Access Token์ด ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด ๋ฐ๋ก ๋ ธ์ถ๋๊ฒ ๋ฉ๋๋ค.
Authorization Code ๋ฐ๊ธ ๊ณผ์ ์ด ์ถ๊ฐ๋ ๊ฒฝ์ฐ, redirect uri๋ก ์ ๋ฌ๋ Authorization Code(2-1)๋ฅผ ๋ฐฑ์๋ ๋ ๋ฒจ์์ ํด๋น ์น์ธ ์ฝ๋๋ฅผ ํฌํจํ API ์์ฒญ์ผ๋ก OAuth2 Access Token์ ๋ฐ๊ธ๋ฐ์ ์ ์์ต๋๋ค.
์ด ๊ณผ์ ์ ํตํด ๋ฐฑ์๋ ์ฌ์ด์์ OAuth2 Access Token์ด ์ ๋ฌ๋๊ธฐ ๋๋ฌธ์ ์ก์ธ์ค ํ ํฐ์ ํ์ทจ ์ํ์ด ์ค์ด๋๋ ๋ฑ, ๋ค๋ฅธ ๋ฐฉ์์ ๋นํด ๋ณด์์ ์ผ๋ก ์์ ํ๋ค๋ ํน์ง์ด ์์ต๋๋ค.
<Authorization Code Grant ๋ฐฉ์ ์์>
Redirect URI: https://api.neo.com/callbackURL
ํ๋ผ๋ฏธํฐ๋ก Authorization Code๋ฅผ ์ ๋ฌํฉ๋๋ค. ์: https://api.neo.com/callbackURL?code=abc123
(code๋ ๋ ธ์ถ๋์ด๋ ๋ ์ํ)
<Implicit Grant ๋ฐฉ์ ์์>
Redirect URI: https://api.neo.com/callbackURL
Access Token์ด ๋ฐ๋ก URI์ ํฌํจ๋ฉ๋๋ค. ์: https://api.neo.com/callbackURL#access_token=xyz456
(OAuth Access Token์ด ์ง์ ๋ ธ์ถ)
NEO๋ Spring OAuth2 Client๋ฅผ ์ฌ์ฉํ๋ฉด์ ์์ ๊ฐ์ Authorization Code Grant ๋ฐฉ์์ ์ฌ์ฉํ์ต๋๋ค.
์ด ๋ฐฉ์ ์ธ์๋ 3๊ฐ์ง ๋ฐฉ์์ด ๋ ์๋๋ฐ, ์ถ๊ฐ์ ์ผ๋ก ์๊ณ ์ถ์ ๋ถ๋ค์ ์๋์ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
โ Spring OAuth2 Client?
Spring์์๋ Security์ ํจ๊ป OAuth2 Client ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์กด์ฌํฉ๋๋ค. OAuth2 Client ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ OAuth2 Client๋ก์จ ๊ตฌํํด์ผ ํ๋ ๋๋ถ๋ถ์ ๋ด์ฉ์ ์ฝ๊ฒ ๊ตฌ์ฑํ ์ ์๋๋ก ๋์์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
ํ๋ก๋ฐ์ด๋ ๋ก๊ทธ์ธ ํผ์ผ๋ก ์ด๋์์ผ์ฃผ๋ ์๋ํฌ์ธํธ ์๋ ์์ฑ ๋ถํฐ, ๊ถํ ๋ถ์ฌ ์น์ธ ์ฝ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Access Token ๋ฐ๊ธ ๋ฐ๊ธฐ ๊ธฐ๋ฅ์ ์์ธํ ๊ตฌํ ์์ด ์ฝ๊ฒ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, OAuth2 Access Token์ ์ฌ์ฉํด ์์์๋ฒ๋ก๋ถํฐ ๋ฐ์ ์์์ ๋ค๋ฃจ๋ ์๋น์ค๋ฅผ ์ถ๊ฐ ๊ตฌํํ๊ธฐ๋ง ํ๋ฉด ์์ ํ๋ก์ธ์ค๋ฅผ ๋ชจ๋ ์์ฝ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
๋ง์ฝ OAuth2 Client ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ค๋ฉด ๊ฐ ํ๋ก๋ฐ์ด๋๋ค์ API Docs๋ฅผ ํ์ธํด์, ๊ฐ ๊ณผ์ ์ ํด๋นํ๋ API๋ฅผ ์ง์ ํต์ ํ๋ ค RestTemplete๋ WebClient๋ฅผ ์ฌ์ฉํ๊ณ , ์๋ํฌ์ธํธ ์์ฑ์ ์ํ ์ปจํธ๋กค๋ฌ ์์ฑ ๋ฑ์ ํด๋์ํ ๊ตฌํ์ด ํ์ํ ๊ฒ์ ๋๋ค.
๋ฐ๋ผ์ OAuth2 Client ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๊ฐ๋ฐํ๊ธฐ๊ฐ ๋์ฑ ์์ํด์ง๋๋ค.
Spring OAuth2 Client๊ฐ ํ๋ ์ญํ ์ ๋ค์ ์ด์ด์ง๋ ํฌ์คํ ์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
๐ง JWT Token
โ JWT Token์ด๋?
JWT(Json Web Token)์ ๋ง ๊ทธ๋๋ก ์น์์ ์ฌ์ฉ๋๋ JSON ํ์์ ํ ํฐ์ ๋ํ ํ์ค ๊ท๊ฒฉ์ ๋๋ค. ์ฃผ๋ก ์ฌ์ฉ์์ ์ธ์ฆ(authentication) ๋๋ ์ธ๊ฐ(authorization) ์ ๋ณด๋ฅผ ์๋ฒ์ ํด๋ผ์ด์ธํธ ๊ฐ์ ์์ ํ๊ฒ ์ฃผ๊ณ ๋ฐ๊ธฐ ์ํด์ ์ฌ์ฉ๋ฉ๋๋ค.
NEO์์๋ OAuth2.0์ ํตํด OAuth2 Access Token์ ํ๋ํ๊ณ ๋๋ฉด, ํด๋น Access Token์ ์ฐ๋ฆฌ NEO ์๋น์ค์ ์ธ๊ฐํ ๋ ์ฌ์ฉํ์ง ์๊ณ ๋ณ๋์ JWT Access Token์ ๋ฐ๊ธํ์ฌ ์ฌ์ฉํ ์์ ์ ๋๋ค.
์๋ JWT ํ ํฐ์ ๊ตฌ์กฐ์ ๋๋ค. Encoded์ Decoded ํํธ๋ฅผ ๋๋ ์ ๋ด ์๋ค.
๐ค Encoded
JWT ํ ํฐ์ ํ์ํ ๋ด์ฉ๋ค์ ๋ด์ ์ธ์ฝ๋ฉ ๋ ๊ธด ๋ฌธ์์ด๋ก, ๋ณดํต ์ฐ๋ฆฌ๊ฐ JWT ํ ํฐ์ '์ ๋ฌ'์ ๋ฒ์์์ ์๊ธฐํ ๋ ์ด ์ธ์ฝ๋ฉ๋ JWT ํ ํฐ์ ์๋ฏธํฉ๋๋ค.
์๋ฒ์์ ํด๋ผ์ด์ธํธ์๊ฒ ์ธ์ฝ๋ฉ ๋ JWT ํ ํฐ์ ์ ๋ฌํ ๋๋ HTTP์ Authorization ํค๋ ํน์ Body์ ๋ด์์ ์ ๋ฌํ๋ฉฐ,
ํด๋ผ์ด์ธํธ์์ ์๋ฒ๋ก JWT ํ ํฐ์ ์ ๋ฌํ ๋ ํด๋น ๋ฌธ์์ด์ Authorization Header์ ์์ "Bearer "๋ผ๋ ๋ฌธ์์ด์ ์ถ๊ฐํด ์๋ฒ๋ก ์ ๋ฌํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค.
์ ๋ณด๋ฉด, ์ธ์ฝ๋ฉ๋ JWT ํ ํฐ์ ๊ฐ ํํธ๊ฐ '.'์ผ๋ก ๊ตฌ๋ถ๋์ด ์์ผ๋ฉฐ ๊ฐ๊ฐ ํค๋, ํ์ด๋ก๋, ์๊ทธ๋์ฒ ์์๋๋ก ์ธ์ฝ๋ฉ ๋ ๋ชจ์ต์ ๋ณผ ์ ์์ต๋๋ค. ๊ทธ๋ฆผ์ ์์์ ๋ณด๋ฉด ์ข ๋ ํ์ฐํ ์ ์ ์์ต๋๋ค.
๐ค Decoded
JWT ํ ํฐ์ ๊ตฌ์ฑ ์์๋ก ์ธ์ฝ๋ฉ ๋๊ธฐ ์ ์ JWT ํ ํฐ์ ๋ชจ์ต์ ๋๋ค. JWT ํ ํฐ์ ์์ฑํ ๋ ์์ ๊ฐ์ด Header, Payload, Signature์ 3์์๋ฅผ ๊ตฌ์ฑํด ๋ง๋ค๊ฒ ๋๋ฉฐ, ์ธ์ฝ๋ฉ ๋ JWT ํ ํฐ์ Decodeํ๋ฉด ์ญ์๋ Header, Payload, Signature์ ๊ฐ์ ํ๋ํ ์ ์์ต๋๋ค.
- ํค๋(Header)
ํด๋น ํ ํฐ ์ค์ค๋ก์ ๋ํ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ธ์ฝ๋ฉ ์๊ณ ๋ฆฌ์ฆ์ธ 'alg'์ ํ ํฐ์ ์ ํ์ธ 'typ'๋ฅผ ํฌํจํฉ๋๋ค.
- ํ์ด๋ก๋(payload)
ํ ํฐ์ ์ฝ์ ํ๊ณ ์ ํ๋ ๋ฐ์ดํฐ๋ฅผ ์๋ฏธํฉ๋๋ค. JWT ํ ํฐ์ ์ ํด์ง ์ธ์ฝ๋ฉ ์๊ณ ๋ฆฌ์ฆ์ ์ํด ์ฝ๊ฒ ๋์ฝ๋ฉ๋ฉ๋๋ค. ๋๊ตฌ๋ JWT ํ ํฐ์ ๋ํด ์ฝ๊ฒ ์ ๋ณด๋ฅผ ์ด๋ํ ์ ์์ผ๋ฏ๋ก ํ์ด๋ก๋์๋ ๊ฐ๋ฅํ ๋๊ตฌ์ธ์ง ์๋ณ ๊ฐ๋ฅํ ์ต์ํ์ ๋ฐ์ดํฐ๋ง์ ๋ฃ์ด์ผ ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
์ฌ๊ธฐ์ ํด๋ ์(claim)์ด๋ผ๋ ๊ฐ๋ ์ด ๋์ค๋๋ฐ, ์ฝ๊ฒ ํํํ๋ฉด ํ์ด๋ก๋์ ์ถ๊ฐ๋๋ ์ ๋ณด ์กฐ๊ฐ์ ๋จ์๋ผ๊ณ ์ดํดํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, JWT ํ ํฐ์ ์์ฑํ ๋ ๊ฐ ์ฌ์ฉ์๋ฅผ ๊ตฌ๋ณํ ์ ์๋ '์ด๋ฉ์ผ'์ ๋ํ ์ ๋ณด๋ฅผ ๋ฃ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
๊ทธ๋ ๋ค๋ฉด JSON ๋ณํ์ด ๊ฐ๋ฅํ key-value์ ํํ๋ก ํด๋น ์กฐ๊ฐ์ ์ฝ์ ํ๋ ๊ฒ์ ๋๋ค.
์๋ฅผ ๋ค์ด ์๋์ ๊ฐ์ด ๋ง์ด์ฃ .
{
"sub": "1234567890",
"email": "aaaaa1234@gmail.com",
}
์์ ๊ฐ์ ํ์ด๋ก๋๋ 'sub'์ 'email' ๋ ๊ฐ์ ํด๋ ์์ผ๋ก ์ด๋ฃจ์ด์ก๋ค๊ณ ํํํ ์ ์์ต๋๋ค.
- ์๊ทธ๋์ณ(Signature)
์๊ทธ๋์ณ๋ ํค๋์ ํ์ด๋ก๋๋ฅผ ๊ฐ๊ฐ Base64 ์ธ์ฝ๋ฉ์ ๊ฑฐ์น ๋ฌธ์์ด๊ณผ ๋ฐฑ์๋ ์๋ฒ๊ฐ ์์งํ๊ณ ์๋ Secret Key๋ฅผ ํฌํจํด์ ๋ค์ ์ธ์ฝ๋ฉํ ๊ธด ๋ฌธ์์ด์ ์๋ฏธํฉ๋๋ค. ์ด๋ ๊ฒ ๋ง๋ค์ด์ง ์๊ทธ๋์ณ๋ JWT ํ ํฐ์ ํฌํจ์ด ๋๋ฉฐ, ์ถํ JWT ํ ํฐ์ ์ ํจ์ฑ์ ๊ฒ์ฆํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
Secret Key๋ ์๊ทธ๋์ณ์ ์ผ๋ถ๋ฅผ ๊ตฌ์ฑํ๊ฒ ๋๋ ๋ฌธ์์ด๋ก ๋๋คํ ๋ฌธ์์ด๋ก ๊ฐ๋ฐ์๊ฐ ์์ฑํด์ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค. ์ธํฐ๋ท ์์ Key Generator๋ฅผ ์ฌ์ฉํ๊ธฐ ๋ณด๋ค, ํค๋ณด๋๋ฅผ ๋๋คํ๊ฒ ๊ธธ๊ฒ ์ ๋ ฅํด ๊ตฌ์ฑํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ผ๋ฐ์ ์ผ๋ก Springboot ํ๋ก์ ํธ์์ Secret Key๋ฅผ application.yml์ ๋ณ๋๋ก ์ ์ฅํด ๋ ธ์ถ๋์ง ์๋๋ก ํฉ๋๋ค.
โ Access Token๊ณผ Refresh Token
JWT Access Token์, JWT๋ฅผ ์ฌ์ฉํด ํน์ ์๋น์ค์ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋๋ก ์ธ์ฆ/์ธ๊ฐ์ ์ญํ ์ ํ ์ ์๋๋ก ๋ง๋๋ ๋งค๊ฐ์ฒด์ ๋๋ค.
์์ JWT Token์ ๋ํ ๋ด์ฉ์, ์ด๋ป๊ฒ ์๋กญ๊ฒ ์์ฑํ๊ณ ์ด๋ป๊ฒ ํด๋น ํ ํฐ์ ๊ฒ์ฆํ๋์ง๋ฅผ ๊ทธ๋ฆผ์ผ๋ก ์ดํด๋ณด๋ฉฐ JWT Token์ด ์ด๋ป๊ฒ Access Token๋ก ํ์ฉ๋ ์ ์๋์ง ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ฐ์ , JWT ํ ํฐ์ ์์ฑํ๋ ๊ณผ์ ์ ๋๋ค.
์์์ ์ค๋ช ํ ๋ด์ฉ๋๋ก, ํค๋์ ํ์ด๋ก๋์ ๋ด์ฉ์ ์ฑ์๋ฃ๊ฒ ๋๊ณ ์๊ทธ๋์ณ๋ ์ด๋ ๊ฒ ์ ๋ ฅ๋ ํค๋ + ํ์ด๋ก๋ + ์ํฌ๋ฆฟ ํค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ฑ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ JWT Token์ ํค๋์ ํ์ด๋ก๋์ ์๊ทธ๋์ณ๋ฅผ ์ธ์ฝ๋ฉํด ๋ง๋ค์ด์ง๊ฒ ๋ฉ๋๋ค.
์ด๋ ๊ฒ ๋ง๋ค์ด์ง JWT Token์ ํด๋ผ์ด์ธํธ์๊ฒ Authorization ํค๋ ํน์ Body๋ก ์ ๋ฌํฉ๋๋ค.
๊ทธ๋ ๋ค๋ฉด ํด๋ผ์ด์ธํธ๋ ํด๋น JWT Token์ ์์ ํ ๋ฐฉ๋ฒ์ผ๋ก ๋ณด๊ด์ ํ๊ณ ์๋ค๊ฐ, ์๋ฒ์ API๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ์์ฒญ๊ณผ ํจ๊ป ํค๋์ ํด๋น ํ ํฐ์ ๋ด์์ ์ ์ก์ ํ๊ฒ ๋ฉ๋๋ค.
์๋ฒ์ ๋์ฐฉํ JWT Token์ ๊ฒ์ฆ ๊ณผ์ ์ ๊ฑฐ์น๊ฒ ๋ฉ๋๋ค. ๊ฒ์ฆ ๊ณผ์ ์ ์๋์ ๊ฐ์ต๋๋ค.
1. ์๋ฒ์ ๋์ฐฉํ JWT Token์ ๋์ฝ๋ฉํฉ๋๋ค.
2. ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ๋ฐ์ JWT ํ ํฐ์ ์๊ทธ๋์ณ๋ฅผ '์๋ณธ ์๊ทธ๋์ณ'๋ผ๊ณ ์ง์นญํฉ๋๋ค.
3. ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ๋ฐ์ JWT ํ ํฐ์ ํค๋์ ํ์ด๋ก๋๋ฅผ ์ป์ด์ต๋๋ค.
4. ์๋ฒ์ ์ ์ฅ๋ secret key๋ฅผ ๊ฐ์ง๊ณ 'ํ ์คํธ ์๊ทธ๋์ณ'๋ฅผ ์์ฑํด๋ ๋๋ค.
5. ์๋ณธ ์๊ทธ๋์ณ์ ํ ์คํธ ์๊ทธ๋์ณ๋ฅผ ์๋ก ๋น๊ตํฉ๋๋ค.
5-1. ๋ ์๋ช ์ด ๊ฐ๋ค๋ฉด ๊ฒ์ฆ ํต๊ณผ์ ๋๋ค.
5-2. ๋ ์๋ช ์ด ๋ค๋ฅด๋ค๋ฉด ๊ฒ์ฆ ์คํจ์ ๋๋ค. (ํค๋ ํน์ ํ์ด๋ก๋ ์์กฐ ๋ฑ)
์๋ฒ๋ ์์ฒญ๊ณผ ํค๋์ ํฌํจ๋ JWT ํ ํฐ์ ๊ฐ์ง๊ณ ์ฐ๋ฆฌ๊ฐ ์๋ ์ฌ์ฉ์์ธ์ง, ํด๋น ์ฌ์ฉ์๊ฐ ์ด ์๋น์ค์ ์ ๊ทผํ ๊ถํ์ด ์๋์ง ํ๋จํด์ผ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๋ฌํ ๊ณผ์ ์ JWT ํ ํฐ์ ๊ฒ์ฆํ๋ ๊ฒ์ผ๋ก ๋์ฒดํ ์ ์์ต๋๋ค.
JWT ํ ํฐ์ ๊ฒ์ฆํ์ ๋ ์ ํจํ๋ค๋ฉด ์ฐ๋ฆฌ ์๋น์ค๊ฐ ๋ง๋ค์ด๋ธ ํ ํฐ์ด๋ฏ๋ก(์ํฌ๋ฆฟ ํค๊ฐ ๋ ธ์ถ๋์ง ์๋ ์ด์) ์ธ์ฆ์, ํ์ด๋ก๋์ ์ฌ์ฉ์ ์ญํ ์ ํฌํจํ๋ค๋ฉด ์ธ๊ฐ ์ญ์ JWT ํ ํฐ์ ํตํด ๊ตฌํ์ด ๊ฐ๋ฅํ๊ฒ ๋ฉ๋๋ค.
๋ฐ๋ผ์ ์ด๋ฌํ ๋ฐฉ์์ผ๋ก ๋ง๋ค์ด์ง JWT ํ ํฐ์ Access Token์ผ๋ก์จ ํ์ฉํ ์ ์๋ ๊ฒ์ ๋๋ค.
JWT ํ ํฐ์ ์ฌ์ฉํ๋ฉด ์๋ฒ์ ๋ณ๋ค๋ฅธ ์ธ์ฆ ์ ๋ณด ์ ์ฅ ๊ณต๊ฐ์ด ์๋๋ผ๋ ์์ฒด์ ์ผ๋ก ์ธ์ฆ/์ธ๊ฐ๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
์ด๋ฌํ ์ ์ ์ธ์ ๊ณผ ๋ค๋ฅธ ๊ต์ฅํ ์ฐจ๋ณ์ ์ผ๋ก ์์ฉํด JWT Token ๋ฐฉ์์ด ์ธ๊ธฐ๋ฅผ ์ป์์ต๋๋ค.
ํ์ง๋ง ์ด๋ฐ Access Token์๋ ๋จ์ ์ ์์ต๋๋ค.
ํด๋น Access Token์ด ๋ค๋ฅธ ๋๊ตฐ๊ฐ์๊ฒ ํ์ทจ๋์ด ์ฌ์ฉํ๋ค๋ฉด ์๋ฒ์์๋ ํด๋น ํ ํฐ์ ๋ํ ์ ๋ณด๋ฅผ ๋ณ๋๋ก ์ ์ฅํ์ง ์๊ธฐ ๋๋ฌธ์, ์๋ฒ๋ก ๋ค์ด์จ ์์ฒญ์ด ๋ค๋ฅธ ์ฌ์ฉ์๊ฐ ํ์ทจํด์ ์ฌ์ฉํ๋ ๊ฒ์ธ์ง, ์ค์ ์ฌ์ฉ์๊ฐ ์ฌ์ฉํ๋ ๊ฒ์ธ์ง ๊ตฌ๋ณํ์ง ๋ชปํฉ๋๋ค.
๋ฌผ๋ก Access Token์ ๊ด๋ฆฌ๋ฅผ ์ ๋๋ก ๋ชปํ ํด๋ผ์ด์ธํธ์๊ฒ ์๋ชป์ด ์์ง๋ง, ํ์ทจ๊ฐ ์์ฌ๋๋ ์ํฉ์ ๋ณ๋์ ์ ์ฅ ๊ณต๊ฐ์ด ์๋ค๋ฉด ์๋ฒ์ธก์์๋ ํ์ ์กฐ์น๊ฐ ์ด๋ ต์ต๋๋ค.
์ด๋ฌํ ๋จ์ ์ ์ต์ํํ๊ธฐ ์ํด ๋์จ ์์ด๋์ด๊ฐ ๋ฐ๋ก, "Access Token์ ๋ง๋ฃ์๊ฐ์ ์งง๊ฒ ์ค์ ํด์ ํ์ทจ๊ฐ ๋๋๋ผ๋ ํผํด๋ฅผ ์ต์ํ ํ์"๋ผ๋ ์์ด๋์ด์ ๋๋ค.
ํด๋น ๋ฐฉ๋ฒ์ ํจ๊ณผ์ ์ด์ง๋ง, ๋จ์ํ Access Token์ ์ ํจ๊ธฐ๊ฐ์ ์งง๊ฒ ์ค์ ํ๋ค๋ฉด ๊ธฐ๊ฐ์ด ๋ง๋ฃ๋ ๋๋ง๋ค ์๋ก ๋ก๊ทธ์ธ์ ํ๋, ๋ถํธํ ์ฌ์ฉ์ ๊ฒฝํ์ ์๊ฒจ์ฃผ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋์ ์ถ๊ฐ๋ ๊ฐ๋ ์ด ๋ฐ๋ก, 'Refresh Token'์ ๋๋ค.
ํด๋ผ์ด์ธํธ๊ฐ ๋ก๊ทธ์ธ์ ํ๋ฉด, ์๋ฒ๋ Access Token๊ณผ Refresh Token์ ๊ฐ์ด ์ง๊ธํฉ๋๋ค. ์ฌ๊ธฐ์ ๋ ํ ํฐ์ ๋ง๋ฃ๊ธฐ๊ฐ์, Access Token์ด ํจ์ฌ ์งง๊ณ Refresh Token์ ๋ง๋ฃ ๊ธฐ๊ฐ์ด ๊ธด ๊ตฌ์กฐ๋ก ์ด๋ฃจ์ด์ ธ์์ต๋๋ค.
์ด๋ ์๊ฐ, Access Token์ด ๋ง๋ฃ๋๊ณ ์ฌ์ฉ์๋ ํด๋น ํ ํฐ์ผ๋ก ์๋ฒ์ ์์ฒญ์ ๋ณด๋ ๋๋ค. ์๋ฒ๋ ๋ง๋ฃ๋ ์ฌ์ค์ ์์์ฐจ๋ฆฌ๊ณ , ์์ฒญ์ ๋ฐ๋ คํฉ๋๋ค. ์ด๋ ๋ค์ ๋ก๊ทธ์ธ์ ์ ๋ํ์ง ์๊ณ Refresh Token์ ํจ๊ป ์๊ตฌํฉ๋๋ค. Refresh Token์ด ์ ํจํ๊ณ Access Token์ด ๋ง๋ฃ๋์๋ค๋ฉด ์๋ก์ด Access Token์ ๋ฐ๊ธํด์ฃผ๋ ๊ตฌ์กฐ์ฃ .
์ด๋ฐ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ค๋ฉด ์ฆ์ ๋ก๊ทธ์ธ์ ์ ๋ํ์ง ์๊ณ , ํ์ทจ๋ Access Token์ ๋ํด์ ์ต์ํ์ ํผํด๋ก ์ค์ผ ์ ์์ต๋๋ค.
๋ฌผ๋ก ์ด ๋ฐฉ๋ฒ ์ญ์ Refresh Token๋ ํจ๊ป ํ์ทจ๊ฐ ๋๋ค๋ฉด ์๋ฒ ์ธก์์๋ ์ ์ธ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. (ํ ํฐ ์ ๋ณด์ ๋ํ ๋ด์ฉ์ ์ ์ฅ ๊ณต๊ฐ์ด ์๋ ๊ฒฝ์ฐ.)
โ Refresh Token์ ์ข ๋ฅ
Refresh Token์ ํฌ๊ฒ ๋ ๊ฐ์ง๋ก ๊ตฌํํ ์ ์์ต๋๋ค.
๐๐ป 1. ๊ธฐ์กด JWT(Claim) ๋ฐฉ์์ Refresh Token
๊ธฐ์กด์ JWT ํ ํฐ์ ํ์ฉํด์ Refresh Token์ ๋ง๋ค ์ ์์ต๋๋ค. ๊ธฐ์กด์ ์์ฑํ๋ ๋ฐฉ์ ๊ทธ๋๋ก ์์ฑ์ด ๊ฐ๋ฅํ๋ฉฐ, ๋ง๋ฃ๊ธฐํ ์ญ์ ์ฝ๊ฒ ์ค์ ํ ์ ์์ต๋๋ค. Access Token๊ณผ๋ ๋ณ๊ฐ๋ก ์๋ก์ด Access Token์ ๋ฐ๊ธ ๋ฐ๊ธฐ ์ํ ํ ํฐ์ด ์กด์ฌ ์์์ด๋ฏ๋ก Access Token์ ๋ค์ด๊ฐ๋ ์ผ๋ถ ํด๋ ์ ์ญ์ ์ ๊ฑฐํด๋ ๋ฉ๋๋ค.
๋ค๋ง Access Token๊ณผ Refresh Token์ด ๋ชจ๋ ํ์ทจ๋์์ ๊ฒฝ์ฐ์๋ ๋ณ๋๋ก ์ ์ธ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์ฌ์ ํ JWT ํ ํฐ์ Stateless ํ๋๊น ๋ง์ด์ฃ .
๐๐ป 2. UUID๋ฅผ ํ์ฉํ Refresh Token
UUID๋ฅผ ๋๋คํ๊ฒ ์์ฑํด ํด๋น ๋ฌธ์์ด์ Refresh Token์ผ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๋ค๋ง UUID๋ JWT ํ ํฐ์ด ์๋๊ธฐ ๋๋ฌธ์ ์์ฒด๋ก ๋ง๋ฃ ์๊ฐ์ ๊ฒฐ์ ํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ํด๋น ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ๊ณง ์๋ฒ์ ๋ณ๋์ ํ ํฐ ์ ์ฅ ๊ณต๊ฐ์ ๋ง๋ จํ๋ค๋ ์๋ฏธ์ ๋์ผํฉ๋๋ค.
NEO์์๋ 2๋ฒ, UUID๋ฅผ ํ์ฉํ Refresh Token์ ์ ํํ๊ณ , ์ ์ฅ ๊ณต๊ฐ์ผ๋ก๋ Redis๋ฅผ ์ ํํ์ต๋๋ค.
์ ํ ์ฌ์ ๋, ์ฐ์ ์ธ๋ฉ๋ชจ๋ฆฌ key-value ์บ์๋ก์ ์์ธ ์๋์์ ์ด์ ์ ์ป์ ์ ์์ผ๋ฉฐ Redis ์บ์์ ๋ฐ์ดํฐ๊ฐ ์ธ์ ๊น์ง ์ ์ฅ๋ ์ง ๋ง๋ฃ๊ธฐ๊ฐ์ ์ ํํ ์ ์์ด ํ ํฐ๊ณผ ๋น์ทํ ๊ตฌ์กฐ๋ก ์ค๊ณํ ์ ์๋ค๋ ์ ์ด ์ข๊ฒ ์์ฉํ์ต๋๋ค.
์ด์ ๊ฐ์ด Refresh Token์ด ์๋ฒ์์ ๋ณ๋ ์คํ ๋ฆฌ์ง๋ก ๊ด๋ฆฌ๋๋ค๋ฉด, ํน์ ํ ํฐ์ ์ ๊ทผ์ ๋ง๋ 'black list' ๊ตฌํ์ ํตํด ๋ณด์์ ๋์ฑ ๋ ๊ฐํํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด Logout ์ดํ์๋ ์์ง ๋ง๋ฃ์๊ฐ์ด ์ง๋์ง ์์ ํ ํฐ์ ๋ํด ์ ๊ทผ์ ๋ง๋ ๊ฒ๋ ๊ฐ๋ฅํด์ง์ฃ .
โ ๊ทธ๋ผ ์ธ์ ์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋ณ๋ฐ ๋ค๋ฅผ ๊ฒ์ด ์๋ค์?
์ด ์๊ฒฌ์ ์์ด์ ๋๋ฌด๋๋ ๋์ํฉ๋๋ค. JWT ํ ํฐ์ ์ฌ์ฉํ๋ ๊ฐ์ฅ ํฐ ์ด์ ๋ "์ธ์ฆ ์ ๋ณด๋ฅผ ๋ณ๋๋ก ์ ์ฅํ๋ ๊ณต๊ฐ์ด ์์ด๋ ๋๋ค, statelessํ๋ค"์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ์ฅ์ ์ด ํด์๋์ด ๊ฒฐ๊ตญ์๋ ์ธ์ ์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ํฐ ์ฐจ์ด๊ฐ ์์ด๋ณด์ ๋๋ค.
๊ธฐ์กด์ JWT ํ ํฐ์ stateless ํ๊ธฐ ๋๋ฌธ์ ํ์ฅ์ฑ์ด ๊ต์ฅํ ์ข์์ต๋๋ค. ์๋ฒ๊ฐ ์ฌ๋ฌ๋๋ก ๋์ด๋๋๋ผ๋ ๋ณ๋์ ์ธ์ ์๋ฒ๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ธ์ ์๋ฒ๋ฅผ ์ ๊ฒฝ ์ธ ํ์๊ฐ ์์๊ธฐ ๋๋ฌธ์ด์ฃ . ๊ทธ๋ฌ๋ ๋ณ๋๋ก ์ ์ฅํ๋ ๊ณต๊ฐ์ด ์๊ฒผ๋ค๋ ๊ฒ์ ์ด๋ฌํ ์ ์ ์์ผ๋ก ๊ณ ๋ คํด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค.
๋ฐ๋ผ์ ์ด๋ฌํ ๊ตฌํ์ ํ์์ ์ธ ์๊ฐ์ผ๋ก ๋ณด์๋ ๊ฐ๋ฐ์๋ถ๋ค๋ ๋ง์ด ๋ณด์์ต๋๋ค.
๊ทธ๋ผ์๋ JWT Token + UUID Refresh Token in Redis์ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ฉด ๊ฐ์ง ์ ์๋ ์ฅ์ ์ ๋ํด ์๊ฐํด๋ณด์๋ฉด,
์ผ๋ฐ์ ์ธ ์ธ์ ๋ฐฉ์์ ๋นํด ์ธ์ ์๋ฒ์ ๋ํ '์์ฒญ' ์์ฒด๋ฅผ ์ค์ผ ์ ์๋ค๋ ์ ์ ํฌ์ธํธ๋ฅผ ์ฃผ๊ณ ์ถ์ต๋๋ค.
์ธ์ ๋ฐฉ์์ ์ธ์ ID๋ฅผ ๋ด์ ์ฟ ํค์ ์์ฒญ์ ํจ๊ป ์ ์กํ๊ณ ํด๋น ์ธ์ ID๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ธ์ ์๋ฒ์ ์คํ ๋ฆฌ์ง๋ฅผ ํ์ธํฉ๋๋ค. ์ฆ, ์ธ์ ์๋ฒ์ ํด๋น ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ์ป์ด์ค๋ ์์ฒญ์ด ํ ๋ฒ, ๋ณธ๋ ํด๋ผ์ด์ธํธ๊ฐ ์ํ๋ ์์ฒญ์ด ํ ๋ฒ ์ผ์ด๋๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ JWT Token + UUID Refresh Token in Redis ๋ฐฉ์์ ๊ฒฝ์ฐ, JWT Access Token์ ๋ํด์๋ Redis๊ฐ ๋ณ๋๋ก ๊ด๋ฆฌํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์ ํ ํฐ ์์ฒด์ ์ ํจ์ฑ ๊ฒ์ฌ๋ง์ผ๋ก ๋ณธ๋ ์์ฒญ์ ํํ ๊ฒ์ธ์ง ๋ฐ๋ คํ ๊ฒ์ธ์ง๋ฅผ ์ ํ ์ ์์ต๋๋ค.
๋ง์ฝ ์ธ์ ์๋ฒ์ ์์ฒญ ์ญ์ ๋ถ๋ด์ด ๊ฐ๋ ํ๋ก์ ํธ๋ผ๋ฉด ์ ํจํ๊ฒ ์์ฉํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
๋ฌผ๋ก ์ด๋ฌํ ์ ๋ณด๋ค ๋ค๋ฅธ ํฌ์ธํธ๋ฅผ ํจ์ฌ ์ค์ํ๊ฒ ์ฌ๊ธด๋ค๋ฉด ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ ํํ๋ ๊ฒ์ด ํด๋น ์๋น์ค์ ๋์ฑ ์ด์ธ๋ฆด ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
์์ง ๊ฒฝํ์ด ๋ง์ง ์์ ๊ฐ๋ฐ์๋ผ ์ด๋ค ์๋น์ค์ ์ด๋ค ๋ฐฉ์์ ์ ํํ๋ ๊ฒ์ด ์ต์ ์ธ์ง ๋ค์ํ ์๊ฒฌ์ ๋ฃ๊ณ ์ถ๊ณ , ์ข์ ๊ฒฝํ์ ์๊ณ ์ถ๋ค๋ ์๊ฐ์ด ๋ค ๋ฟ์ด๋ค์.
์ํํธ์จ์ด ๊ณตํ์์ '์ํํ์ ์๋ค' ๋ผ๋ ๋ง์ด ์์ต๋๋ค.
์ธ๋ฒ๋ฆฐ, ๋๋์ธ๊ฐ, ๋๋ผํ๋ผ์ ๊ฐ์ ๊ดด๋ฌผ๋ค์๊ฒ ์ํํ(one seeks bullets of silver)์ ํ๋ฒ์ ๋ฌด๋ ฅํ ์ํฌ ์ ์๋ ์ต๊ณ ์ ๋๊ตฌ์ด๋ค.
- Fred Brooks, ใSilver Bullet-Essence and Accidents of Software Engineeringใ
ํ ํฐ ๋ฐฉ์์ ์ธ์ ๋ฐฉ์์ ๋์ฒดํ๊ธฐ ์ํด ๋์จ ๊ฐ๋ ์ด์ง๋ง, ์ญ์๋ ์ํํ์ ์๋ ์ต๋๋ค.
๋ค์์ ๊ธฐํ๊ฐ ๋๋ค๋ฉด ์ธ์ ๋ฐฉ์๋ ํ ๋ฒ ๊ตฌํํด๋ณด๋ฉด์ ๊ฐ๊ฐ์ ์ฅ์ ์ ์ข ๋ ์ฒด๊ฐํ๊ณ ์ถ๋ค์.
โ๏ธ ์ ์ฒด ํ๋ก์ธ์ค ๋์ํ
์๋์ ๊ทธ๋ฆผ์ NEO์์ ์ฌ์ฉ๋ ์ ์ฒด ํ๋ก์ธ์ค๋ฅผ ํํํ ๊ทธ๋ฆผ์ ๋๋ค. ํํ๋ ฅ์ ๋ฌธ์ ๋ก ์ฝ๊ฐ์ ์ฐจ์ด๊ฐ ์์ ์ ์์ผ๋ฏ๋ก ์ฐธ๊ณ ๋ง ๋ถํ๋๋ฆฝ๋๋ค.
โ๏ธ ์ฐ๊ด ํฌ์คํธ
์ ๋ฐ์ดํธ ์์ ..
[โ๏ธ Trouble Shooting] - [TS] Spring Security + Spring OAuth2 Client ์ ์ฉ ๊ณผ์ ์ค ๋ฐ์ํ ๋ฌธ์ ํธ๋ฌ๋ธ ์ํ
โ๏ธ Reference
https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-token-claims
https://wildeveloperetrain.tistory.com/247
https://stackoverflow.com/questions/31309759/what-is-secret-key-for-jwt-based-authentication-and-how-to-generate-it