98 lines
3.2 KiB
Markdown
98 lines
3.2 KiB
Markdown
flowchart TD
|
|
A[1. backend/main.go 실행] --> B[.env 로드, Logger/DB/IDP 초기화]
|
|
B --> C[API 라우트 등록]
|
|
C --> D[/api/v1/auth/*, /api/v1/user/me 등]
|
|
|
|
E[2. userfront/main.dart 실행] --> F[Flutter 앱 초기화]
|
|
F --> G[GoRouter 생성]
|
|
G --> H[/ko/connect 또는 /ko/signin 진입]
|
|
|
|
H --> I[LoginScreen 생성]
|
|
I --> J[phoneOnly 모드 여부 결정]
|
|
J --> K[사용자 입력]
|
|
K --> L{로그인 타입}
|
|
|
|
L -->|비밀번호| M[_handlePasswordLogin]
|
|
L -->|전화번호 connect| N[_handlePhoneOnlyLogin]
|
|
|
|
M --> O[AuthProxyService.loginWithPassword]
|
|
N --> P[AuthProxyService.loginWithPhoneOnly]
|
|
|
|
O --> Q[POST /api/v1/auth/password/login]
|
|
P --> R[POST /api/v1/auth/phone-login]
|
|
|
|
Q --> S[backend AuthHandler.PasswordLogin]
|
|
R --> T[backend PhoneLogin]
|
|
|
|
S --> U[IDP 인증]
|
|
T --> U
|
|
|
|
U --> V{login_challenge 있음?}
|
|
V -->|예| W[Hydra/OIDC accept 처리]
|
|
V -->|아니오| X[sessionJwt/token 응답]
|
|
|
|
W --> Y[redirectTo + token 응답]
|
|
X --> Z[userfront 성공 처리]
|
|
Y --> Z
|
|
|
|
Z --> AA[_onLoginSuccess]
|
|
AA --> AB[AuthTokenStore.setToken]
|
|
AB --> AC{redirectTo 있음?}
|
|
AC -->|예| AD[webWindow.redirectTo]
|
|
AC -->|아니오| AE[profile load]
|
|
AE --> AF[dashboard 이동]
|
|
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Browser as Browser
|
|
participant App as userfront (Flutter)
|
|
participant Store as AuthTokenStore
|
|
participant Proxy as AuthProxyService
|
|
participant API as backend /api/v1/auth
|
|
participant IDP as IDP/Hydra/Kratos
|
|
|
|
Browser->>App: /ko/connect 또는 /ko/signin 진입
|
|
App->>App: GoRouter가 LoginScreen 생성
|
|
App->>Browser: 로그인 UI 렌더링
|
|
|
|
Browser->>App: 로그인 정보 입력 후 제출
|
|
alt 비밀번호 로그인
|
|
App->>Proxy: loginWithPassword(loginId, password, loginChallenge?)
|
|
Proxy->>API: POST /api/v1/auth/password/login
|
|
API->>IDP: 자격 증명 검증
|
|
IDP-->>API: 세션 토큰/쿠키
|
|
API-->>Proxy: sessionJwt, token, provider, redirectTo?
|
|
else connect 전화번호 로그인
|
|
App->>Proxy: loginWithPhoneOnly(phoneNumber, loginChallenge?)
|
|
Proxy->>API: POST /api/v1/auth/phone-login
|
|
API->>IDP: 전화번호 기반 인증
|
|
IDP-->>API: 세션 토큰/쿠키
|
|
API-->>Proxy: sessionJwt, token, provider, redirectTo?
|
|
end
|
|
|
|
Proxy-->>App: JSON 응답
|
|
App->>App: _onLoginSuccess(token, provider, redirectTo)
|
|
App->>Store: setToken(token, provider)
|
|
alt redirectTo 있음
|
|
App->>Browser: redirectTo로 이동
|
|
else OIDC challenge 있음
|
|
App->>Proxy: acceptOidcLogin(login_challenge, token)
|
|
Proxy->>API: POST /api/v1/auth/oidc/login/accept
|
|
API->>IDP: login accept 처리
|
|
IDP-->>API: OIDC redirect URL
|
|
API-->>App: redirectTo + token
|
|
App->>Store: setToken(...)
|
|
App->>Browser: OIDC redirect
|
|
else 일반 로그인
|
|
App->>App: profile load
|
|
App->>Browser: /{locale}/dashboard 이동
|
|
end
|
|
```
|
|
|
|
핵심만 한 줄로 요약하면:
|
|
backend/main.go가 API를 열고
|
|
userfront/main.dart가 /ko/connect를 LoginScreen(phoneOnly: true)로 연결하고
|
|
login_screen.dart가 AuthProxyService를 통해 /api/v1/auth/password/login 또는 /api/v1/auth/phone-login을 호출한 뒤
|
|
백엔드가 토큰을 주면 AuthTokenStore에 저장하고
|
|
redirectTo가 있으면 그쪽으로, 없으면 dashboard로 갑니다. |