From 582db7e688b4458b8b4f71ae4668a80f1505f29e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A5=98=ED=98=B8=EC=84=B1?= Date: Tue, 7 Jul 2026 16:34:47 +0900 Subject: [PATCH] baron-sso --- 2026/07/baron-sso.md | 98 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 2026/07/baron-sso.md diff --git a/2026/07/baron-sso.md b/2026/07/baron-sso.md new file mode 100644 index 0000000..5840f58 --- /dev/null +++ b/2026/07/baron-sso.md @@ -0,0 +1,98 @@ +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로 갑니다. \ No newline at end of file