๐Ÿ” | OAuth Authentication Flow (with supabase)

NewHaยท2024๋…„ 9์›” 16์ผ
post-thumbnail

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป Supabase๋กœ OAuth Login์„ ๊ตฌํ˜„ํ•˜๋ฉด์„œ Supabase์™€ OAuth ๊ณต๊ธ‰์ž ๊ฐ„ ํ†ต์‹ ๊ณผ, OAuth Login ๊ณผ์ •์— ๋Œ€ํ•ด ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ๊ณต๋ถ€ํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ์„ค์ •๊ณผ ๊ด€๋ จ๋œ ๊ฒŒ์‹œ๊ธ€์€ ์•„๋ž˜๋กœ ์ด๋™ํ•ด ์ฃผ์„ธ์š”.

๐ŸŒฑ OAuth

์š”์ฆ˜ ๋งŽ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ํšŒ์›๊ฐ€์ž…์„ ์š”๊ตฌํ•˜๊ธฐ๋„ ํ•˜์ง€๋งŒ, ์ด๋ฏธ ์‚ฌ์šฉ ์ค‘์ธ ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ์˜ ๊ณ„์ •์„ ํ†ตํ•ด ๊ฐ„ํŽธํ•˜๊ฒŒ ๊ฐ€์ž…ํ•˜๊ฑฐ๋‚˜ ๋กœ๊ทธ์ธํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹๋„ ํ•จ๊ป˜ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋งค๋ฒˆ ์ด๋ฆ„์ด๋‚˜ ์ด๋ฉ”์ผ ๊ฐ™์€ ์ •๋ณด๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ์ž…๋ ฅํ•˜์ง€ ์•Š์•„๋„ ๋˜๊ณ , ํด๋ฆญ ํ•œ ๋ฒˆ์œผ๋กœ ๋๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ๋งค์šฐ ํŽธ๋ฆฌํ•˜์ฃ .

์ด๋ ‡๊ฒŒ ํƒ€ ์‚ฌ์ดํŠธ์˜ ๊ณ„์ •์œผ๋กœ ๋‹ค๋ฅธ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด OAuth์ž…๋‹ˆ๋‹ค. OAuth๋Š” ๋‹ค๋ฅธ ์„œ๋น„์Šค๊ฐ€ ๋‚ด ๊ณ„์ • ์ •๋ณด์— ์•ˆ์ „ํ•˜๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, โ€˜๊ตฌ๊ธ€๋กœ ๋กœ๊ทธ์ธํ•˜๊ธฐโ€™ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์‚ฌ์šฉ์ž์˜ ๊ตฌ๊ธ€ ๊ณ„์ • ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ชฐ๋ผ๋„, ๊ตฌ๊ธ€์—์„œ ์ธ์ฆ๋œ ์ •๋ณด๋ฅผ ๋ฐ›์•„์™€ ์•ˆ์ „ํ•˜๊ฒŒ ๋กœ๊ทธ์ธ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ๋Š” ํŽธ๋ฆฌํ•จ์„, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ํŽธ์˜์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด, ํ”„๋กœ์ ํŠธ์—์„œ OAuth ์ธ์ฆ ๋ฐฉ์‹์„ ๊ตฌํ˜„ํ•˜๋ฉด์„œ OAuth 2.0์˜ ์ธ์ฆ ๊ณผ์ •์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  Supabase ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ OAuth๋ฅผ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š”์ง€๋ฅผ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค.

โ˜€๏ธ ๊ธฐ๋ณธ ๊ฐœ๋…

์•ž์œผ๋กœ ์„ค๋ช…ํ•  supabase์˜ ์ธ์ฆ ํ๋ฆ„์—์„œ ์“ฐ์ด๋Š” ๋ฐฉ์‹๊ณผ ์ธ์ฆ ์‹œ ์„œ๋ฒ„ ๊ฐ„ ํ†ต์‹ ์— ์“ฐ์ด๋Š” ๋‹ค์–‘ํ•œ ๊ฐœ๋…๋“ค์— ๋Œ€ํ•ด ๋จผ์ € ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1. OAuth Flow (์ธ์ฆ ํ๋ฆ„): Authorization Code Grant

OAuth 2.0์—์„œ๋Š” ์ฃผ๋กœ Authorization Code Grant์™€ Implicit Grant๏ผŠ ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

Supabase OAuth๋Š” ๊ทธ ์ค‘ Authorization Code Grant๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. OAuth 2.0์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ์ธ์ฆ ํ๋ฆ„ ์ค‘ ํ•˜๋‚˜๋กœ, ๋ณด์•ˆ์„ฑ์ด ๋›ฐ์–ด๋‚˜๊ณ  ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์„œ๋ฒ„ ๊ฐ„์˜ ํ†ต์‹ ์„ ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

ํŠน ์ง•

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ง์ ‘ ์ž๊ฒฉ ์ฆ๋ช…์„ ๋‹ค๋ฃจ์ง€ ์•Š๊ณ , ์ธ์ฆ ์ฝ”๋“œ(Authorization Code)๋ฅผ ํ†ตํ•ด ๋ณด์•ˆ์„ ์œ ์ง€ํ•˜๋ฉฐ ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›์Šต๋‹ˆ๋‹ค.

  • ์•ก์„ธ์Šค ํ† ํฐ์„ ์„œ๋ฒ„์—์„œ ์ฒ˜๋ฆฌํ•ด ์ž๊ฒฉ ์ฆ๋ช…์ด ๋…ธ์ถœ๋  ์œ„ํ—˜์ด ์ค„์–ด๋“ค๊ณ , ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ํด๋ผ์ด์–ธํŠธ ์ธก์— ๋…ธ์ถœํ•˜์ง€ ์•Š๋„๋ก ์„ค๊ณ„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์„œ๋ฒ„๊ฐ€ ํ† ํฐ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋ณด๊ด€ํ•˜๋Š” ๊ตฌ์กฐ๋กœ ํด๋ผ์ด์–ธํŠธ ์ธก์˜ ๋ณด์•ˆ ์œ„ํ—˜์ด ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

  • ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ํ†ตํ•ด ์•ก์„ธ์Šค ํ† ํฐ ๋งŒ๋ฃŒ์‹œ์— ์‚ฌ์šฉ์ž๋Š” ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•  ํ•„์š” ์—†์ด ์ƒˆ๋กญ๊ฒŒ ํ† ํฐ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • BUT, ๋‹ค๋ฅธ OAuth ํ๋ฆ„์— ๋น„ํ•ด ๋น„๊ต์  ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. Redirect URI, Client Secret๋“ฑ ์„ค์ •์ด ํ•„์š”ํ•˜๊ณ  ์„œ๋ฒ„๊ฐ€ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ†š

