@authon/react 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +44 -177
- package/README.md +141 -710
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.ko.md
CHANGED
|
@@ -2,226 +2,93 @@
|
|
|
2
2
|
|
|
3
3
|
# @authon/react
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> React 인증 훅 및 컴포넌트 -- 셀프 호스팅 Clerk 대안, Auth0 대안
|
|
6
6
|
|
|
7
7
|
## 설치
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npm install @authon/react
|
|
11
|
-
# 또는
|
|
12
|
-
pnpm add @authon/react
|
|
13
11
|
```
|
|
14
12
|
|
|
15
|
-
`react >= 18.0.0`이 필요합니다.
|
|
16
|
-
|
|
17
13
|
## 빠른 시작
|
|
18
14
|
|
|
19
15
|
```tsx
|
|
20
|
-
import
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
SignedOut,
|
|
24
|
-
UserButton,
|
|
25
|
-
useUser,
|
|
26
|
-
useAuthon,
|
|
27
|
-
} from '@authon/react';
|
|
16
|
+
import React from 'react';
|
|
17
|
+
import ReactDOM from 'react-dom/client';
|
|
18
|
+
import { AuthonProvider, useAuthon, useUser, SignedIn, SignedOut, UserButton } from '@authon/react';
|
|
28
19
|
|
|
29
20
|
function App() {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<Header />
|
|
33
|
-
<Main />
|
|
34
|
-
</AuthonProvider>
|
|
35
|
-
);
|
|
36
|
-
}
|
|
21
|
+
const { openSignIn, signOut } = useAuthon();
|
|
22
|
+
const { user } = useUser();
|
|
37
23
|
|
|
38
|
-
function Header() {
|
|
39
24
|
return (
|
|
40
|
-
<
|
|
25
|
+
<div>
|
|
26
|
+
<SignedOut>
|
|
27
|
+
<button onClick={() => openSignIn()}>로그인</button>
|
|
28
|
+
</SignedOut>
|
|
41
29
|
<SignedIn>
|
|
30
|
+
<p>환영합니다, {user?.email}</p>
|
|
42
31
|
<UserButton />
|
|
43
32
|
</SignedIn>
|
|
44
|
-
|
|
45
|
-
<SignInButton />
|
|
46
|
-
</SignedOut>
|
|
47
|
-
</nav>
|
|
33
|
+
</div>
|
|
48
34
|
);
|
|
49
35
|
}
|
|
50
36
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
function Main() {
|
|
57
|
-
const { user, isLoading } = useUser();
|
|
58
|
-
if (isLoading) return <p>Loading...</p>;
|
|
59
|
-
if (!user) return <p>Please sign in.</p>;
|
|
60
|
-
return <h1>Welcome, {user.displayName}</h1>;
|
|
61
|
-
}
|
|
37
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
38
|
+
<AuthonProvider publishableKey="pk_live_...">
|
|
39
|
+
<App />
|
|
40
|
+
</AuthonProvider>
|
|
41
|
+
);
|
|
62
42
|
```
|
|
63
43
|
|
|
64
|
-
##
|
|
44
|
+
## 주요 작업
|
|
65
45
|
|
|
66
|
-
###
|
|
67
|
-
|
|
68
|
-
앱을 감싸며 인증 컨텍스트를 제공합니다.
|
|
46
|
+
### Google OAuth 로그인
|
|
69
47
|
|
|
70
48
|
```tsx
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
config={{
|
|
74
|
-
apiUrl: 'https://api.authon.dev',
|
|
75
|
-
theme: 'auto',
|
|
76
|
-
locale: 'en',
|
|
77
|
-
appearance: { primaryColorStart: '#7c3aed' },
|
|
78
|
-
}}
|
|
79
|
-
>
|
|
80
|
-
{children}
|
|
81
|
-
</AuthonProvider>
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### 훅
|
|
85
|
-
|
|
86
|
-
#### `useAuthon()`
|
|
87
|
-
|
|
88
|
-
전체 인증 컨텍스트를 반환합니다.
|
|
89
|
-
|
|
90
|
-
```ts
|
|
91
|
-
const {
|
|
92
|
-
isSignedIn, // boolean
|
|
93
|
-
isLoading, // boolean
|
|
94
|
-
user, // AuthonUser | null
|
|
95
|
-
signOut, // () => Promise<void>
|
|
96
|
-
openSignIn, // () => Promise<void>
|
|
97
|
-
openSignUp, // () => Promise<void>
|
|
98
|
-
getToken, // () => string | null
|
|
99
|
-
client, // Authon instance
|
|
100
|
-
} = useAuthon();
|
|
49
|
+
const { client } = useAuthon();
|
|
50
|
+
<button onClick={() => client?.signInWithOAuth('google')}>Google로 로그인</button>
|
|
101
51
|
```
|
|
102
52
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
사용자 데이터 간단 접근용 훅입니다.
|
|
106
|
-
|
|
107
|
-
```ts
|
|
108
|
-
const { user, isLoading } = useUser();
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### 컴포넌트
|
|
112
|
-
|
|
113
|
-
| 컴포넌트 | Props | 설명 |
|
|
114
|
-
|---------|-------|------|
|
|
115
|
-
| `<SignedIn>` | `children` | 로그인 상태일 때만 자식 컴포넌트를 렌더링합니다 |
|
|
116
|
-
| `<SignedOut>` | `children` | 로그아웃 상태일 때만 자식 컴포넌트를 렌더링합니다 |
|
|
117
|
-
| `<UserButton>` | 없음 | 로그아웃 액션이 포함된 아바타 드롭다운입니다 |
|
|
118
|
-
| `<SignIn>` | `mode?` | 로그인 모달을 열거나 인라인 폼을 렌더링합니다 |
|
|
119
|
-
| `<SignUp>` | `mode?` | 회원가입 모달을 열거나 인라인 폼을 렌더링합니다 |
|
|
120
|
-
| `<Protect>` | `fallback?`, `condition?` | 콘텐츠를 보호하며, 선택적으로 커스텀 조건을 지정할 수 있습니다 |
|
|
121
|
-
|
|
122
|
-
### `<Protect>` 사용 예시
|
|
53
|
+
### 라우트 보호
|
|
123
54
|
|
|
124
55
|
```tsx
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
<AdminPanel />
|
|
56
|
+
import { Protect } from '@authon/react';
|
|
57
|
+
|
|
58
|
+
<Protect fallback={<p>로그인이 필요합니다.</p>}>
|
|
59
|
+
<Dashboard />
|
|
130
60
|
</Protect>
|
|
131
61
|
```
|
|
132
62
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
`useAuthonMfa` 훅을 사용하여 TOTP 기반 MFA(Google Authenticator, Authy 등)를 관리합니다.
|
|
136
|
-
|
|
137
|
-
### MFA 설정
|
|
63
|
+
### 현재 사용자
|
|
138
64
|
|
|
139
65
|
```tsx
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
function MfaSetup() {
|
|
143
|
-
const { setupMfa, verifyMfaSetup, isLoading, error } = useAuthonMfa();
|
|
144
|
-
const [qrSvg, setQrSvg] = useState('');
|
|
145
|
-
const [backupCodes, setBackupCodes] = useState<string[]>([]);
|
|
146
|
-
const [code, setCode] = useState('');
|
|
147
|
-
|
|
148
|
-
const handleSetup = async () => {
|
|
149
|
-
const result = await setupMfa();
|
|
150
|
-
if (result) {
|
|
151
|
-
setQrSvg(result.qrCodeSvg);
|
|
152
|
-
setBackupCodes(result.backupCodes);
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
const handleVerify = async () => {
|
|
157
|
-
const success = await verifyMfaSetup(code);
|
|
158
|
-
if (success) alert('MFA enabled!');
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
return (
|
|
162
|
-
<div>
|
|
163
|
-
<button onClick={handleSetup} disabled={isLoading}>Enable MFA</button>
|
|
164
|
-
{qrSvg && (
|
|
165
|
-
<>
|
|
166
|
-
<div dangerouslySetInnerHTML={{ __html: qrSvg }} />
|
|
167
|
-
<p>Scan this QR code with your authenticator app</p>
|
|
168
|
-
<input value={code} onChange={(e) => setCode(e.target.value)} placeholder="6-digit code" />
|
|
169
|
-
<button onClick={handleVerify}>Verify</button>
|
|
170
|
-
</>
|
|
171
|
-
)}
|
|
172
|
-
{error && <p style={{ color: 'red' }}>{error.message}</p>}
|
|
173
|
-
</div>
|
|
174
|
-
);
|
|
175
|
-
}
|
|
66
|
+
const { user, isLoading } = useUser();
|
|
176
67
|
```
|
|
177
68
|
|
|
178
|
-
###
|
|
69
|
+
### 로그아웃
|
|
179
70
|
|
|
180
71
|
```tsx
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
import { AuthonMfaRequiredError } from '@authon/js';
|
|
184
|
-
|
|
185
|
-
function SignIn() {
|
|
186
|
-
const { client } = useAuthon();
|
|
187
|
-
const { verifyMfa } = useAuthonMfa();
|
|
188
|
-
const [mfaToken, setMfaToken] = useState('');
|
|
189
|
-
|
|
190
|
-
const handleSignIn = async (email: string, password: string) => {
|
|
191
|
-
try {
|
|
192
|
-
await client!.signInWithEmail(email, password);
|
|
193
|
-
} catch (err) {
|
|
194
|
-
if (err instanceof AuthonMfaRequiredError) {
|
|
195
|
-
setMfaToken(err.mfaToken); // Show MFA input
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
const handleMfaVerify = async (code: string) => {
|
|
201
|
-
await verifyMfa(mfaToken, code);
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
// ...
|
|
205
|
-
}
|
|
72
|
+
const { signOut } = useAuthon();
|
|
73
|
+
<button onClick={() => signOut()}>로그아웃</button>
|
|
206
74
|
```
|
|
207
75
|
|
|
208
|
-
|
|
76
|
+
## 환경 변수
|
|
209
77
|
|
|
210
|
-
|
|
|
211
|
-
|
|
212
|
-
| `
|
|
213
|
-
| `verifyMfaSetup(code)` | `Promise<boolean>` | TOTP 코드를 검증하여 설정을 완료합니다 |
|
|
214
|
-
| `verifyMfa(mfaToken, code)` | `Promise<boolean>` | 로그인 시 TOTP 코드를 검증합니다 |
|
|
215
|
-
| `disableMfa(code)` | `Promise<boolean>` | MFA를 비활성화합니다 |
|
|
216
|
-
| `getMfaStatus()` | `Promise<MfaStatus \| null>` | MFA 상태를 조회합니다 |
|
|
217
|
-
| `regenerateBackupCodes(code)` | `Promise<string[] \| null>` | 백업 코드를 재생성합니다 |
|
|
218
|
-
| `isLoading` | `boolean` | 로딩 상태입니다 |
|
|
219
|
-
| `error` | `Error \| null` | 마지막으로 발생한 오류입니다 |
|
|
78
|
+
| 변수 | 필수 | 설명 |
|
|
79
|
+
|------|------|------|
|
|
80
|
+
| `AUTHON_PUBLISHABLE_KEY` | Yes | 프로젝트 퍼블리셔블 키 |
|
|
220
81
|
|
|
221
|
-
##
|
|
82
|
+
## 비교
|
|
222
83
|
|
|
223
|
-
|
|
84
|
+
| 기능 | Authon | Clerk | Auth.js |
|
|
85
|
+
|------|--------|-------|---------|
|
|
86
|
+
| 셀프 호스팅 | Yes | No | 부분적 |
|
|
87
|
+
| 가격 | 무료 | $25/월+ | 무료 |
|
|
88
|
+
| ShadowDOM 모달 | Yes | No | No |
|
|
89
|
+
| MFA/패스키 | Yes | Yes | 플러그인 |
|
|
90
|
+
| Web3 인증 | Yes | No | No |
|
|
224
91
|
|
|
225
92
|
## 라이선스
|
|
226
93
|
|
|
227
|
-
|
|
94
|
+
MIT
|