[FastAPI] 6. Google-auth ๋ฐ PyJWT๋ฅผ ์ด์ฉํ OAuth2 ์ธ์ฆ ๊ตฌํ 1
์ด๋ฒ ํฌ์คํธ์์๋ ์ธ์ฆ์ ๋ํ ์ด์ผ๊ธฐ๋ฅผ ํด๋ณด๊ณ ์ ํฉ๋๋ค.
Spring์์๋ Spring Security๋ผ๋ ๋ชจ๋์ ์ ๊ณตํ์ฌ ๊ฐ๋ฐ์๊ฐ ์ธ์ฆ์ ๋ํ ๊ตฌํ์ ๊ฐ๋ณ์ ์ผ๋ก ํ์ง ์๊ณ ๋ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์กด์ฌํ์ต๋๋ค. ์ด๋ฅผ ํตํ์ฌ Google ๊ฐ๋ฐ์ ์ฝ์์์ Client ID๋ฅผ ๋ฏธ๋ฆฌ ๋ฐ๊ธ๋ฐ์ ํ ๊ตฌํ๋์ด ์๋ ๊ตฌํ์ฒด๋ง ์ ์ฌ์ฉํ๋ฉด ์ด๋ ต์ง ์๊ฒ OAuth2 ์ธ์ฆ์ ๊ตฌํํ ์ ์์์ฃ .
FastAPI๋ ์ด์ ๋น์ทํ๊ฒ OAuth2 ์ธ์ฆ์ ๊ตฌํํ์ง๋ง JWT๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์๋ ๋ณ๋์ ๊ตฌํ ์ฒ๋ฆฌ๋ฅผ ํด์ค์ผ ํฉ๋๋ค. ์ด๋ฒ ํฌ์คํธ์์๋ ์ด ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ์ง๊ณ OAuth2 ์ธ์ฆ์ ์ด๋ป๊ฒ ๊ตฌํํ ์ ์๋์ง์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
์ด ๊ธ์ ์ฝ์ด๋ณด์๊ธฐ ์ ์ OAuth2 ์ธ์ฆ์ ๋ํ ์ ํ ๊ณต๋ถ๋ฅผ ์ถ์ฒํฉ๋๋ค. ๋ง์ฝ OAuth2 ์ธ์ฆ์ ์ฒ์ ์ ํด๋ณด์๋ ๋ถ๋ค์ด๋ผ๋ฉด ์ ๊ธ์ ๋จผ์ ์ฝ์ด๋ณด์๊ธฐ ๋ฐ๋๋๋ค.
To Be
๋จผ์ ์ฐ๋ฆฌ๊ฐ ๊ตฌํํ๊ณ ์ ํ๋ ๋ชจ์ต์ ์ํคํ ์ฒ ๊ทธ๋ฆผ์ ํตํด ๋ํ๋ด ๋ดค์ต๋๋ค.
Spring boot Security๋ฅผ ์ฌ์ฉํ์ ๋๋ ํ์ด์ง๊ฐ ์๋ MVC๋ฅผ ๊ธฐ์ค์ผ๋ก ์์ฑ์ ํ์ง๋ง ์ด๋ฒ์๋ Restful API๋ฅผ ์ด์ฉํด์ OAuth2 ๋ก๊ทธ์ธ์ ๊ตฌํํ๊ณ ์ ํฉ๋๋ค. ๋ค๋ฅธ ์ ์ด ์๋ค๋ฉด Redirect URL์ ์ ๊ณตํ์ง ์๋๋ค๋ ์ ์ด ์๋๋ฐ, ์ด ๋ถ๋ถ์ React๋ Vue์ ๊ฐ์ SPA ๊ฐ๋ฐ ํ๋ ์์ํฌ ๋ฑ์ ์ด์ฉํด์ Google ๋ก๊ทธ์ธ Redirect URL์ ์ง์ ํ๊ณ , ํด๋น ๋ก๊ทธ์ธ์ ํตํด์ ๋ฐ์ ๊ถํ ๋ถ์ฌ ์ฝ๋๋ฅผ REST ์๋ฒ๋ก ์์ฒญํ๋ฉด ์ด์ JWT ํ ํฐ์ ์์ฑํ์ฌ Client์๊ฒ ์ ๊ณตํด์ฃผ๋ฉด ๋ฉ๋๋ค.
๊ทธ๋ฐ ๋ค์ ํด๋ผ์ด์ธํธ๋ ํด๋น ํ ํฐ์ ์ด์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์๋น์ค๋ฅผ ์ด์ฉํ ์ ์๋๋ก ๊ตฌํํด์ฃผ๋ฉด ๋ฉ๋๋ค.
Spring boot Security์์๋ ์ด๋ฌํ ๊ณผ์ ๋ค์ด ์ ๋ถ ๊ตฌํ๋์ด ์์ง๋ง ๊ณต๊ต๋กญ๊ฒ๋ FastAPI์์๋ ์ด๋ฌํ ๊ณผ์ ์ ์ ๋ถ ์๋์ผ๋ก ๊ตฌํํด์ค์ผ ํฉ๋๋ค.
์ด๋ฅผ ์ํด์ ์ฐ๋ฆฌ๋ JWT๊ฐ ๋ฌด์์ธ์ง ๊ฐ๋จํ๊ฒ ์๊ณ ๋์ด๊ฐ์ผ ํฉ๋๋ค.
JWT
JWT๋ ์น ํ์ค(RFC 7519)์ผ๋ก์จ JSON ๊ฐ์ฒด๋ฅผ ์ด์ฉํ ๊ฐ๋ณ๊ณ ์๊ฐ ์์ฉ์ ์ธ ๋ฐฉ์์ผ๋ก ์ ๋ณด๋ฅผ ์ ๋ฌํ๋ ํ ํฐ์ ๋๋ค. ๋ฐ๋ผ์ ์๋์ ๊ฐ์ด JSON ๊ตฌ์กฐ๋ก ๋์ด ์๋ ์ธ์ฆ ํฌ๋งท์ ๋๋ค.
์ ๊ตฌ์กฐ๋ JSON ํํ๋ง์ ๋ณด์ฌ์ค ๊ฒ์ด๋ฉฐ ์ค์ ์ด ๋ฐ์ดํฐ๋ JWT์์ payload์ ํด๋น ๋ฉ๋๋ค. payload๊ฐ ๋ฌด์์ด๋๊ตฌ์? ์๋ง ์ปดํจํฐ ๋คํธ์ํฌ๋ฅผ ๊ณต๋ถํด๋ณด์ ๋ถ๋ค์ด๋ผ๋ฉด ๋คํธ์ํฌ์ ํจํท ๊ตฌ์กฐ์ ๋ํด ์๊ณ ๊ณ์ค ๊ฒ์ ๋๋ค. ํจํท ๊ตฌ์กฐ๋ ๊ธฐ๋ณธ์ ์ผ๋ก Header์ data๋ก ๊ตฌ๋ถ๋๋๋ฐ, JWT ์ญ์ Header์ Payload๋ก ๊ตฌ๋ถ๋์ด ์ง๋ฉฐ payload๋ ์ฌ๊ธฐ์ ํจํท์ data์ ํด๋น๋๋๋ฐ์. ์ด ๋ถ๋ถ์ 2ํธ์์ ์ข ๋ ์ฌ์ธต์ ์ผ๋ก ์ด๋ป๊ฒ ์ฌ์ฉํ ์ ์๋์ง ์์๋ณด๊ธฐ ์ํด์ ์ ์ ๋ด์๋๋๋ก ํ๊ฒ ์ต๋๋ค.
๋ฐ๋ผ์ ์ฐ๋ฆฌ๋ ์ด๋ฌํ ์ธ์ฆ ์ ๋ณด๋ฅผ JSON ํํ๋ก ๋ด์๋ ๋ค ๋ถ๋ฌ์์ ๋ ๋๊ตฌ์ ์ ๋ณด์ธ์ง, ์ ํจ๊ธฐ๊ฐ์ ์ผ๋ง๋ ๋๋์ง๋ฅผ ํ์ธํ์ฌ ์ธ์ฆ์ ์ํํ ์ ์์ต๋๋ค.
Generate Client ID (Google)
์ฐ๋ฆฌ๋ ์ฌ๊ธฐ์์ Google ์ธ์ฆ ๊ตฌํ์ ์๋ํด๋ณผ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๊ธฐ ์ํด์ Google์์ Client ID๋ฅผ ๋ฐ๊ธ๋ฐ์์ผ ํ๋๋ฐ์. ๋ง์ฝ ๋ฐ๊ธํ์ง ๋ชปํ๋ค๋ฉด ์๋์ ๊ธ์ ์ฐธ๊ณ ํ์ฌ Google์ Client ID๋ฅผ ๋ฐ๊ธ๋ฐ์์ฃผ์ธ์.
Install Dependency
์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ๊ตฌํ์ ํด๋ณด๋๋ก ํ์ฃ . ๋จผ์ JWT๋ฅผ ๋ง๋ค๊ธฐ ์ํ PyJWT์ Google ์ธ์ฆ ์๋ฒ๋ก์ ์ธ์ฆ ๊ตฌํ์ด ๋์ด ์๋ google-auth ๋ํ๋์๋ฅผ ์ค์นํ๋๋ก ํฉ๋๋ค.
FastAPI๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ฏธ๋ฆฌ FastAPI๋ ๊ฐ์ด ์ค์นํด์ฃผ๋ฉด ์ข๊ฒ ์ฃ ?
Generate Token
๋จผ์ ํ ํฐ์ ๋ฐ๊ธ๋ฐ๋ ๋ถ๋ถ๋ถํฐ ๊ตฌํํด๋ณผํ ๋ฐ์. ์ฐ๋ฆฌ๊ฐ ํ ํฐ์์ ์ฌ์ฉํด์ผํ ์ ๋ณด๋ ๋ฐ๋ก ๊ตฌ๊ธ ๊ณ์ ์ ์ ๋ณด์ ๋๋ค. ๋๊ฐ ์ฐ๋ฆฌ ์๋น์ค์ ์ ๊ทผํ๋ ค๋ ๊ฑฐ๊ธด ํ๋ฐ, Google ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธ ํ์๊ธด ํ์ง๋ง ๊ทธ๊ฒ ๋๊ตฌ์ธ์ง๋ฅผ ํ์ธํด์ผ๋๋๋ฐ์. ๊ทธ๋์ REST API์์๋ Client์์ Redirect๋ก ์ ์ํ์ฌ ๋ฐ์ ํ ํฐ์ ๋ฐ์ Google ๊ณ์ ์๋ฒ๋ก ์ด ํ ํฐ์ ๋๊ฒจ์ฃผ๊ฒ ๋๋ฉด ์ด๋ค Client ID๋ก ์ด ํ ํฐ์ ๋ฐ์๊ณ , ๋๊ตฌ์ ์ ๋ณด์ธ์ง๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
์กฐ๊ธ ์ด๋ ค์ด ๋ถ๋ถ์ด๋ผ๊ณ ์๊ฐ๋์ด, ๊ทธ๋ฆผ์ผ๋ก ํ ๋ฒ ๋ ๊ทธ๋ ค๋ดค์ต๋๋ค.
์ฌ์ฉ์๊ฐ ์น ํ์ด์ง์ ์ ์ํด์ Google ๋ก๊ทธ์ธ์ ์์ฒญํ ๊ฒฝ์ฐ ์์์ ์ ๋ ฅํ Redirect URI๋ก ์์ฒญ์ํ๊ฒ ๋๋ฉฐ Google์์๋ ๋ก๊ทธ์ธ ํ์ด์ง๋ฅผ ๋ณด์ฌ์ฃผ๊ฒ ๋๊ณ , ์ฌ์ฉ์๊ฐ ์ ๋ณด๋ฅผ ์ ๋ ฅํ๋ฉด ์ด๋ฅผ Google์์๋ ์ธ์ฝ๋ฉ๋ JWT ํ ํฐ์ ์น์ ์ ๋ฌํ๋ฉฐ ์น์์๋ ๋ค์ ์ด๋ฅผ ๋ฐฑ์๋๋ก ์ ์กํ์ฌ ๋ฐฑ์๋๊ฐ ์ด ์ ์ ๋ฅผ ํ๋จํ ์ ์๋๋ก ํ๋ ๊ตฌ์กฐ์ ๋๋ค.
์ด๋ฅผ ์ฝ๋๋ก ์ ์ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์น์ผ๋ก๋ถํฐ ๋ฐ์ ํ ํฐ์ ${token}์ด๋ผ๊ณ ๊ฐ์ ํ์ ๋ FastAPI์์ ํด์ค์ผํ๋ ๋ถ๋ถ์ ์ด ์ธ์ฝ๋ฉ๋ ํ ํฐ์ ๋์ฝ๋ฉํ์ฌ payload๋ก ๋ฐ๊ฒ ๋๋๋ฐ, ์ด ๋ ์ฃผ๋ ์ ๋ณด๋ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์์ง๋ง ๋ํ์ ์ผ๋ก ์ด๋ค Client ID๋ก, ๋๊ฐ ์ ๊ทผํ๋์ง๋ฅผ ์ ์ ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ์ด๋ฅผ ํ ๋๋ก ์๋์ ํ์์ ํ ํฐ์ ๋ง๋ค์ด ๋ฐํํด์ฃผ๋ API๋ฅผ ๋ง๋ค์ด์ฃผ๋๋ก ํ๊ฒ ์ต๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ํ ํฐ์ด ์ธ์ ๋ง๋ค์ด์ก๋์ง, ์ธ์ ๊น์ง ์ฌ์ฉํ ์ ์๋์ง์ ๋๊ตฌ์ ํ ํฐ์ธ์ง๋ฅผ ์ ์ ์๋๋ก 4๊ฐ์ ๊ตฌ์กฐ๋ฅผ ๋ง๋ จํ์์ต๋๋ค.
Create API
๊ทธ๋ผ ์์ ์ ๋ณด๋ฅผ ํ ๋๋ก API๋ฅผ ๋ง๋ค์ด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
POST ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ JSON์ id_token์ด๋ผ๋ key๋ก ๊ตฌ์กฐ๋ฅผ ์ผ๊ณ , ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญํ์ ๋ id_token ๊ฐ์ Google์์ ๋ฐ์ JWT ํ ํฐ์ ๋ฃ์ด์ ๋ฐฑ์๋๊ฐ ํ์ธํ ์ ์๋๋ก ๊ตฌํํด์ค๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๋ ์์์ ๋ง๋ ๊ตฌ์กฐ๋ฅผ ๋ฐํ์ผ๋ก 'secret' key๋ฅผ ์ด์ฉํ์ฌ base64๋ก ์ธ์ฝ๋ฉํ ๊ฐ์ ๋ฐํํด์ฃผ๋ฉด ํด๋น ๊ฐ์ ์ด์ฉํ์ฌ ํด๋ผ์ด์ธํธ๊ฐ ์ธ์ฆ์ด ํ์ํ ๋ฐฑ์๋ ์๋ํฌ์ธํธ๋ฅผ ํธ์ถํ ์ ์๋๋ก ํ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์ ์ฃผ์ํ ์ ์ payload์์ datetime์ ์ฌ์ฉํ๋ key์ ๊ฒฝ์ฐ exp์ iat๊ฐ ์์ต๋๋ค. ๋ง์ฝ ๋ ๊ฐ์ ํค๊ฐ ์๋ ๋ค๋ฅธ ํค์ string์ด ์๋ datetime์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํ์ฑ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฏ๋ก ๋ฐ๋์ ์ ํจ๊ธฐ๊ฐ์ ๋ช ์ํ ๋๋ exp์ iat ํค๋ฅผ ์ฌ์ฉํ์ฌ ์ธ์ฝ๋ฉํ๋๋ก ํฉ์๋ค.
๋ค์ ํฌ์คํธ์์ ์ธ์ฝ๋ฉํ์ฌ ๋ฐ์ ํ ํฐ์ ์ด๋ป๊ฒ ์ฌ์ฉํ ์ ์๋์ง์ ๋ํด ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.