Implicit Grant

ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ฐ”๋กœ ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐ›๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์ธ์ฆ ์ ˆ์ฐจ๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์ด๋ฃจ์–ด์ง€๋ฉฐ ์„œ๋ฒ„์—์„œ ๊ถŒํ•œ ์ฝ”๋“œ๋ฅผ ๊ตํ™˜ํ•˜๋Š” ๊ณผ์ •์ด ์ƒ๋žต๋ฉ๋‹ˆ๋‹ค.
์„œ๋ฒ„๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ๋น ๋ฅด๊ณ  ๊ฐ„ํŽธํ•œ ๋Œ€์‹  ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ํ† ํฐ์„ ์ง์ ‘ ์ทจ๊ธ‰ํ•˜์—ฌ ์ƒ๋Œ€์ ์œผ๋กœ ๋ณด์•ˆ ์ˆ˜์ค€์ด ๋‚ฎ์Šต๋‹ˆ๋‹ค.
๐Ÿ‘‰๐Ÿป ๋ณด์•ˆ ๋ฌธ์ œ๋กœ ์ธํ•ด OAuth 2.0 ์ตœ์‹  ๊ถŒ๊ณ ์—์„œ๋Š” Implicit Grant ์‚ฌ์šฉ์„ ์ง€์–‘ํ•ฉ๋‹ˆ๋‹ค.

  • ํ† ํฐ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ๋ธŒ๋ผ์šฐ์ €๋‚˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ ํƒˆ์ทจ ์œ„ํ—˜์ด ํฌ๊ณ , ์•…์˜์  ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • URL์˜ ํ•ด์‹œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ๋˜์–ด ๋…ธ์ถœ๋˜๋Š” ์•ก์„ธ์Šค ํ† ํฐ์€ ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ก์—๋Š” ๋‚จ์ง€ ์•Š์ง€๋งŒ, ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ํƒˆ์ทจ๋  ์œ„ํ—˜์ด ์žˆ์–ด ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ๋”ฐ๋กœ ๋ฐœ๊ธ‰ํ•˜์ง€ ์•Š์•„, ์•ก์„ธ์Šค ํ† ํฐ ๋งŒ๋ฃŒ์‹œ์— ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค์‹œ ๋กœ๊ทธ์ธ์„ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ํ† ํฌ ๊ฐฑ์‹ ์„ ์œ„ํ•œ ์ถ”๊ฐ€์ ์ธ ๋ณด์•ˆ ์ ˆ์ฐจ๊ฐ€ ์—†์–ด ๋ณด์•ˆ ์ˆ˜์ค€์ด ๋‚ฎ์Šต๋‹ˆ๋‹ค.
  • ์ฃผ๋กœ ์„œ๋ฒ„๊ฐ€ ์—†๋Š” ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

ํŠน์ง•Authorization Code GrantImplicit Grant
๋ณด์•ˆ์„ฑ๋†’์Œ(์„œ๋ฒ„๊ฐ€ ํ† ํฐ์„ ์ฒ˜๋ฆฌ)๋‚ฎ์Œ(ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ† ํฐ์„ ์ฒ˜๋ฆฌ)
์„œ๋ฒ„ ํ•„์š” ์—ฌ๋ถ€ํ•„์š”๋ถˆํ•„์š”
์•ก์„ธ์Šค ํ† ํฐ ํš๋“ ๋ฐฉ์‹๊ถŒํ•œ ์ฝ”๋“œ๋ฅผ ๋ฐ›์€ ํ›„, ์„œ๋ฒ„์—์„œ ๊ตํ™˜ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ณง๋ฐ”๋กœ ๋ฐ›์Œ
๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์ง€์›ํ•˜๋ฏ€๋กœ ์•ก์„ธ์Šค ํ† ํฐ ๋งŒ๋ฃŒ์‹œ ๊ฐฑ์‹  ๊ฐ€๋Šฅ๋ฏธ์ง€์›
์‚ฌ์šฉ์‚ฌ๋ก€์„œ๋ฒ„ ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜SPA, ๋ชจ๋ฐ”์ผ ์•ฑ, ์„œ๋ฒ„์—†๋Š” ํด๋ผ์ด์–ธํŠธ
ํ† ํฐ ๋ณด์•ˆ์„œ๋ฒ„์—์„œ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ ๋ณด์•ˆ์ˆ˜์ค€์ด ๋†’์ŒURL ํ•ด์‹œ์— ๋…ธ์ถœ๋˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ด€๋ฆฌ
OAuth 2.0 ๊ถŒ๊ณ ์‚ฌํ•ญ๊ถŒ์žฅ์ง€์–‘

2. Redirect URI

ํด๋ผ์ด์–ธํŠธ์™€ OAuth ์„œ๋ฒ„ ๊ฐ„์˜ ํ†ต์‹  ๊ฒฝ๋กœ๋กœ, OAuth ์ œ๊ณต์ž(google, kakao ๋“ฑ)๊ฐ€ ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„, ์ธ์ฆ ์ฝ”๋“œ๋ฅผ ๋ณด๋‚ผ URI์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์ธ์ฆ ํ›„ OAuth ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋Œ์•„์˜ฌ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, supabase์™€ OAuth ๊ณต๊ธ‰์ž์— ๋™์ผํ•˜๊ฒŒ ์„ค์ •๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ, OAuth ๊ณต๊ธ‰์ž ์„ค์ •์˜ Redirect URI์™€ Supabase์˜ ์„ค์ •์ด ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด, OAuth๊ณผ์ •์ด ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.

์„ค์ • ์ด์œ 

  • OAuth ์ œ๊ณต์ž๋Š” ์ธ์ฆ ๊ฒฐ๊ณผ(์ธ์ฆ ์ฝ”๋“œ)๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋‹ค์‹œ ์ „์†กํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๋ฏธ๋ฆฌ ๋“ฑ๋ก๋œ Redirect URI๋กœ๋งŒ ์ธ์ฆ์ฝ”๋“œ๋ฅผ ์ „์†กํ•จ์œผ๋กœ์จ OAuth ๊ณต๊ฒฉ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์•ˆ์ „ํ•œ ํ†ต๋กœ์—ญํ• ์„ ํ•จ์œผ๋กœ์จ, ๋“ฑ๋ก๋˜์ง€ ์•Š์€ URI๋กœ redirect ์š”์ฒญ์„ ํ•˜๋ฉด ์ธ์ฆ์„ ๊ฑฐ๋ถ€ํ•จ์œผ๋กœ์จ ์•…์˜์ ์ธ ์ธ์ฆ ํƒˆ์ทจ ๋ฐ ์ •๋ณด ์œ ์ถœ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

  • OAuth 2.0 ๋ณด์•ˆ ์›์น™ ์ค‘ ํ•˜๋‚˜์ธ '์ธ์ฆ ๊ณผ์ •์—์„œ ๊ถŒํ•œ ์ฝ”๋“œ๋‚˜ ์•ก์„ธ์Šค ํ† ํฐ์ด ๋ฏธ๋ฆฌ ๋“ฑ๋ก๋œ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ๋กœ๋กœ๋งŒ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•œ๋‹ค'๋ฅผ ์ง€ํ‚ต๋‹ˆ๋‹ค.


3. Client ID & Client Secret

