# 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 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 ``` ## 흐름 요약 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)