ํ ๋ง
๐ฑ ๋ชจ๋ฐ์ผ ์ฑ ํตํฉ ํธ๋ โ
iOS ยท Android ยท Flutter ยท React Native ๋ค์ดํฐ๋ธ ์ฑ์์ logi ๋ฅผ ํตํฉํ๋ ๊ฐ์ฅ ๋น ๋ฅธ ๊ธธ.
์ด ํธ๋์ด ๋ง๋์?
- โ ๋ง์: ์ฌ์ฉ์๊ฐ ์ฑ ์คํ ์ด์์ ๊น์ ์ฐ๋ ๋ค์ดํฐ๋ธ ์ฑ
- โ ์น์ด๋ผ๋ฉด โ ๐ ์น ํตํฉ ํธ๋
- โ ์๋ฒ ๊ฐ ํต์ / CLI ๋ผ๋ฉด โ ๐ง API ยท CLI ํธ๋
ํต์ฌ ์ฝ์ 4์ค โ
- Public client + PKCE ํ์.
client_secret๋ชจ๋ฐ์ผ์ ๋ชป ๋ฐ์ง ๋ง์ธ์. - redirect_uri ๋ custom scheme 1๊ฐ โ ์:
com.example.app://oauth/1pass/callback - app-to-app first, ์ธ์ฑ ๋ธ๋ผ์ฐ์ fallback โ ์ฌ์ฉ์๊ฐ ์นดํก/๋ค์ด๋ฒ ์ธ์ฑ์์ ๋ค์ด์๋ ๋์.
- ์ฑ RP ์ ์น RP ๋ ๋ถ๋ฆฌ โ ๊ฐ์
client_id์ ๋ชจ๋ฐ์ผ+์น redirect ์์ง ๋ง์ธ์. ์์ธํ: ๊ณตํต/Public Clients ยท Surface ๋ณ RP ๋ถ๋ฆฌ
Step 1 ยท ์ฑ ๋ฑ๋ก โ
client_type: public ์ผ๋ก RP ํ ๊ฐ ๋ฑ๋ก. ์ฝ์ ๋๋ API ๋ ๋ค ๊ฐ๋ฅ.
- ์ฑ ๋ฑ๋ก ๊ฐ์ด๋ โ ์ฝ์ UI ์ํฌ์ค๋ฃจ
- Public Clients (PKCE-only) โ API ๋ฑ๋ก + redirect_uri ์ ์ฑ
- Public vs Confidential ๊ฒฐ์ โ ๋ญ ๊ณจ๋ผ์ผ ํ๋
Step 2 ยท ํ๋ซํผ๋ณ Quickstart โ
iOS โ LogiAuth Swift Package (๊ถ์ฅ) โ
iOS ๋ ๊ณต์ Swift SDK LogiAuth 0.1.2 ๊ฐ PKCE ยท ASWebAuthenticationSession ยท ์ธ์ฑ escape ยท keychain ๋ณด๊ด๊น์ง ์ฒ๋ฆฌํฉ๋๋ค. roll-your-own ๋ณด๋ค ๋จผ์ SDK ๋ฅผ ์๋ํ์ธ์.
swift
// Package.swift
.package(url: "https://github.com/1pass-dev/logi.git", exact: "0.1.2"),
// App.swift
import LogiAuth
@main
struct MyApp: App {
init() {
LogiAuth.configure(LogiAuthConfig(
clientId: "logi_xxx",
redirectURI: URL(string: "myapp://oauth/1pass/callback")!
))
}
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL { url in _ = LogiAuth.handle(url) }
}
}
}
// ์ด๋์๋
let result = try await LogiAuth.signIn().onOpenURL { url in _ = LogiAuth.handle(url) } ๋ ์์ง ๋ง์ธ์ โ ๋ก๊ทธ์ธ ์ฝ๋ฐฑ์ SDK ๊ฐ ๋ฐ์ ํ ํฐ ๊ตํ์ ๋ง๋ฌด๋ฆฌํฉ๋๋ค.
์์ธํ ํตํฉ + ์๋ฌ ๋ถ๋ฅ โ Swift quickstart
๊ทธ ์ธ ํ๋ซํผ โ
๋ณธ์ธ ์คํ์ ํ์ด์ง ํ ๊ฐ๋ง ๋ฐ๋ผ๊ฐ์ธ์. ๋๋จธ์ง๋ ๊ฐ์ ํจํด์ ๋ฏธ๋ฌ์ ๋๋ค.
| ์คํ | ๊ฐ์ด๋ | SDK / ๋ผ์ด๋ธ๋ฌ๋ฆฌ |
|---|---|---|
| iOS (Swift) | integrations/swift | LogiAuth 0.1.2 (๊ถ์ฅ) ยท ๋๋ roll-your-own ASWebAuthenticationSession + CryptoKit |
| Android (Kotlin) | integrations/android | LogiAuth Kotlin SDK (๊ถ์ฅ) ยท ๋๋ hand-rolled Custom Tabs + DataStore + Keystore |
| Flutter | integrations/flutter | flutter_web_auth_2 + flutter_secure_storage |
| React Native | integrations/react-native | react-native-app-auth + react-native-keychain |
Android ์๊ฒฉ์ฆ๋ช ๋ถ๋ฆฌ ๋ณด๊ด
Android (Kotlin) โ Canonical/Merge ํ์ด์ง๋ canonical_sub / linked_subs ์ฒ๋ฆฌ + ์๊ฒฉ์ฆ๋ช
๋ถ๋ฆฌ ๋ณด๊ด ํจํด์ ๋ฐ๋ก ๋ค๋ฃน๋๋ค. ์ ๊ท ํตํฉ์ด๋ฉด Step 2 ๊ฐ์ด๋ ๋๋ธ ๋ค ์ฝ์ผ์ธ์.
Step 3 ยท ๋ชจ๋ฐ์ผ ํนํ ํจ์ ํผํ๊ธฐ โ
- Universal Links ํตํฉ ๊ฐ์ด๋ โ iOS Universal Link / Android App Link ๋ฑ๋ก
- ์ธ์ฑ ๋ธ๋ผ์ฐ์ escape โ ์นดํก/๋ค์ด๋ฒ/ํ๋ถ ์ธ์ฑ์์ OAuth ๊ฐ ๋งํ ๋
- Refresh Token ํ์ ์ ์ฑ โ Apple Sign In / Google ํ์ ์ฃผ๊ธฐ ์ฐจ์ด
- ์ฒซ ๋ก๊ทธ์ธ ์๋ฃ ํผ โ RP ์์ฒด ์ถ๊ฐ ์ ๋ณด(์ญํ /์กฐ์ง) 1ํ ์์ง ํจํด
Step 4 ยท ๋น๋ ์ ์ฒดํฌ โ
- RP ํตํฉ ํ ์คํธ โ ์๋ฎฌ๋ ์ดํฐ + ์ค๊ธฐ๊ธฐ ์์ชฝ ๊ฒ์ฆ ์ ์ฐจ
- Demo ํ์ด์ง ๋๋ฌ๋ณด๊ธฐ โ Reference ๊ตฌํ ์ฝ๋ ๋น๊ต
demo.1pass.dev/oauthโ ๋ชจ๋ฐ์ผ PKCE end-to-end walking sample (์๋๋ฆฌ์ค deep-link)demo.1pass.dev/iosโ iOS ๋ค์ดํฐ๋ธ (์ฑ ์ค์น ํ) โ Universal Link first-try + Swift SDKdemo.1pass.dev/app-clipโ iOS App Clip (์ฑ ์ค์น ์ ) โ QR ์ค์บ์ผ๋ก ์นด๋ ๋ก๊ทธ์ธdemo.1pass.dev/androidโ Android ๋ค์ดํฐ๋ธ โ Intent setPackage first-try + Custom Tabs fallback- ์
ํ ์ง๋จ โ
/diagnoseโ ๋ฑ๋กยทredirect_uriยท์ค์ฝํ ์ ๊ฒ
๊ณตํต ๋ ํผ๋ฐ์ค (ํธ๋ ๋ฌด๊ด) โ
- Authorization Code Flow ยท PKCE ยท Scope ๋ ํผ๋ฐ์ค
- ์ค๋ฅ ์ฝ๋ ยท ์๋ต ํค๋
- ๋ณด์ Best Practices (RP ์ธก)
- ๋ก๊ทธ์ธ ๋ฒํผ ์ปดํฌ๋ํธ
AI ์๊ฒ ํต์งธ๋ก ๋์ง๊ธฐ โ
@/llms-full.txt ๋ฅผ Claude Code ยท Cursor ยท Codex ์ ๋ถ์ด๊ณ ๋ค์ ํ ์ค:
"logi 1pass ๋ฅผ [iOS Swift / Flutter / Android Kotlin / RN] ์ฑ์ RP ๋ก ํตํฉํด์ค. public client + PKCE ๊ธฐ์ค."
โ Quickstart, env, redirect_uri ๋ฑ๋ก, ์ฝ๋ฐฑ ํธ๋ค๋ฌ๊น์ง ์๋ ์์ฑ๋ฉ๋๋ค.