์„œ๋ฒ„ ๊ฐ„ ํ†ต์‹ ์—์„œ OAuth ์ œ๊ณต์ž๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹๋ณ„ํ•˜๊ณ  ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” ์ž๊ฒฉ ์ฆ๋ช…์ž…๋‹ˆ๋‹ค.

์„œ๋ฒ„ ๊ฐ„ ํ†ต์‹ ์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ๋…ธ์ถœ๋˜์–ด์„  ์•ˆ๋ฉ๋‹ˆ๋‹ค. ๋ณด๊ด€ํ•  ๋•Œ๋„ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋“ฑ์˜ ์•ˆ์ „ํ•œ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ด ๋ณด๊ด€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋…ธ์ถœ ์‹œ ๊ณต๊ฒฉ์ž๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๊ฐ€์žฅํ•˜์—ฌ OAuth ์ œ๊ณต์ž๋กœ๋ถ€ํ„ฐ ์•ก์„ธ์Šค ํ† ํฐ์„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ „์†ก์‹œ์—๋Š” ๋ฐ˜๋“œ์‹œ HTTPS๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ†š

Implicit Grant ํ๋ฆ„์—์„œ๋Š”, ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง์ ‘ Access Token์„ ์š”์ฒญํ•˜๋Š” ๋ฐฉ์‹์ด๊ธฐ ๋•Œ๋ฌธ์— Client Secret์ด ๋…ธ์ถœ๋  ์œ„ํ—˜์ด ์žˆ์–ด ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Client ID

Client ID๋Š” OAuth ์ œ๊ณต์ž๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” ๊ณ ์œ ํ•œ ์‹๋ณ„์ž๋กœ ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ID์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

OAuth ์ œ๊ณต์ž๋Š” ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž„์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ด ID๋ฅผ ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค. ์ธ์ฆ ์š”์ฒญ์‹œ ํŒŒ๋ผ๋ฏธํ„ฐ์— ํ•„์ˆ˜๋กœ ํฌํ•จ๋˜์–ด, ์ธ์ฆ์„ ๋ณด๋‚ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์–ด๋–ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ธ์ง€ ํŒŒ์•…ํ•˜๊ณ , ๋“ฑ๋ก๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

Client Secret

Client ID๋งŒ์œผ๋กœ๋Š” ๊ณต๊ฒฉ์ž๊ฐ€ ์‰ฝ๊ฒŒ ํด๋ผ์ด์–ธํŠธ๋กœ ์œ„์žฅํ•  ์ˆ˜ ์žˆ์–ด ์š”์ฒญ์„ ์™„์ „ํžˆ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋”์šฑ ์•ˆ์ „ํ•˜๊ฒŒ ์ธ์ฆํ•˜๊ธฐ ์œ„ํ•ด OAuth ์ œ๊ณต์ž๊ฐ€ ๋ฐœ๊ธ‰ํ•˜๋Š” ๋น„๋ฐ€ ํ‚ค์ž…๋‹ˆ๋‹ค.

์•ก์„ธ์Šค ํ† ํฐ์„ ์š”์ฒญํ•  ๋•Œ Client ID์™€ ํ•จ๊ป˜ ๋ณด๋‚ด์–ด ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž„์„ ์ฆ๋ช…ํ•˜๋Š” ๋ฐ ์“ฐ์ž…๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ—ˆ์œ„๋กœ Access Token์„ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.


4. Access Token (์•ก์„ธ์Šค ํ† ํฐ) & Refresh Token (๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ)

Supabase๋Š” Access Token๊ณผ Refresh Token์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ๋ณต์žกํ•œ ํ† ํฐ ๊ด€๋ฆฌ ์ž‘์—…์„ ํ•˜์ง€ ์•Š๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ๋กœ๊ทธ์ธ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ณ , ํ† ํฐ์„ ๊ฐฑ์‹ ํ•˜๋Š” ๊ณผ์ •์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

Access Token (์•ก์„ธ์Šค ํ† ํฐ)

  • ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‚ฌ์šฉ์ž์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณดํ˜ธ๋œ API๋กœ๋ถ€ํ„ฐ ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋Š” ๋‹จ๊ธฐ ์œ ํšจ ํ† ํฐ์ž…๋‹ˆ๋‹ค. ๋ณดํ†ต ๋ช‡ ๋ถ„์—์„œ ๋ช‡ ์‹œ๊ฐ„ ์ •๋„๋กœ ์œ ํšจ๊ธฐ๊ฐ„์ด ์งง์Šต๋‹ˆ๋‹ค.

  • API ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ ์ด ํ† ํฐ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž์˜ ๊ถŒํ•œ์„ ์ธ์ฆํ•ฉ๋‹ˆ๋‹ค. supabase๋Š” ์š”์ฒญ์‹œ ์•ก์„ธ์Šค ํ† ํฐ์„ ์ž๋™์œผ๋กœ ํฌํ•จ์‹œํ‚ต๋‹ˆ๋‹ค.

Refresh Token (๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ)

  • ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์€ ์•ก์„ธ์Šค ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์„ ๋•Œ, ์ƒˆ๋กœ์šด ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›๊ธฐ ์œ„ํ•œ ์žฅ๊ธฐ ์œ ํšจ ํ† ํฐ์ž…๋‹ˆ๋‹ค. ์œ ํšจ๊ธฐ๊ฐ„์ด ๊ธธ๋ฉฐ, ์‚ฌ์šฉ์ž๊ฐ€ ์žฌ๋กœ๊ทธ์ธํ•˜์ง€ ์•Š๊ณ ๋„ ์ธ์ฆ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ณดํ†ต ํด๋ผ์ด์–ธํŠธ ์ธก์— ์ €์žฅ๋˜๋ฉฐ,*Supabase๊ฐ€ ์ž๋™์œผ๋กœ ํ† ํฐ์„ ๊ฐฑ์‹ ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.


5. State parameter

์š”์ฒญ์ด ์™ธ๋ถ€์—์„œ ๋ณ€์กฐ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ณ  ์•ˆ์ „ํ•œ ์ธ์ฆ ๊ณผ์ •์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ์ž„์˜์˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.

Supabase๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์•”ํ˜ธํ™”๋œ ๋ฐฉ์‹์œผ๋กœ State ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ž๋™ ์ƒ์„ฑํ•˜์—ฌ OAuth ์ œ๊ณต์ž์—๊ฒŒ ํ•จ๊ป˜ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋Š” ์ง์ ‘์ ์œผ๋กœ State ๊ฐ’์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ฒ€์ฆํ•  ํ•„์š” ์—†์–ด ๋ถ€๋‹ด์ด ์ ์Šต๋‹ˆ๋‹ค.

