๋ชจ๋ฐ์ผ ์ฑ์์์ OAuth 2.0 ๊ตฌํ ๊ฐ์ด๋: Deep Linking๊ณผ Secure Storage ํ์ฉ
1. ๋ชจ๋ฐ์ผ ์ฑ์์ OAuth 2.0์ ์ค์์ฑ
๋ชจ๋ฐ์ผ ์ฑ์ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๊ธฐ ์ํด ์์ ๋ก๊ทธ์ธ๊ณผ API ์ธ์ฆ ์ ์์ฃผ ์ฌ์ฉํฉ๋๋ค. ์ด๋ OAuth 2.0 ์ ํตํด ์์ ํ๊ฒ ์ธ์ฆ ๋ฐ ๊ถํ ๋ถ์ฌ ๋ฅผ ์ํํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ฐ์ผ ํ๊ฒฝ์์๋ ํ ํฐ ์ ์ฅ ๋ฐฉ์๊ณผ ๋ฆฌ๋ค์ด๋ ํธ ์ฒ๋ฆฌ ์ ์ฃผ์ํด์ผ ํฉ๋๋ค.
2. Deep Linking๊ณผ Redirect ์ฒ๋ฆฌ
Deep Linking์ด๋?
Deep Linking ์ ์ฑ ๋ด๋ถ์ ํน์ ํ์ด์ง๋ก ์ฌ์ฉ์๋ฅผ ๋ฐ๋ก ์ฐ๊ฒฐํ๋ ๋ฐฉ์์ ๋๋ค. OAuth ๋ก๊ทธ์ธ ํ ์ฌ์ฉ์๋ฅผ ๋ค์ ์ฑ์ผ๋ก ๋ฆฌ๋๋ ์ ํ ๋ Deep Linking ์ด ํ์ํฉ๋๋ค.
Android์์ Deep Link ์ค์ ์์
<!-- AndroidManifest.xml -->
<activity android:name=".MainActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" android:host="oauth" />
</intent-filter>
</activity>
1. ๋ชจ๋ฐ์ผ ์ฑ์์ OAuth 2.0์ ์ค์์ฑ
๋ชจ๋ฐ์ผ ์ฑ์ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๊ธฐ ์ํด ์์ ๋ก๊ทธ์ธ๊ณผ API ์ธ์ฆ ์ ์์ฃผ ์ฌ์ฉํฉ๋๋ค. ์ด๋ OAuth 2.0 ์ ํตํด ์์ ํ๊ฒ ์ธ์ฆ ๋ฐ ๊ถํ ๋ถ์ฌ ๋ฅผ ์ํํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ฐ์ผ ํ๊ฒฝ์์๋ ํ ํฐ ์ ์ฅ ๋ฐฉ์๊ณผ ๋ฆฌ๋ค์ด๋ ํธ ์ฒ๋ฆฌ ์ ์ฃผ์ํด์ผ ํฉ๋๋ค.
2. Deep Linking๊ณผ Redirect ์ฒ๋ฆฌ
Deep Linking์ด๋?
Deep Linking ์ ์ฑ ๋ด๋ถ์ ํน์ ํ์ด์ง๋ก ์ฌ์ฉ์๋ฅผ ๋ฐ๋ก ์ฐ๊ฒฐํ๋ ๋ฐฉ์์ ๋๋ค. OAuth ๋ก๊ทธ์ธ ํ ์ฌ์ฉ์๋ฅผ ๋ค์ ์ฑ์ผ๋ก ๋ฆฌ๋๋ ์ ํ ๋ Deep Linking ์ด ํ์ํฉ๋๋ค.
Android์์ Deep Link ์ค์ ์์
<!-- AndroidManifest.xml -->
<activity android:name=".MainActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" android:host="oauth" />
</intent-filter>
</activity>
iOS์์ Deep Link ์ค์ ์์
// SceneDelegate.swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
if let url = URLContexts.first?.url {
print("Deep Link URL: \(url)")
// OAuth ๋ฆฌ๋ค์ด๋ ํธ ์ฒ๋ฆฌ ๋ก์ง
}
}
์ค๋ช
:
- Android์ iOS ๋ชจ๋ OAuth ์ธ์ฆ ํ ์ฑ์ผ๋ก ๋ฆฌ๋ค์ด๋ ํธ ํ๋ Deep Link๋ฅผ ์ค์ ํด์ผ ํฉ๋๋ค.
- ์ฌ์ฉ์๊ฐ ์ธ์ฆ์ ์๋ฃํ๋ฉด
myapp://oauth
๊ฒฝ๋ก๋ก ์ด๋ํฉ๋๋ค.
3. Secure Storage์ ํ ํฐ ์ ์ฅํ๊ธฐ
์ Secure Storage๊ฐ ํ์ํ๊ฐ?
๋ชจ๋ฐ์ผ ์ฑ์์๋ Access Token๊ณผ Refresh Token ์ด ํ์ทจ๋์ง ์๋๋ก ๋ณด์ ์ ์ฅ์ ์ ์ ์ฅํด์ผ ํฉ๋๋ค. Android์ iOS์์ Secure Storage ๋ฅผ ํ์ฉํด ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ๋ณดํธํฉ๋๋ค.
Android์์ Secure Storage ์ฌ์ฉ ์์
val sharedPreferences = getSharedPreferences("auth_prefs", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
// ํ ํฐ ์ ์ฅ
editor.putString("access_token", "your_access_token")
editor.apply()
// ํ ํฐ ๊ฐ์ ธ์ค๊ธฐ
val accessToken = sharedPreferences.getString("access_token", null)
iOS์์ Secure Storage ์ฌ์ฉ ์์
import KeychainAccess
let keychain = Keychain(service: "com.example.myapp")
// ํ ํฐ ์ ์ฅ
keychain["access_token"] = "your_access_token"
// ํ ํฐ ๊ฐ์ ธ์ค๊ธฐ
if let accessToken = keychain["access_token"] {
print("Access Token: \(accessToken)")
}
์ค๋ช
:
- Android์์๋ SharedPreferences ๋ฅผ ์ฌ์ฉํ๋ฉฐ, ์ํธํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก ๋ณด์์ ๊ฐํํ ์ ์์ต๋๋ค.
- iOS์์๋ Keychain ์ ์ฌ์ฉํด ์์ ํ๊ฒ ํ ํฐ์ ์ ์ฅํฉ๋๋ค.
4. SSO(Single Sign-On) ๊ตฌํํ๊ธฐ
SSO๋?
SSO(Single Sign-On) ์ ์ฌ์ฉ์๊ฐ ํ ๋ฒ ๋ก๊ทธ์ธํ๋ฉด ๋ค๋ฅธ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋์ผํ ์ธ์ฆ ์ ๋ณด ๋ก ์ ๊ทผํ ์ ์๋๋ก ํ๋ ๋ฐฉ์์ ๋๋ค. OAuth 2.0๊ณผ ํจ๊ป ์ฌ์ฉํด ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํฉ๋๋ค.
์์: Google SSO ์ฐ๋ ์ฝ๋ (Android)
val googleSignInClient = GoogleSignIn.getClient(this, GoogleSignInOptions.DEFAULT_SIGN_IN)
fun loginWithGoogle() {
val signInIntent = googleSignInClient.signInIntent
startActivityForResult(signInIntent, 100)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 100) {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
if (task.isSuccessful) {
val account = task.result
val idToken = account.idToken
println("Google ID Token: $idToken")
}
}
}
์ค๋ช
:
- Google SSO๋ฅผ ํตํด ํ ๋ฒ ๋ก๊ทธ์ธํ ์ฌ์ฉ์์๊ฒ ๋ค๋ฅธ ์๋น์ค๋ ์๋ ๋ก๊ทธ์ธ ํ ์ ์๋๋ก ํฉ๋๋ค.
5. ๋ชจ๋ฐ์ผ OAuth ๊ตฌํ ์ ๊ณ ๋ คํ ๋ณด์ ์์
- PKCE ์ฌ์ฉ
- ๋ชจ๋ฐ์ผ ์ฑ์์๋ PKCE ๋ฅผ ์ฌ์ฉํด Authorization Code ํ์ทจ๋ฅผ ๋ฐฉ์งํด์ผ ํฉ๋๋ค. - Refresh Token Rotation
- Refresh Token์ด ์ฌ์ฌ์ฉ๋์ง ์๋๋ก ๊ฐ ์์ฒญ๋ง๋ค ์๋ก์ด Refresh Token์ ๋ฐ๊ธํฉ๋๋ค. - HTTPS ์ฌ์ฉ
- ๋ชจ๋ ํต์ ์ HTTPS ๋ฅผ ํตํด ์ํธํํด์ผ ํฉ๋๋ค. - ํ ํฐ ๋ง๋ฃ์ ์๋ ๊ฐฑ์
- Access Token์ด ๋ง๋ฃ๋๋ฉด Refresh Token์ผ๋ก ์๋ ๊ฐฑ์ ํ๋ ๋ก์ง์ ๊ตฌํํฉ๋๋ค.
6. ๋ชจ๋ฐ์ผ OAuth ๊ตฌํ ํ๋ฆ ์ ๋ฆฌ
- ์ฌ์ฉ์๊ฐ ์์ ๋ก๊ทธ์ธ ๋ฒํผ ์ ํด๋ฆญํฉ๋๋ค.
- OAuth ์๋ฒ๋ก๋ถํฐ Authorization Code ๋ฅผ ๋ฐ์ต๋๋ค.
- PKCE ๋ฅผ ์ฌ์ฉํด Authorization Code๋ฅผ ๊ฒ์ฆํฉ๋๋ค.
- Access Token์ ๋ฐ๊ธ๋ฐ์ Secure Storage์ ์ ์ฅ ํฉ๋๋ค.
- ํ์ ์ Refresh Token์ ์ฌ์ฉํด ํ ํฐ์ ๊ฐฑ์ ํฉ๋๋ค.
FAQ
Q1. ๋ชจ๋ฐ์ผ ์ฑ์์ ๋ฐ๋์ PKCE๋ฅผ ์ฌ์ฉํด์ผ ํ๋์?
A1. ๋ค, PKCE๋ ํ์์ ์
๋๋ค. ๋ชจ๋ฐ์ผ ์ฑ์ ๊ณต๊ฐ ํด๋ผ์ด์ธํธ์์ ์ฝ๋ ํ์ทจ๋ฅผ ๋ฐฉ์ง ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
Q2. Access Token๊ณผ Refresh Token์ ์ด๋์ ์ ์ฅํด์ผ ํ๋์?
A2. Android์์๋ KeyStore ๋๋ SharedPreferences , iOS์์๋ Keychain ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
Q3. SSO ๊ตฌํ ์ ์ด๋ค ์ฅ์ ์ด ์๋์?
A3. ์ฌ์ฉ์๊ฐ ํ ๋ฒ ๋ก๊ทธ์ธํ๋ฉด ์ฌ๋ฌ ์ ํ๋ฆฌ์ผ์ด์
์์ ๋์ผํ ์ธ์ฆ ์ ๋ณด ๋ก ์๋ ๋ก๊ทธ์ธํ ์ ์์ต๋๋ค.
Q4. Deep Link ์ค์ ์ ์ฃผ์ํ ์ ์ ๋ฌด์์ธ๊ฐ์?
A4. ๋ฆฌ๋ค์ด๋ ํธ URI๊ฐ ์ ํํ ์ผ์น ํด์ผ ํ๋ฉฐ, ์
์ฑ ๋งํฌ์ ์ฃผ์ ํด์ผ ํฉ๋๋ค.
Q5. ๋ชจ๋ฐ์ผ OAuth์ ๋ณด์์ ๊ฐํํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ๋์?
A5. HTTPS ์ฌ์ฉ, PKCE ์ ์ฉ, Refresh Token Rotation ๋ฑ์ ํตํด ๋ณด์์ ๊ฐํํ ์ ์์ต๋๋ค.
๋๊ธ