diff --git a/2026/07/baron-sso.md b/2026/07/baron-sso.md index 476ecde..3d1ce2d 100644 --- a/2026/07/baron-sso.md +++ b/2026/07/baron-sso.md @@ -1,43 +1,98 @@ # baron-sso 로그인 흐름 +## 순서도 + ```mermaid flowchart TD - 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 + 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 - 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 + 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 - - U4 --> U5 - U4 --> U6 - U7 --> B5 - U7 --> B6 - B7 --> U8 - U10 --> B8 ``` ## 흐름 요약