State ๊ฐ’์€ ๊ณ ์œ ํ•˜๋ฉฐ ๊ฐ OAuth ์š”์ฒญ์— ๋Œ€ํ•ด ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ƒ์„ฑํ•˜์—ฌ ์š”์ฒญ์ด ๋„์ค‘์— ๋ณ€์กฐ๋˜๊ฑฐ๋‚˜ ๊ฐ€๋กœ์ฑ„์งˆ ๊ฐ€๋Šฅ์„ฑ์„ ์ฐจ๋‹จํ•ด ๋ณด์•ˆ ์œ„ํ˜‘์„ ์ตœ์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค. ๋˜ ์ธ์ฆ ๊ณผ์ • ์ค‘ ํด๋ผ์ด์–ธํŠธ๋Š” ์—ฌ๋Ÿฌ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ, ๊ฐ™์€ ์‚ฌ์šฉ์ž๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ์ธ์ฆ ์š”์ฒญ์„ ๋ณด๋‚ด๋”๋ผ๋„ ๊ฐ ์š”์ฒญ์€ ๊ณ ์œ ํ•œ State๊ฐ’์„ ๊ฐ€์ ธ ์–ด๋–ค ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์ธ์ง€ ์ถ”์ ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

OAuth ์ œ๊ณต์ž๊ฐ€ ๋ฆฌ๋””๋ ‰์…˜ ์š”์ฒญ์„ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋‹ค์‹œ ๋ณด๋‚ผ ๋•Œ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. supabase๋Š” ๋ฐ˜ํ™˜ํ•œ State ๊ฐ’์„ ๋‚ด๋ถ€์ ์œผ๋กœ ํ™•์ธํ•˜์—ฌ ์š”์ฒญ์ด ๋ณ€์กฐ๋˜์ง€ ์•Š์•˜๋Š” ์ง€ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์€ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์–ด ๋ณด์•ˆ ์ƒ์˜ ์‹ค์ˆ˜๋ฅผ ์˜ˆ๋ฐฉํ•ฉ๋‹ˆ๋‹ค.

ํŠนํžˆ State ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๊ณต๊ฒฉ์ž๊ฐ€ OAuth ์ธ์ฆ ํ๋ฆ„์„ ๊ฐ€๋กœ์ฑ„์„œ ์•…์˜์ ์ธ ์š”์ฒญ์„ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ณด๋‚ด๋Š” CSRF ๊ณต๊ฒฉ๏ผŠ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ค‘์š”ํ•œ ๋ณด์•ˆ์š”์†Œ์ž…๋‹ˆ๋‹ค. State ๊ฐ’์„ ํ†ตํ•ด OAuth ์ œ๊ณต์ž๊ฐ€ ์ „์†กํ•˜๋Š” ๋ฆฌ๋””๋ ‰์…˜์ด ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์ถœ์ฒ˜์—์„œ ์˜จ ๊ฒƒ์ž„์„ ํ™•์ธํ•ด ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ CSRF(Cross-Site Request Forgery) ๊ณต๊ฒฉ

์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ๊ถŒํ•œ์„ ์•…์šฉํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์˜๋„ํ•˜์ง€ ์•Š์€ ์š”์ฒญ์„ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ๊ณต๊ฒฉ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ ์ƒํƒœ๋ฅผ ์ด์šฉํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ง€ํ•˜์ง€ ๋ชปํ•œ ์ƒํƒœ์—์„œ ๋‹ค๋ฅธ ์›น์‚ฌ์ดํŠธ์—์„œ ์‚ฌ์šฉ์ž ๊ถŒํ•œ์œผ๋กœ ์„œ๋ฒ„์— ์ธ์ฆ๋œ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋กœ๊ทธ์ธ๋œ ์ƒํƒœ์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ ์ž๋™์œผ๋กœ ํ•ด๋‹น ๋„๋ฉ”์ธ์˜ ์ฟ ํ‚ค๋ฅผ ํ•จ๊ป˜ ์ „์†กํ•˜์—ฌ ์ธ์ฆ์„ ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์•…์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž์˜ ์ค‘์š”ํ•œ ๋ฐ์ดํ„ฐ(๊ณ„์ขŒ ์ด์ฒด, ์‚ฌ์šฉ์ž ์ •๋ณด ๋“ฑ)๋ฅผ ๊ณต๊ฒฉ์ž๊ฐ€ ๋งˆ์Œ๋Œ€๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž๋Š” ์š”์ฒญ ์‚ฌ์‹ค์„ ์ธ์ง€ํ•˜์ง€ ๋ชปํ•˜๋ฏ€๋กœ, ๊ณต๊ฒฉ์„ ์•Œ์•„์ฐจ๋ฆฌ๊ธฐ ํž˜๋“ญ๋‹ˆ๋‹ค.

๋ฐฉ์–ด๋ฐฉ๋ฒ•
์„œ๋ฒ„ ์ธก์—์„œ ์š”์ฒญ์ด ์ง„์งœ ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์˜จ ๊ฒƒ์ธ์ง€ ํ™•์ธํ•˜๋Š” ์ ˆ์ฐจ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฐฉ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • CSRF ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. CSRF ํ† ํฐ์€ ์„œ๋ฒ„์—์„œ ์ƒ์„ฑํ•œ ๊ณ ์œ ์˜ ๋‚œ์ˆ˜๋กœ, ์š”์ฒญ๋งˆ๋‹ค ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋‹ค์‹œ ์„œ๋ฒ„๋กœ ์ „์†กํ•จ์œผ๋กœ์จ ํ™•์ธํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
  • ์„œ๋ฒ„๋Š” ์š”์ฒญ์˜ Referer ํ—ค๋”์˜ ์ถœ์ฒ˜๋ฅผ ํ™•์ธํ•˜๊ณ , ์˜ฌ๋ฐ”๋ฅธ ์ถœ์ฒ˜์ธ ๊ฒฝ์šฐ์—๋งŒ ์‘๋‹ตํ•˜๊ณ , ๋‹ค๋ฅธ ์ถœ์ฒ˜๋ผ๋ฉด ์ฐจ๋‹จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ๋ธŒ๋ผ์šฐ์ € ์„ค์ •์ด๋‚˜ ํ”„๋ก์‹œ๋กœ Referer ํ—ค๋”๊ฐ€ ์ œ๊ฑฐ๋  ์ˆ˜ ์žˆ์–ด ์‹ ๋ขฐ๋„๊ฐ€ ๋‚ฎ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • SamSite ์ฟ ํ‚ค ์†์„ฑ์„ ์„ค์ •ํ•ด ์š”์ฒญ์ด ๋™์ผํ•œ ์‚ฌ์ดํŠธ์—์„œ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ฟ ํ‚ค๋ฅผ ์ „์†กํ•˜๋„๋ก ์ œํ•œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์™ธ๋ถ€ ์›น์‚ฌ์ดํŠธ์—์„œ ๋ฐœ์ƒํ•œ ์š”์ฒญ์—๋Š”์ฟ ๊ธฐ๊ฐ€ ์ž๋™์œผ๋กœ ์ „์†ก๋˜์ง€ ์•Š์•„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    Set-Cookie: sessionid=xyz; SameSite=Strict

โ˜€๏ธ Supabase OAuth Authentication Flow


