프로젝트

일반

사용자정보

Actions

이슈 #439

진행중
JL HP

[Go backport] Mobile SDK GoTrue 인증 전환 — Phase 6

이슈 #439: [Go backport] Mobile SDK GoTrue 인증 전환 — Phase 6

James Lee이(가) 약 5시간 전에 추가함.

상태:
해결
우선순위:
높음
담당자:
목표버전:
시작일:
2026/05/18
완료일:
2026/05/18 (약 6달 지연)
진척도:

0%

추정시간:

설명

배경

서버 측 Phase 1–5 를 통해 GoTrue 기반 user_id 인증 과 AGX 회계가 완료되었으나, 모바일 SDK (alphea-rpc/sdk/, alphea-rpc/sdk/mobile/) 는 여전히 제거된 wallet challenge/Verify 흐름을 호출하고 있으며 현재 서버와 호환되지 않는다:

  • sdk.Authenticate(...) 는 AuthService.Challenge / Verify 를 호출 (Phase 1에서 서버에서 제거됨)
  • sdk.AuthenticateWithWallet(...) 동일
  • tokenManager.refreshToken 은 RegisterNode 을 ownerWalletAddress 필드 + Authorization 헤더 없이 호출 (Phase 1 이후 user JWT 필수)
  • sdk/mobile/mobile.go Authenticate 계열 함수들 동일

작업 범위

제거

  • sdk.Authenticate(ctx, AuthConfig) 제거
  • sdk.AuthenticateWithWallet(ctx, WalletAuthConfig, Signer) 제거
  • sdk.AuthConfig, sdk.WalletAuthConfig, sdk.Signer 제거
  • sdk/mobile/mobile.go::Authenticate*, AuthenticateWithWallet 제거

신규

  • sdk.AuthenticateWithGoTrueToken(ctx, GoTrueAuthConfig) -> (*AuthResult, error)
    • GoTrue user JWT + node 서명 keypair + device meta 을 받아 NodeService.NodeChallenge + RegisterNode 로 노드 토큰 획득
    • GoTrue 토큰은 모바일 앱이 supabase-flutter/swift/js 등 공식 클라이언트로 미리 획득
  • sdk.GoTrueAuthConfig { ServerAddr, GoTrueToken, PrivateKey, DeviceID, Platform, Timezone }
  • sdk.AuthResult 안의 WalletAddress 는 node 서명 keypair address (소유자 wallet 아님)
  • sdk/mobile/mobile.go::AuthenticateWithGoTrueToken(serverAddr, gotrueToken, privateKey, deviceID, platform, timezone) -> string (AuthResult JSON)

Token refresh

  • tokenManager.refreshToken 은 RegisterNode 를 저장된 user JWT 를 Authorization 헤더에 실어 호출
  • ownerWalletAddress 필드 대신 walletAddress (서명 키) 필드 사용
  • NodeAgent.UpdateUserJWT(token) 메소드 추가 — 모바일 앱이 GoTrue 세션 갱신 시 호출

기타

  • NodeConfig 에 UserJWT string 필드 추가. authTransport 에서 node access token 과 구분
  • sdk/api.go 는 Phase 2/4 에서 이미 wallet_address 필드 제거되었음 — 추가 변경 없음
  • sdk/auth_test.go / sdk/call_test.go 관련 테스트 정리

DoD

  • make build, make test 통과
  • sdk.Authenticate / AuthenticateWithWallet 단어 제거
  • sdk.AuthenticateWithGoTrueToken 이 RegisterNode 경로로 노드 토큰 획득
  • tokenManager 가 user JWT 을 포함해 RegisterNode 호출
  • sdk/mobile 가 새 인증 API로 포팅됨 (gomobile 호환)

관련 이슈

  • 이전 phase: #434(Phase 1, 해결), #435(Phase 2, 해결), #436(Phase 3, 해결), #437(Phase 4, 해결), #438(Phase 5, 해결)
  • Mobile app 구현과 별개이며, Mobile 측에서는 supabase-flutter/swift 등 공식 클라이언트로 GoTrue 로그인 수행 후 SDK에 토큰 주입

연결된 일감 1 (한 건 진행 중 — 모두 미완료)

다음 일감을 우선 진행: 이슈 #438: [Go backport] Legacy wallet_address 컬럼 제거 — Phase 5 (final cleanup)해결Henry Park2026/05/152026/05/15

Actions

JL James Lee이(가) 6달 전에 변경 Actions #1

  • 완료일을(를) 2026/05/18(으)로 지정되었습니다.
  • 시작일을(를) 2026/05/11에서 2026/05/18(으)로 변경되었습니다.
  • 다음 일감을 우선 진행:에 이슈 #438: [Go backport] Legacy wallet_address 컬럼 제거 — Phase 5 (final cleanup)이(가) 추가되었습니다.

JL James Lee이(가) 6달 전에 변경 Actions #2

  • 상태을(를) 신규에서 해결(으)로 변경되었습니다.

Phase 6 구현 완료 — SDK GoTrue 인증 전환

commit:server|dceda06

적용된 변경

