diff --git a/2026/07/baron-sso.md b/2026/07/baron-sso.md index 0b75dad..476ecde 100644 --- a/2026/07/baron-sso.md +++ b/2026/07/baron-sso.md @@ -1,100 +1,58 @@ +# baron-sso 로그인 흐름 + ```mermaid 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? + subgraph Backend[backend] + B1[main.go 실행] + B2[.env 로드] + B3[Logger / DB / IDP 초기화] + B4[/api/v1/auth 라우트 등록] + B5[AuthHandler.PasswordLogin] + B6[AuthHandler.PhoneLogin] + B7[토큰 및 redirectTo 응답] + B8[/api/v1/user/me] + B1 --> B2 --> B3 --> B4 + B5 --> B7 + B6 --> B7 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 이동 + subgraph Userfront[userfront] + U1[main.dart 실행] + U2[GoRouter 설정] + U3[/ko/signin 또는 /ko/connect] + U4[LoginScreen 표시] + U5[_handlePasswordLogin] + U6[_handlePhoneOnlyLogin] + U7[AuthProxyService 호출] + U8[_onLoginSuccess] + U9[AuthTokenStore.setToken] + U10[redirectTo 이동 또는 dashboard 이동] + U1 --> U2 --> U3 --> U4 + U5 --> U7 --> U8 --> U9 --> U10 + U6 --> U7 end + + U4 --> U5 + U4 --> U6 + U7 --> B5 + U7 --> B6 + B7 --> U8 + U10 --> B8 ``` -핵심 요약: +## 흐름 요약 -* `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`로 이동합니다. +1. `backend/cmd/server/main.go`가 먼저 실행되어 라우트를 엽니다. +2. `userfront/lib/main.dart`가 실행되어 `/ko/signin`, `/ko/connect`를 `LoginScreen`으로 연결합니다. +3. 사용자가 로그인하면 `login_screen.dart`의 `_handlePasswordLogin()` 또는 `_handlePhoneOnlyLogin()`이 실행됩니다. +4. `AuthProxyService`가 백엔드 인증 API를 호출합니다. +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)