๋ณธ๊ฒฉ์ ์œผ๋กœ supabase์—์„œ OAuth๋ฅผ ์‚ฌ์šฉํ•ด ๋กœ๊ทธ์ธํ•  ๋•Œ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ณผ์ •์„ ์•Œ์•„๋ด…๋‹ˆ๋‹ค. (์˜ˆ์‹œ๋Š” Kakao OAuth ์ธ์ฆ์œผ๋กœ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.)

STEP 1. OAuth ์ธ์ฆ ์„œ๋ฒ„๋กœ ์ธ์ฆ ์š”์ฒญ

์‚ฌ์šฉ์ž๊ฐ€ OAuth ์ œ๊ณต์ž๋กœ ๋กœ๊ทธ์ธํ•  ๋•Œ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ client_id, redirect_url, response_type=code(์ธ์ฆ ์ฝ”๋“œ ์š”์ฒญ), scope(์š”์ฒญ ๊ถŒํ•œ ๋ฒ”์œ„), state๋ฅผ ํฌํ•จํ•˜์—ฌ OAuth ์ธ์ฆ ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

https://kauth.kakao.com/oauth/authorize?
  response_type=code&
  client_id={CLIENT_ID}&
  redirect_uri=https://{application address}/callback&
  scope=profile,email

๐Ÿ‘‡๐Ÿป Kakao OAuth๋ฅผ ์š”์ฒญํ•  ๋•Œ์˜ ์„œ๋ฒ„ ํ†ต์‹  ๋ชจ์Šต์„ ๋ณด๋ฉด ํ†ต์‹ ์„ ํ•˜๋Š” OAuth ์ œ๊ณต์ž ์„œ๋ฒ„๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ณ , client_id, redirect_uri, response_type=code, scope, state์™€ ๊ฐ™์€ ์ •๋ณด๋ฅผ ํ•จ๊ป˜ ๋ณด๋‚ด๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • OAuth 2.0์€ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์ฃผ๊ณ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— HTTPS๋ฅผ ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์•ก์„ธ์Šค ํ† ํฐ์ด๋‚˜ ์ธ์ฆ ์ฝ”๋“œ๊ฐ€ ๊ณต๊ฒฉ์ž์—๊ฒŒ ๋…ธ์ถœ๋  ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • redirect_uri๋Š” ์‚ฌ์ „ ๋“ฑ๋ก๋œ URI์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • State ๊ฐ’(eyJhb~)์€ ์ž๋™์œผ๋กœ supabase๊ฐ€ ์ž„์˜๋กœ ์ƒ์„ฑํ•˜์—ฌ ํฌํ•จ์‹œํ‚ต๋‹ˆ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ OAuth ์ œ๊ณต์ž์—๊ฒŒ ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋„๋ก ๋ฆฌ๋””๋ ‰์…˜ํ•ฉ๋‹ˆ๋‹ค.


STEP 2. ์‚ฌ์šฉ์ž๊ฐ€ ๊ถŒํ•œ์„ ๋ถ€์—ฌ & ์ธ์ฆ ์ฝ”๋“œ ๋ฐœ๊ธ‰

์‚ฌ์šฉ์ž๊ฐ€ OAuth ์ œ๊ณต์ž์—์„œ ์ธ์ฆ์„ ์™„๋ฃŒํ•˜๋ฉด, OAuth ์„œ๋ฒ„๋Š” ์ธ์ฆ ์ฝ”๋“œ(Authorization Code)์™€ ์ดˆ๊ธฐ ์š”์ฒญ์‹œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ณด๋ƒˆ๋˜ state ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํฌํ•จํ•ด ๋“ฑ๋ก๋œ Redirect URI๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•ฉ๋‹ˆ๋‹ค.