sdk/auth.go (완전 재작성)

  • 제거: Authenticate(ctx, AuthConfig), AuthenticateWithWallet(ctx, WalletAuthConfig, Signer), AuthConfig, WalletAuthConfig, Signer 인터페이스 (Phase 1에서 서버 측이 제거한 Challenge / Verify RPC 호출하여 이미 broken 상태)
  • 신규: AuthenticateWithGoTrueToken(ctx, GoTrueAuthConfig) -> (*AuthResult, error)
    • 호스트 앱은 supabase-flutter/swift/js 클라이언트로 GoTrue 로그인 수행 후 토큰을 SDK에 주입
    • 내부 동작:
      1. deriveWalletAddress(privateKey) → 노드 서명 주소
      2. NodeService.NodeChallenge(nodeID) — public RPC
      3. signChallenge(privateKey, challenge)
      4. NodeService.RegisterNode(nodeID, challenge, signature, walletAddress, deviceMeta) with Authorization: Bearer <gotrueToken> — 서버가 owner_user_id = JWT.sub 로 기록
    • Result: nodeID + nodeToken + gotrueToken + walletAddress + privateKey echo (호스트 앱이 NodeConfig.UserJWT 으로 이어받으라고)
  • nodeIDForKeypair(walletAddress, deviceID) 헬퍼: rn_<short> / rn_<short>_<device> 패턴 (서버 nodeIDForAccount 과 동일)
  • AuthResult.WalletAddress 의 의미: 노드 서명 keypair address (소유자 wallet 아님). 주석 추가

sdk/call.go

  • rpcCallWithHeaders(httpClient, serverAddr, path, reqJSON, extraHeaders) 공용 헬퍼 추가
  • rpcCallWithAuth(httpClient, serverAddr, path, reqJSON, bearerToken) — NodeAgent 없이 RegisterNode 에 Bearer 주입
  • 기존 rpcCall 은 내부적으로 rpcCallWithHeaders(..., nil) 호출

sdk/node.go

  • NodeConfig.UserJWT string 필드 추가 (GoTrue access token 캠시, 토큰 갱신 경로에 사용)
  • NodeAgent.UpdateUserJWT(token) 퍼블릭 메소드: 호스트 앱이 Supabase 세션 갱신 시 호출. tokenManager 의 내부 캐시도 함께 갱신
  • newTokenManager 시그니쳐에 userJWT 인자 추가

sdk/token.go (완전 재작성)

  • tokenManager 구조체에 userJWT 필드 + updateUserJWT(token) 메소드
  • refreshToken 로직:
    1. 캐시된 userJWT 없으면 즉시 에러 (token refresh requires a GoTrue JWT; call NodeAgent.UpdateUserJWT first)
    2. NodeChallenge (public) → challenge
    3. signChallenge(privateKey, ...)
    4. rpcCallWithAuth(..., RegisterNode, ..., userJWT) — agent transport 의 (만료된) 노드 토큰 대신 저장된 GoTrue JWT 를 최종 주입
    5. 응답 access_token 를 새 노드 토큰으로 반환, attempts reset
  • ownerWalletAddress 제거, walletAddress (서명 키) 필드만 서버에 전송

sdk/mobile/mobile.go

  • 제거: Authenticate, AuthenticateWithTimezone, AuthenticateWithWallet, Signer 인터페이스, signerAdapter, 내부 authenticate(...) 헬퍼
  • 신규: AuthenticateWithGoTrueToken(serverAddr, gotrueToken, privateKey, deviceID, platform, timezone) -> string (gomobile-compatible JSON return)
  • NodeAgent.UpdateUserJWT(token) gomobile 익스포트 추가

뎍번 변경 없는 곳

  • sdk/api.go — Phase 2/4 에서 이미 wallet_address payload 제거 완료
  • WalletService / FriendsService 호출들 — 이미 user JWT 헤더와 호환

검증

  • go build ./... PASS
  • go vet ./... PASS
  • go test ./... PASS (SDK 단위·integration 테스트 전체)

DoD 체크

  • make build, make test 통과
  • sdk.Authenticate / AuthenticateWithWallet 완전 제거
  • sdk.AuthenticateWithGoTrueToken 이 RegisterNode 경로로 노드 토큰 획득
  • tokenManager 가 user JWT 을 RegisterNode Authorization 헤더에 실어 호출
  • sdk/mobile 가 새 인증 API로 포팅됨 (gomobile 호환)

호스트 앱 사용 헤닜온 예시

// Flutter 예시 (supabase-flutter 사용)
final sess = await supabase.auth.signInWithPassword(email: ..., password: ...);
final gotrueToken = sess.session!.accessToken;

final kp = Alphea.generateKeypair(); // SDK provides locally
final authResultJson = await Alphea.authenticateWithGoTrueToken(
  serverAddr: 'https://edge-rpc.alphea.io',
  gotrueToken: gotrueToken,
  privateKey: kp.privateKey,
  deviceID: deviceID,
  platform: 'ios',
  timezone: 'Asia/Seoul',
);
final agent = Alphea.newNodeAgentFromAuth(authResultJson, listener);
agent.start();

// 세션 갱신 시
supabase.auth.onAuthStateChange.listen((event) {
  final freshToken = event.session?.accessToken;
  if (freshToken != null) agent.updateUserJWT(freshToken);
});

Phase 완전 종결

Go 원본 (서버 + SDK) GoTrue 백포트가 6개 phase 로 종결:

  • Phase 1–5: 서버 측
  • Phase 6 (본 이슈): Mobile SDK 측

HP Henry Park이(가) 6달 전에 변경 Actions #3

Reference implementation 도착

commit:server|94d7be4 에서 데스크톱 CLI alphea-rpc/cmd/sdktest 신설:

  • GoTrue REST 직접 호출 (signup / login / refresh)
  • NodeService.NodeChallenge + RegisterNode (user JWT bearer)
  • ConnectNode bidi 스트림 (sdk.NodeAgent)
  • VFS smoke (Phase 1 후 dfs-* 로 교체 예정)

이 이슈의 mobile SDK GoTrue backport 와 새 흐름의 정합성 검증용. State 는 ~/.alphea/sdktest.json. make sdktest ARGS="..." 로 실행.

#441 의 작업.

CP Chris Park이(가) 6달 전에 변경 Actions #4

  • 담당자을(를) James Lee에서 Henry Park(으)로 변경되었습니다.
Actions

내보내기 PDF Atom