
OAuth๊ฐ ๋ญ๊น?
OAuth๋ ์ 3์ ์๋น์ค์ ๊ณ์ ๊ด๋ฆฌ๋ฅผ ๋งก๊ธฐ๋ ๋ฐฉ์์.
ex) ์นด์นด์ค๋ก ๋ก๊ทธ์ธํ๊ธฐ, ๋ค์ด๋ฒ๋ก ๋ก๊ทธ์ธํ๊ธฐ ๋ฑ๋ฑ..
OAuth ์ฉ์ด ์ ๋ฆฌ๋จผ์ ํ๊ฒ ์.
๋ฆฌ์์ค ์ค๋(resource owner)
์ธ์ฆ ์๋ฒ์ ์์ ์ ์ ๋ณด์ฌ์ฉ์ ํ๊ฐํ๋ ์ฃผ์ฒด.
์๋น์ค ์ด์ฉํ๋ ์ฌ์ฉ์๊ฐ ๋ฆฌ์์ค ์ค๋์.
๋ฆฌ์์ค ์๋ฒ(resource server)
๋ฆฌ์์ค ์ค๋ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ , ์ค๋์ ์ ๋ณด๋ฅผ ๋ณดํธํ๋ ์ฃผ์ฒด.
๋ค์ด๋ฒ, ์นด์นด์ค, ๊ตฌ๊ธ์ด ๋ฆฌ์์ค ์๋ฒ์.
์ธ์ฆ ์๋ฒ(Authorization server)
ํด๋ผ์ด์ธํธ์๊ฒ ๋ฆฌ์์ค ์ค๋์ ์ ๋ณด์ ์ ๊ทผํ ์ ์๊ฒ ํ ํฐ ๋ฐ๊ธํ๋ ์ญํ ์ ํ๋ ์ ํ๋ฆฌ์ผ์ด์
(์ค์ ์ด์์์๋ ์นด์นด์ค๊ฐ์ ๊ธฐ๊ด์ด ๋ฆฌ์์ค ์๋ฒ, ์ธ์ฆ์๋ฒ ์ญํ ๋์์ ์ํํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์)

ํด๋ผ์ด์ธํธ ์ ํ๋ฆฌ์ผ์ด์ (Client Application)
์ธ์ฆ ์๋ฒํํ ์ธ์ฆ ๋ฐ๊ณ , ๋ฆฌ์์ค ์ค๋์ ๋ฆฌ์์ค๋ฅผ ์ฐ๋ ์ฃผ์ฒด
์ฐ๋ฆฌ๊ฐ ๋ง๋๋ ํ๋ก๊ทธ๋จ.
OAuth ์ฐ๋ฉด ์ธ์ฆ ์๋ฒ(์นด์นด์ค)์์ ๋ฐ๊ธ๋ฐ์ Token์ฌ์ฉํด์
๋ฆฌ์์ค ์๋ฒ์์ ์ค๋์ ์ ๋ณด ์์ฒญํ๊ณ ์๋ต๋ฐ์์ ์ฌ์ฉํ ์ ์์.
๊ทผ๋ฐ ์ด๋ป๊ฒ ํด๋ผ์ด์ธํธ๊ฐ ๋ฆฌ์์ค ์ค๋์ ์ ๋ณด๋ฅผ ์ทจ๋ ํ ์ ์์๊น?
๋ฐฉ๋ฒ์ 4๊ฐ์ง์
โ ๊ถํ ๋ถ์ฌ ์ฝ๋ ์น์ธ ํ์
OAuth2.0์์ ๊ฐ์ฅ ๋ง์ด ์ฐ์ด๋ ๋ฐฉ๋ฒ
ํด๋ผ์ด์ธํธ๊ฐ ๋ฆฌ์์ค ์ ๊ทผํ ๋ ์ฐ์ด๊ณ ,
๊ถํ์ ์ ๊ทผํ ์ ์๋ ์ฝ๋ & ๋ฆฌ์์ค ์ค๋์ ๋ํ ์์ธ์ค ํ ํฐ
๋ฐ๊ธ ๋ฐ๋ ๋ฐฉ์
โ ์์์ ์น์ธ ํ์
์๋ฒ๊ฐ ์๋ ์๋ฐ ์คํฌ๋ฆฝํธ ์น app์์ ์ฃผ๋ก ์ฐ๋ ๋ฐฉ๋ฒ
โ ๋ฆฌ์์ค ์์ ์ ์ํธ ์๊ฒฉ์ฆ๋ช ์น์ธ ํ์
โ ํด๋ผ์ด์ธํธ ์๊ฒฉ์ฆ๋ช ์น์ธ ํ์
**๊ถํ ๋ถ์ฌ ์ฝ๋ ์น์ธ ํ์ ๋ง ์๋ฉด ๋ ๋ฏ
๊ทธ๊ฒ๋ง ํฌ์คํ ํ๊ฒ ์!
๊ถํ ๋ถ์ฌ ์ฝ๋ ์น์ธ ํ์ (Authorization code grant type)
์ ํ๋ฆฌ์ผ์ด์
๋ฆฌ์์ค ์๋ฒ (์์์ ๊ฐ๊ณ ์๋ ์ )
์ธ์ฆ ์๋ฒ (ํ ํฐ ๋ฐ๊ธํด์ฃผ๋ ์ญํ )
๋ฆฌ์์ค ์ค๋ (๋ก๊ทธ์ธํ๋ ค๋ ์ฌ์ฉ์)
์ด ๋ค๊ฐ์ง๊ฐ ์ด๋ค ์์๋ก ์ผํ๋์ง ์์์ผ๋จ.