https://{application address}/callback?code={AUTHORIZATION_CODE}&state={STATE_VALUE}

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋ฆฌ๋””๋ ‰์…˜๋œ URI์—์„œ ๋ฐ›์€ state๊ฐ’์„ ์ฒ˜์Œ ์ƒ์„ฑํ•œ ๊ฐ’๊ณผ ๋น„๊ต ๊ฒ€์ฆํ•ด CSRF ๊ณต๊ฒฉ๊ณผ ๋ณ€์กฐ๋œ ์š”์ฒญ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. (STEP 1์˜ ์˜ˆ์‹œ ์‚ฌ์ง„์† state์™€ ๊ฐ™์€ ๊ฐ’์œผ๋กœ eyJhb~์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

    • ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ, ์š”์ฒญ์ด ๋ณ€์กฐ๋˜์—ˆ๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์ถœ์ฒ˜์—์„œ ๋ฐœ์ƒํ•œ ์š”์ฒญ์ผ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์–ด supabase๋Š” ํ•ด๋‹น ์š”์ฒญ์„ ๊ฑฐ๋ถ€ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ธ์ฆ ์„œ๋ฒ„๊ฐ€ ๋ฐœ๊ธ‰ํ•œ ์ธ์ฆ ์ฝ”๋“œ๋Š” ์ผํšŒ์šฉ์ด๋ฉฐ, ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ๋งŒ๋ฃŒ๋ฉ๋‹ˆ๋‹ค.


STEP 3. ์ธ์ฆ ์ฝ”๋“œ๋ฅผ ์•ก์„ธ์Šค ํ† ํฐ์œผ๋กœ ๊ตํ™˜

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ „๋‹ฌ๋ฐ›์€ ์ธ์ฆ ์ฝ”๋“œ๋ฅผ ์„œ๋ฒ„(supabase)๋กœ ์ „๋‹ฌํ•˜๊ณ , ์„œ๋ฒ„๋Š” ์ด ์ธ์ฆ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ด OAuth ์ œ๊ณต์ž(kakao)์—๊ฒŒ ์•ก์„ธ์Šค ํ† ํฐ๊ณผ ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ์š”์ฒญํ•˜๋Š” POST ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
POST /token
Host: oauth.provider.com
Content-Type: application/x-www-form-urlencoded
------------------------------
grant_type=authorization_code&
code={AUTHORIZATION_CODE}&
redirect_uri=https://{application address}/callback&
client_id={CLIENT_ID}&
client_secret={CLIENT_SECRET}
  • ์š”์ฒญ์‹œ Redirect URI๋ฅผ ํ•จ๊ป˜ ์ „๋‹ฌํ•ด, OAuth ์„œ๋ฒ„๊ฐ€ ์ตœ์ดˆ์— ์‚ฌ์šฉํ•œ URI์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ ๋™์ผํ•˜์ง€ ์•Š์œผ๋ฉด ์š”์ฒญ์„ ๊ฑฐ๋ถ€ํ•จ์œผ๋กœ์จ ๊ถŒํ•œ ์ฝ”๋“œ ๋‚จ์šฉ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

  • ํ† ํฐ ์š”์ฒญ ์‹œ์—๋Š” Client_id์™€ Client_secret์ด ํ•จ๊ป˜ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด OAuth ์ œ๊ณต์ž์—๊ฒŒ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž„์„ ์ฆ๋ช…ํ•˜๊ณ , ๋“ฑ๋ก๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž„์„ ํ™•์ธํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

  • ์ด ๋•Œ, ์ž˜๋ชป๋œ Client_id, Client_secret์„ ์‚ฌ์šฉํ•ด ์ž๊ฒฉ ์ฆ๋ช…์ด ์•ˆ๋˜๊ฑฐ๋‚˜, ์ž˜๋ชป๋œ redirect_uri๋ฅผ ์„ค์ •ํ•œ ๊ฒฝ์šฐ, ์ธ์ฆ ์ฝ”๋“œ๊ฐ€ ์ž˜๋ชป๋˜์–ด ์ธ์ฆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ ์ธ์ฆ ์‹คํŒจ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SETP 4. ์•ก์„ธ์Šค ํ† ํฐ๊ณผ ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ ๋ฐ›๊ธฐ

OAuth ์ œ๊ณต์ž๋Š” ์š”์ฒญ์„ ๊ฒ€์ฆํ•˜๊ณ , ์œ ํšจํ•˜๋‹ค๋ฉด ์•ก์„ธ์Šค ํ† ํฐ๊ณผ ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.

  • expires_at์€ ํ† ํฐ์˜ ๋ฐœ๊ธ‰ ์ผ์‹œ์ž…๋‹ˆ๋‹ค. expires_in์€ ์•ก์„ธ์Šค ํ† ํฐ์˜ ์œ ํšจ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค.

  • ์•ก์„ธ์Šค ํ† ํฐ์€ ์‚ฌ์šฉ์ž์˜ ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๊ณ , ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์€ ์•ก์„ธ์Šค ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์„ ๋•Œ ์ƒˆ๋กœ์šด ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„(supabase)๋Š” ๋ฐ›์€ ์•ก์„ธ์Šค ํ† ํฐ์„ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ๋ณดํ˜ธ๋œ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. OAuth ์ œ๊ณต์ž(kakao)๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(client)์— ์ „๋‹ฌํ•ด ์ธ์ฆ๋œ ์„ธ์…˜์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.



โ˜€๏ธ Post-Authentication (์ธ์ฆ ํ›„)

Supabase๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธํ•œ ํ›„, ํ•ด๋‹น ์‚ฌ์šฉ์ž์˜ ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐ›์•„ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ํ† ํฐ์˜ ์œ ํšจ์„ฑ์ด๋‚˜ ๋งŒ๋ฃŒ์— ๋Œ€ํ•ด ์‹ ๊ฒฝ ์“ธ ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ, ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ณ„๋„๋กœ ์ฒ˜๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

ํ† ํฐ ์•ˆ์ „ ์ €์žฅ

ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์•ก์„ธ์Šค ํ† ํฐ๊ณผ ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ์•ˆ์ „ํ•˜๊ฒŒ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ์•ก์„ธ์Šค ํ† ํฐ์€ ํด๋ผ์ด์–ธํŠธ์—์„œ API ํ˜ธ์ถœ ์‹œ ์‚ฌ์šฉ๋˜๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์ €์žฅ ๋ฐฉ์‹์— ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ž˜๋ชป๋œ ์ €์žฅ ๋ฐฉ์‹์€ ํ† ํฐ ํƒˆ์ทจ๋กœ ์ด๋ฃจ์–ด์งˆ ์ˆ˜ ์žˆ๊ณ , ํ† ํฐ์ด ์œ ์ถœ๋˜๋ฉด ์ œ3์ž๊ฐ€ ์‚ฌ์šฉ์ž์˜ ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์•ˆ์ „ํ•œ ์ €์žฅ ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

(1) Local Storage ๋˜๋Š” Session Storage

  • Local Storage๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋‹ซ์•„๋„ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ณต๊ฐ„์ž…๋‹ˆ๋‹ค. Session Storage๋Š” ๋ธŒ๋ผ์šฐ์ € ์„ธ์…˜์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • Local Storage๋Š” XSS(ํฌ๋กœ์Šค ์‚ฌ์ดํŠธ ์Šคํฌ๋ฆฝํŒ…) ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์•ก์„ธ์Šค ํ† ํฐ๊ณผ ๊ฐ™์€ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ Local Storage์— ์ €์žฅํ•˜๋Š” ๊ฒƒ์€ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

(2) HTTP-Only ์ฟ ํ‚ค

  • HTTP-Only ์ฟ ํ‚ค๋Š” ์•ˆ์ „ํ•œ ์ €์žฅ์†Œ๋กœ XSS ๊ณต๊ฒฉ์œผ๋กœ๋ถ€ํ„ฐ ๋ณดํ˜ธํ•  ์ˆ˜ ์žˆ๋Š” ๋” ์•ˆ์ „ํ•œ ์˜ต์…˜์ž…๋‹ˆ๋‹ค. ์ด ์ฟ ํ‚ค๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, ์ž๋™์œผ๋กœ ์„œ๋ฒ„๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ HTTP-Only ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Access Token๊ณผ Refresh Token์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ† ํฐ ๋งŒ๋ฃŒ ๊ด€๋ฆฌ

  • ์•ก์„ธ์Šค ํ† ํฐ์ด ๋งŒ๋ฃŒ๋œ ๊ฒฝ์šฐ, ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ์‚ฌ์šฉํ•ด ์ƒˆ๋กœ์šด ์•ก์„ธ์Šค ํ† ํฐ์„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ, ๊ถŒํ•œ ๋ฒ”์œ„(scope)๋ฅผ ์ตœ์†Œํ•œ์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ํ•„์š”ํ•œ ๊ถŒํ•œ๋งŒ ์š”์ฒญํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜๊ฑฐ๋‚˜ ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜๋กœ ๊ฐฑ์‹  ๊ณผ์ •์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ, Supabase๋Š” ์‚ฌ์šฉ์ž๋ฅผ ๋กœ๊ทธ์•„์›ƒ ์ฒ˜๋ฆฌํ•˜๊ณ , ์žฌ๋กœ๊ทธ์ธ์„ ์œ ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • OAuth ํ† ํฐ์„ ์ฃผ๊ณ ๋ฐ›์„ ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ HTTPS๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋„คํŠธ์›Œํฌ ์ƒ์—์„œ ํ† ํฐ์ด ๋…ธ์ถœ๋˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

(1) ์•ก์„ธ์Šค ํ† ํฐ ๋งŒ๋ฃŒ

์•ก์„ธ์Šค ํ† ํฐ์€ ๋ณดํ†ต ์งง์€ ์œ ํšจ ๊ธฐ๊ฐ„์„ ๊ฐ€์ง€๋ฉฐ, ๋งŒ๋ฃŒ๋œ ํ›„์—๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์•ก์„ธ์Šค ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜๋ฉด, ์‚ฌ์šฉ์ž๊ฐ€ ๋ณดํ˜ธ๋œ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•˜๋ ค ํ•  ๋•Œ 401 Unauthorized ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

Supabase๋Š” ์ด๋Ÿฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ๋งŒ๋ฃŒ๋˜๋ฉด ์ž๋™์œผ๋กœ ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ์‚ฌ์šฉํ•ด ์ƒˆ๋กœ์šด ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›์Šต๋‹ˆ๋‹ค.

์ด ์ž๋™ํ™”๋œ ๊ณผ์ •์—์„œ, Supabase๊ฐ€ ํ† ํฐ ๋งŒ๋ฃŒ ์‹œ๊ฐ„์ด ๋‹ค๊ฐ€์˜ค๊ธฐ ์ „์— ๋ฏธ๋ฆฌ ์žฌ์ธ์ฆ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

์•ก์„ธ์Šค ํ† ํฐ์ด ๋งŒ๋ฃŒ๋œ ํ›„, API ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋„์ค‘์— ์•ก์„ธ์Šค ํ† ํฐ์ด ๋งŒ๋ฃŒ๋œ ๊ฒƒ์„ ๊ฐ์ง€ํ•˜๋ฉด, ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ์‚ฌ์šฉํ•ด OAuth ์ œ๊ณต์ž์—๊ฒŒ ์ƒˆ๋กœ์šด ์•ก์„ธ์Šค ํ† ํฐ์„ ์š”์ฒญํ•˜๊ณ  ์ƒˆ๋กญ๊ฒŒ ๋ฐœ๊ธ‰๋ฐ›์•„ ์‚ฌ์šฉ์ž ์„ธ์…˜์„ ๊ฐฑ์‹ ํ•ด ๋กœ๊ทธ์ธ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

(2) ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ ๋งŒ๋ฃŒ

๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์€ ์žฅ๊ธฐ์ ์œผ๋กœ ์œ ํšจํ•˜์ง€๋งŒ, ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์•„์›ƒํ•˜๊ฑฐ๋‚˜ ๋ณด์•ˆ์ƒ์˜ ์ด์œ ๋กœ ๋งŒ๋ฃŒ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜๋ฉด ์ƒˆ๋กœ์šด ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์—†์œผ๋ฉฐ, ์‚ฌ์šฉ์ž๋Š” ๋กœ๊ทธ์•„์›ƒ ์ƒํƒœ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์ด ๋งŒ๋ฃŒ๋œ ์ƒํƒœ์—์„œ๋Š” ์„ธ์…˜์„ ๋ณต๊ตฌํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ํด๋ผ์ด์–ธํŠธ๋Š” ์‚ฌ์šฉ์ž๋ฅผ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•˜์—ฌ ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•˜๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

(3) ์ž๋™ ๋กœ๊ทธ์•„์›ƒ ์ฒ˜๋ฆฌ

๋งŒ์•ฝ Access Token๊ณผ Refresh Token ๋ชจ๋‘ ๋งŒ๋ฃŒ๋œ ๊ฒฝ์šฐ, Supabase๋Š” ์ž๋™์œผ๋กœ ์„ธ์…˜์„ ์ข…๋ฃŒํ•˜๊ณ , ์‚ฌ์šฉ์ž๋ฅผ ๋กœ๊ทธ์•„์›ƒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ด๋Ÿฌํ•œ ๋กœ๊ทธ์•„์›ƒ ์ƒํ™ฉ์„ ๊ฐ์ง€ํ•˜๊ณ , ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

supabase.auth.onAuthStateChange((event, session) => {
  if (event === 'SIGNED_OUT') {
    console.log('์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์•„์›ƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.');
    window.location.href = '/login';  // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋””๋ ‰์…˜
  }
});
  • onAuthStateChange: Supabase๋Š” ์ธ์ฆ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. ์ด ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์•„์›ƒ๋˜์—ˆ์„ ๋•Œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โ›“๏ธโ€๐Ÿ’ฅ

์ˆ˜๋™ ๋กœ๊ทธ์•„์›ƒ

Supabase๋Š” ์ž๋™์œผ๋กœ ํ† ํฐ ๊ฐฑ์‹ ์„ ์ฒ˜๋ฆฌ๋ฏ€๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์•„์›ƒํ•˜์ง€ ์•Š๋Š” ํ•œ ๋กœ๊ทธ์ธ ์„ธ์…˜์ด ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋กœ๊ทธ์•„์›ƒํ•  ๋•Œ๋Š” ์•ก์„ธ์Šค ํ† ํฐ๊ณผ ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ๋ชจ๋‘ ์‚ญ์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • Supabase๋Š” auth.signOut() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์„ธ์…˜์„ ์ข…๋ฃŒํ•˜๊ณ , ๊ด€๋ จ ํ† ํฐ์„ ๋ฌดํšจํ™”ํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ๋” ์ด์ƒ ๋ณดํ˜ธ๋œ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋„๋ก ๋งŒ๋“ญ๋‹ˆ๋‹ค.
await supabase.auth.signOut();

Error handling

OAuth ์ธ์ฆ ๊ณผ์ •์—์„œ ํ†ต์‹  ์ค‘ ์ธ์ฆ ์‹คํŒจ, ํ† ํฐ ๋งŒ๋ฃŒ ๋“ฑ์˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์˜ค๋ฅ˜๋Š” ์•ก์„ธ์Šค ํ† ํฐ์˜ ๋งŒ๋ฃŒ, ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์˜ ์œ ํšจ์„ฑ ๋ฌธ์ œ, ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ๋“ฑ ๋‹ค์–‘ํ•œ ์ด์œ ๋กœ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋ฉด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ํ–ฅ์ƒ์‹œํ‚ค๊ณ  ๋ณด์•ˆ์„ ์œ ์ง€ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

Supabase์—์„œ ์ด๋Ÿฌํ•œ ์˜ค๋ฅ˜๋“ค์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์ง€๋งŒ, ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋„ ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์ ์ ˆํžˆ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋กœ์ง์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ธ์ฆ ์‹คํŒจ ์ฒ˜๋ฆฌ

OAuth ์ธ์ฆ ๊ณผ์ •์—์„œ ์ธ์ฆ ์‹คํŒจ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž˜๋ชป๋œ ํด๋ผ์ด์–ธํŠธ ์ž๊ฒฉ ์ฆ๋ช…์ด๋‚˜ ์„ค์ • ์˜ค๋ฅ˜๊ฐ€ ์›์ธ์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ธ์ฆ ์‹คํŒจ ์‹œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ , ๋‹ค์‹œ ์‹œ๋„ํ•˜๊ฑฐ๋‚˜ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์œ ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const { data, error } = await supabase.auth.signInWithOAuth({
  provider: 'kakao',
  options: {
    redirectTo: 'https://{application address}/callback',
  }
});

if (error) {
  console.error("์ธ์ฆ ์‹คํŒจ:", error.message);
  alert("์ธ์ฆ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด ์ฃผ์„ธ์š”.");
} else {
  console.log("์ธ์ฆ ์„ฑ๊ณต:", data);
}

์ด ๋–„, ๊ฐœ๋ฐœ์ž๋Š” ์ž˜๋ชป๋œ Client ID, Client Secret, Redirect URI ์„ค์ •์„ ์ ๊ฒ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ

๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜๋Š” ์ผ์‹œ์ ์ธ ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์žฌ์‹œ๋„ ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ ๋ถˆ์•ˆ์ •์œผ๋กœ ์ธํ•ด ์š”์ฒญ์ด ์‹คํŒจํ•˜๋ฉด, ์š”์ฒญ์„ ๋‹ค์‹œ ์‹œ๋„ํ•˜๊ฑฐ๋‚˜ ์ผ์ • ์‹œ๊ฐ„ ํ›„์— ๋‹ค์‹œ ์‹œ๋„ํ•˜๋„๋ก ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ‘€ ์ถ”๊ฐ€๋กœ, User Agent

supabase์—์„œ log๋กœ OAuth ํ†ต์‹ ์„ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ, ์š”์ฒญ URL ๋’ค์— ์žˆ๋Š” ๋ถ€๋ถ„์ด User Agent ์ž…๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•  ๋•Œ, ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋””๋ฐ”์ด์Šค์™€ ๋ธŒ๋ผ์šฐ์ € ๋“ฑ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ์šฉ์ž ์†Œํ”„ํŠธ์›จ์–ด์˜ ์ •๋ณด๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ž„์˜๋กœ ์ˆ˜์ •๋  ์ˆ˜ ์—†๋Š” ๊ฐ’์œผ๋กœ, ์š”์ฒญ์„ ๋ณด๋‚ธ ์‚ฌ์šฉ์ž ํ™˜๊ฒฝ์„ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์˜ ๋„คํŠธ์›Œํฌ์—์„œ Request Headers์—์„œ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์„œ๋ฒ„๋Š” User Agent๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์–ด๋–ค ๋ธŒ๋ผ์šฐ์ €๋‚˜ ์•ฑ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ํŒŒ์•…ํ•ด, ๋ชจ๋ฐ”์ผ ๊ธฐ๊ธฐ์™€ ๋ฐ์Šคํฌํƒ‘์„ ๊ตฌ๋ถ„ํ•˜์—ฌ ๊ฐ๊ธฐ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๊ณ , ํŠน์ • ๋ธŒ๋ผ์šฐ์ €์— ์ตœ์ ํ™”๋œ ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๊ณตํ•˜๊ฑฐ๋‚˜ ํŠน์ • ๊ธฐ๋Šฅ์„ ์ฐจ๋‹จํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ํ•ฉ๋‹ˆ๋‹ค.

  • ๋กœ๊ทธ์— ์š”์ฒญ๋งˆ๋‹ค User Agent๊ฐ€ ๊ธฐ๋ก๋˜๋ฏ€๋กœ, ์„œ๋ฒ„ ๊ด€๋ฆฌ์ž๋Š” ํด๋ผ์ด์–ธํŠธ ์ข…๋ฅ˜์™€ ๋ฒ„์ „ ๋ถ„ํฌ๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ ์‹œ

๋ณดํ†ต Mozilla ์ •๋ณด/๋ฒ„์ „ + ์šด์˜์ฒด์ œ ์ •๋ณด + ๋ Œ๋”๋ง ์—”์ง„ ์ •๋ณด + ๋ธŒ๋ผ์šฐ์ € ํ˜•ํƒœ๋กœ ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36
  • Mozila/5.0: User Agent ๋ฌธ์ž์—ด์˜ ์ผ๋ฐ˜์ ์ธ ์‹œ์ž‘ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์ ‘์†ํ•œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ Mozila์™€ ํ˜ธํ™˜๋จ์„ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋Œ€๋ถ€๋ถ„์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  • (Linux; Android 6.0; Nexus 5 Build/MRA58N)
    • Linux: ์š”์ฒญ์„ ๋ณด๋‚ธ ์žฅ์น˜์˜ ์šด์˜ ์ฒด์ œ๊ฐ€ Linux ๊ธฐ๋ฐ˜์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. Android๋Š” Linux ์ปค๋„ ์œ„์—์„œ ์‹คํ–‰๋˜๋ฏ€๋กœ ์ด ๋ถ€๋ถ„์€ Android ์šด์˜ ์ฒด์ œ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
    • Android 6.0: Android ์šด์˜ ์ฒด์ œ์˜ ๋ฒ„์ „์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
    • Nexus 5: ์žฅ์น˜์˜ ๋ชจ๋ธ๋กœ Google Nexus 5 ์Šค๋งˆํŠธํฐ์—์„œ ๋ฐœ์ƒํ•œ ์š”์ฒญ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
    • Build/MRA58N: ํ•ด๋‹น Android ์šด์˜ ์ฒด์ œ์˜ ํŠน์ • ๋นŒ๋“œ ๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค.
  • AppleWebKit/537.36 (KHTML, like Gecko)
    • AppleWebKit/537.36: HTML ๋ฐ CSS๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๋ Œ๋”๋ง ์—”์ง„์ธ WebKit์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. Safari์™€ Chrome ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
    • (KHTML, like Gecko): ์ด ๋ฌธ์ž์—ด์€ ๊ณผ๊ฑฐ KHTML๊ณผ Gecko ์—”์ง„๊ณผ์˜ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. KHTML์€ ์›๋ž˜ Konqueror ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์šฉ๋œ ์—”์ง„์ด๋ฉฐ, Gecko๋Š” Mozilla Firefox์˜ ๋ Œ๋”๋ง ์—”์ง„์ž…๋‹ˆ๋‹ค. ์ด๋Š” WebKit์ด Gecko์ฒ˜๋Ÿผ ๋™์ž‘ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • Chrome/128.0.0.0: ์‚ฌ์šฉ ์ค‘์ธ ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ Chrome ๋ธŒ๋ผ์šฐ์ €์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. 128.0.0.0์€ Chrome ๋ธŒ๋ผ์šฐ์ €์˜ ๋ฒ„์ „์œผ๋กœ ์ผ๋ฐ˜์ ์œผ๋กœ ์ตœ์‹  ๋ฒ„์ „์˜ Chrome์ด 100 ์ด์ƒ์œผ๋กœ, 128 ๋ฒ„์ „์€ ์ตœ์‹  ๋ฒ„์ „์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • Mobile Safari/537.36: Safari ๋ธŒ๋ผ์šฐ์ €์˜ ๋ชจ๋ฐ”์ผ ๋ฒ„์ „๊ณผ ํ˜ธํ™˜์„ฑ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. WebKit ๊ธฐ๋ฐ˜์˜ ๋ธŒ๋ผ์šฐ์ €๋Š” ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด Safari์˜ User-Agent ๋ฌธ์ž์—ด์„ ํฌํ•จํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.
profile
๋ฐฑ ๋ฒˆ์„ ๋ณด๋ฉด ํ•œ ๊ฐ€์ง€๋Š” ์•ˆ๋‹ค ๐Ÿ‘€

0๊ฐœ์˜ ๋Œ“๊ธ€