순서도수정
This commit is contained in:
+50
-92
@@ -1,100 +1,58 @@
|
|||||||
|
# baron-sso 로그인 흐름
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
A[1. backend/main.go 실행] --> B[.env 로드, Logger/DB/IDP 초기화]
|
subgraph Backend[backend]
|
||||||
B --> C[API 라우트 등록]
|
B1[main.go 실행]
|
||||||
C --> D[/api/v1/auth/*, /api/v1/user/me 등]
|
B2[.env 로드]
|
||||||
|
B3[Logger / DB / IDP 초기화]
|
||||||
E[2. userfront/main.dart 실행] --> F[Flutter 앱 초기화]
|
B4[/api/v1/auth 라우트 등록]
|
||||||
F --> G[GoRouter 생성]
|
B5[AuthHandler.PasswordLogin]
|
||||||
G --> H[/ko/connect 또는 /ko/signin 진입]
|
B6[AuthHandler.PhoneLogin]
|
||||||
|
B7[토큰 및 redirectTo 응답]
|
||||||
H --> I[LoginScreen 생성]
|
B8[/api/v1/user/me]
|
||||||
I --> J[phoneOnly 모드 여부 결정]
|
B1 --> B2 --> B3 --> B4
|
||||||
J --> K[사용자 입력]
|
B5 --> B7
|
||||||
K --> L{로그인 타입}
|
B6 --> B7
|
||||||
|
|
||||||
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
|
end
|
||||||
|
|
||||||
Proxy-->>App: JSON 응답
|
subgraph Userfront[userfront]
|
||||||
App->>App: _onLoginSuccess(token, provider, redirectTo)
|
U1[main.dart 실행]
|
||||||
App->>Store: setToken(token, provider)
|
U2[GoRouter 설정]
|
||||||
alt redirectTo 있음
|
U3[/ko/signin 또는 /ko/connect]
|
||||||
App->>Browser: redirectTo로 이동
|
U4[LoginScreen 표시]
|
||||||
else OIDC challenge 있음
|
U5[_handlePasswordLogin]
|
||||||
App->>Proxy: acceptOidcLogin(login_challenge, token)
|
U6[_handlePhoneOnlyLogin]
|
||||||
Proxy->>API: POST /api/v1/auth/oidc/login/accept
|
U7[AuthProxyService 호출]
|
||||||
API->>IDP: login accept 처리
|
U8[_onLoginSuccess]
|
||||||
IDP-->>API: OIDC redirect URL
|
U9[AuthTokenStore.setToken]
|
||||||
API-->>App: redirectTo + token
|
U10[redirectTo 이동 또는 dashboard 이동]
|
||||||
App->>Store: setToken(...)
|
U1 --> U2 --> U3 --> U4
|
||||||
App->>Browser: OIDC redirect
|
U5 --> U7 --> U8 --> U9 --> U10
|
||||||
else 일반 로그인
|
U6 --> U7
|
||||||
App->>App: profile load
|
|
||||||
App->>Browser: /{locale}/dashboard 이동
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
U4 --> U5
|
||||||
|
U4 --> U6
|
||||||
|
U7 --> B5
|
||||||
|
U7 --> B6
|
||||||
|
B7 --> U8
|
||||||
|
U10 --> B8
|
||||||
```
|
```
|
||||||
|
|
||||||
핵심 요약:
|
## 흐름 요약
|
||||||
|
|
||||||
* `backend/main.go`가 API를 열고
|
1. `backend/cmd/server/main.go`가 먼저 실행되어 라우트를 엽니다.
|
||||||
* `userfront/main.dart`가 `/ko/connect`를 `LoginScreen(phoneOnly: true)`로 연결하고
|
2. `userfront/lib/main.dart`가 실행되어 `/ko/signin`, `/ko/connect`를 `LoginScreen`으로 연결합니다.
|
||||||
* `login_screen.dart`가 `AuthProxyService`를 통해 `/api/v1/auth/password/login` 또는 `/api/v1/auth/phone-login`을 호출한 뒤
|
3. 사용자가 로그인하면 `login_screen.dart`의 `_handlePasswordLogin()` 또는 `_handlePhoneOnlyLogin()`이 실행됩니다.
|
||||||
* 백엔드가 토큰을 주면 `AuthTokenStore`에 저장하고
|
4. `AuthProxyService`가 백엔드 인증 API를 호출합니다.
|
||||||
* `redirectTo`가 있으면 그쪽으로, 없으면 `dashboard`로 이동합니다.
|
5. 백엔드가 성공 응답을 주면 `AuthTokenStore`에 토큰을 저장합니다.
|
||||||
|
6. `redirectTo`가 있으면 그쪽으로 이동하고, 없으면 `dashboard`로 이동합니다.
|
||||||
|
|
||||||
|
## 참고 파일
|
||||||
|
|
||||||
|
* [backend/cmd/server/main.go](/home/ryu/baron-sso/backend/cmd/server/main.go)
|
||||||
|
* [userfront/lib/main.dart](/home/ryu/baron-sso/userfront/lib/main.dart)
|
||||||
|
* [userfront/lib/features/auth/presentation/login_screen.dart](/home/ryu/baron-sso/userfront/lib/features/auth/presentation/login_screen.dart)
|
||||||
|
* [userfront/lib/core/services/auth_proxy_service.dart](/home/ryu/baron-sso/userfront/lib/core/services/auth_proxy_service.dart)
|
||||||
|
* [backend/internal/handler/auth_handler.go](/home/ryu/baron-sso/backend/internal/handler/auth_handler.go)
|
||||||
|
|||||||
Reference in New Issue
Block a user