๊ถํ ์์ฒญ์ด๋?
ํด๋ผ์ด์ธํธ(์คํ๋ง๋ถํธ ์๋ฒ)๊ฐ ์นด์นด์ค๊ฐ์ ๊ถํ ์๋ฒ์
ํน์ ์ฌ์ฉ์ ๋ฐ์ดํฐ์ ์ ๊ทผํ๊ธฐ ์ํด ๊ถํ์ ์์ฒญํ๋๊ฒ์.
์์ฒญ URI๋ ์๋ฒ๋ง๋ค ๋ค๋ฅด์ง๋ง ๋ณดํต์
ํด๋ผ์ด์ธํธID, ๋ฆฌ๋ค์ด๋ ํธ URI, ์๋ต ํ์
์ ํ๋ผ๋ฏธํฐ๋ก ๋ณด๋
์ฌ์ฉ์๊ฐ "์นด์นด์ค ๋ก๊ทธ์ธ" ๋ฒํผ์ ๋๋ฅด๋ฉด, ๋ธ๋ผ์ฐ์ ๊ฐ ์ธ์ฆ ์๋ฒ๋ก
์๋์ ๊ฐ์ด GET ์์ฒญ ๋ณด๋ด๋๊ฑฐ์.
GET spring-authorization-server.example/authorize=?
client_id=66a36b4c2&
redirect_uri=http://locationhost:8080/oauth/kakao/callback
response_type=code& // ์ธ๊ฐ ์ฝ๋ ์์ฒญ
scope=profile
client_id : ์ธ์ฆ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธํํ ํ ๋นํ ๊ณ ์ ์๋ณ์
redirec_uri : ๋ก๊ทธ์ธ ์ฑ๊ณต์์ ์ด๋ํ URI (์ธ๊ฐ ์ฝ๋ ๋ฐ์๋ ์ฐ์)

response_type : ํด๋ผ์ด์ธํธ๊ฐ ์ ๊ณต๋ฐ๊ธธ ์ํ๋ ์๋ต ํ์ ( code๊ฐ ํฌํจํด์ผ๋จ )
scope : ๋ฐ๊ณ ์ถ์ ์ ๋ณด ๋ชฉ๋ก
**์ฐธ๊ณ ๋ก ์ธ๊ฐ ์ฝ๋๋
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ, ๊ถํ ๋์ ๋๋์๋
ํด๋ผ์ด์ธํธ(๋ด๊ฐ ๋ง๋ ์ฑ)๊ฐ ์ธ์ฆ์๋ฒ๋ก๋ถํฐ ๋ฐ๋ ์งง์ ๋ฌธ์์ด์
GET http://localhost:8080/oauth/kakao/callback?code=abc123xyz
์ธ์ฆ ์๋ฒ๋ ๋ฐ๋ก access_token์ ์ฃผ๋๊ฒ ์๋๋ผ ์ธ๊ฐ ์ฝ๋ ๋จผ์ ์ค.
๋ฐ์ดํฐ ์ ๊ทผ์ฉ ๊ถํ ๋ถ์ฌ
์ธ์ฆ ์๋ฒ์ ์์ฒญ์ ์ฒ์ ๋ณด๋ผ ๋,
์ฌ์ฉ์ํํ ๋ก๊ทธ์ธ ํ์ด์ง ๋ณด์ฌ์ฃผ๊ณ ๋ฐ์ดํฐ ์ ๊ทผ ๋์๋ฅผ ์ป์ (์ต์ด 1ํ๋ง)
์ดํ์๋ ์ธ์ฆ ์๋ฒ์์ ๋์ ๋ด์ฉ ์ ์ฅํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๊ฑ ๋ก๊ทธ์ธ๋ง ๋ฐ๋ก ํจ.
๋ก๊ทธ์ธ ์๋ฃ๋๋ฉด ๊ถํ ๋ถ์ฌ ์๋ฒ๋ ๋ฐ์ดํฐ์ ์ ๊ทผ ํ ์ ์๊ฒ
์ธ์ฆ ๋ฐ ๊ถํ ๋ถ์ฌ๋ฅผ ์์ ํจ.
์ธ์ฆ ์ฝ๋ ์ ๊ณต
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด,
์ฒจ์ ์์ฒญ ๋ณด๋ผ๋ ๋ณด๋๋ค redirect_uri๋ก ๋ฆฌ๋ค์ด๋ ์ ๋๊ณ ,
์ด๋ ํ๋ผ๋ฏธํฐ๋ก ์ธ์ฆ ์ฝ๋๋ฅผ ์ค.
GET http://localhost:8080/myapp?code=a1s2f3g4
์์ธ์ค ํ ํฐ ์๋ต์ด๋?
์์ ๊ฐ์ด ์ธ์ฆ ์ฝ๋ ๋ฐ์ผ๋ฉด, ์์ธ์ค ํ ํฐ์ผ๋ก ๊ตํํด์ผ๋จ.
์์ธ์ค ํ ํฐ = ๋ก๊ทธ์ธ์ธ์ ์ ๋ํ ์๊ฒฉ์ ์ฆ๋ช ํ๋ ์๋ณ ์ฝ๋.
๋ณดํต /token POST ์์ฒญ ๋ณด๋
ex)
POST spring-authorization-server.example.com/token
{
"client_id" : "66aasdf",
"client_secret" : "aaabbbcc111",
"redirect_uri" : "http://localhost:8080/myapp",
"grant_type" : "authorization_code",
"code" : "a1s2f3g4"
}
client_secret : OAuth ์๋น์ค์ ๋ฑ๋กํ ๋ ์ ๊ณต๋ฐ๋ ๋น๋ฐํค
grant_type : ๊ถํ ์ ํ ใ ํ์ธํ ๋ ์ฌ์ฉ.
๊ถํ ์๋ฒ๋, ์์ฒญ ๊ฐ ๊ธฐ๋ฐ์ผ๋ก ์ ํจ์ฑ ํ์ธํ๊ณ
์ ํจํ๋ค๋ฉด ์์ธ์ค ํ ํฐ์ผ๋ก ์๋ตํจ.
ex)
{
"access_token" : "aassdf",
"token_type" : "Bearer",
"expires_in" : 3600,
"scope" : "openid profile",
...
}
์ด ๋ ์ ๊ณต๋ฐ์ ์์ธ์ค ํ ํฐ์ผ๋ก ๋ฆฌ์์ค ์ค๋ ์ ๋ณด ๊ฐ์ ธ์ฌ ์ ์์.
์ ๋ณด๊ฐ ํ์ํ ๋๋ง๋ค APIํธ์ถํด์ ์ ๋ณด ๊ฐ์ ธ์ค๊ณ
๋ฆฌ์์ค ์๋ฒ๋ ํ ํฐ ์ ํจํ์ง ํ์ธํ๊ณ , ์๋ต.
์์ฒญ ex)
GET Spring-authorization-resource-server.example.com/userinfo
Header:Authorization: Bearer aassdf
(์ฐธ๊ณ ๋ก ๋ด ์๋น์ค์ ๋ก๊ทธ์ธ ์ํ๋ ๋ฐ๋ก ๊ด๋ฆฌํจ
๋ด ์๋ฒ์์๋ ์ฌ์ฉ์ ์ ๋ณด ๋ณด๊ณ JWT ๋ฐ๊ธํ๊ฑฐ๋ ์ธ์ ์ ์ฅํด์
์ฐ๋ฆฌ ์๋น์ค ๋ก๊ทธ์ธ ์ํ ์ ์งํด์ผ๋จ)
์ ๋ฆฌํ์๋ฉด
1. ์ฑ -> ์ธ์ฆ์๋ฒ : ์ธ๊ฐ ์ฝ๋ ๋ฌ๋ผ๊ณ GET ์์ฒญ ๋ณด๋
2. ์ธ์ฆ์๋ฒ -> ์ฌ์ฉ์ : ๋์ํ๋ฉด, ๋ก๊ทธ์ธ ํ๋ฉด ๋ณด์ฌ์ฃผ๊ณ ๋์ ์ป๊ณ ๋๋ฉด
3. ์ธ์ฆ์๋ฒ -> ์ฑ : ๋ฆฌ๋ค์ด๋ ํธ url๋ก ์ธ๊ฐ ์ฝ๋ ์ค
4. ์ฑ -> ์ธ์ฆ์๋ฒ : ๋ฐฉ๊ธ ๋ฐ์ ์ธ๊ฐ ์ฝ๋๋ก, ์ด๋ฒ์๋ ์์ธ์ค ํ ํฐ ๋ฌ๋ผ๊ณ POST ์์ฒญ ๋ณด๋
5. ์ธ์ฆ์๋ฒ -> ์ฑ : JSON ํํ๋ก ์์ธ์ค ํ ํฐ ์ค
6. ์ฑ -> ๋ฆฌ์์ค ์๋ฒ : 5๋ฒ์์ ๋ฐ๋ ์์ธ์ค ํ ํฐ์ผ๋ก
GET /user/me + Authorization Bearer (์์ธ์ค ํ ํฐ)
์ด๋ ๊ฒ GET ์์ฒญ ๋ณด๋
7. ๋ฆฌ์์ค ์๋ฒ -> ์ฑ : ์ฌ์ฉ์ ์ ๋ณด ์ค
(์ด ๋ Authentication๊ฐ์ฒด์ ์ฃผ๋๊ฒ ์๋๋ผ, kakaoId, email, nickname๋ฑ์ ๋ฐ๊ณ
๊ทธ๊ฑธ ๋ด ์๋น์ค์ ์ ์ ๋ฅผ ์๋ณํ๊ณ , ํ์๊ฐ์ ์ํด
ํด๋น ์ ์ ๋ก Authentication๊ฐ์ฒด ๋ง๋ค์ด์ SecurityContextHolder์ ์ ์ฅ!)
Q. ์ ์ธ๊ฐ ์ฝ๋ ๋ฌ๋ผ๊ณ ํ ๋ GET ์์ฒญ์ด๊ณ , ์์ธ์ค ํ ํฐ ๋ฌ๋ผ๊ณ ํ ๋ POST ์์ฒญ์?
A.
GET ์ธ๊ฐ ์ฝ๋ ์์ฒญ์, ์ฌ์ฉ์๋ฅผ ๋ก๊ทธ์ธ, ๋์ ํ๋ฉด์ผ๋ก ๋ฆฌ๋๋ ์ ์ํค๋ ค๋๊ฒ ๋ชฉ์ ์
url๋ก ์์ฒญ์ ๋ณด๋ด์ผ ๋ธ๋ผ์ฐ์ ์ด๋์ด ๋๋๊น.
POST ์์ธ์ค ํ ํฐ ์์ฒญ์, ๋ฏผ๊ฐํ ์ ๋ณด(clietn_secret๋ฑ)๋ฅผ ์์ ํ๊ฒ ์ฃผ๊ณ ๋ฐ๊ธฐ ์ํด POST ์์ฒญ ์ฐ๋๊ฑฐ์
url์ ์์ฒญ๋๋ฉด ์๋๋๊น
'Spring Boot' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [OAuth] ๊ตฌ๊ธ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ1 ( ํ ํฐ ๋ฐ๊ธ๋ฐ๊ธฐ) (5) | 2025.05.07 |
|---|---|
| [Spring Boot] ์ฟ ํค๋? Cookie ๐ช (0) | 2025.05.07 |
| [Spring Boot] ํ์๋ฆฌํ ์์ , Model ๊ฐ์ฒด๋? (0) | 2025.05.03 |
| [Spring Boot] ํ์๋ฆฌํ ํํ์, ๋ฌธ๋ฒ ์ ๋ฆฌ (0) | 2025.05.03 |
| [Spring Boot] ํ์๋ฆฌํ ํ ํ๋ฆฟ ์์ง์ด๋?์์กด์ฑ ์ถ๊ฐ (0) | 2025.05.03 |