이슈 #424
진행중Dev Console 에 GoTrue Sign Up / Log In 통합 — 테스트 환경 간소화
설명
배경¶
GoTrue 자체 호스팅은 #411 에서 docker-compose 에 추가됐지만 (port 9011), Dev Console 에서 토큰을 얻으려면 외부에서 curl/Postman 으로 /signup / /token?grant_type=password 를 호출 후 access_token 을 복사해 paste 해야 한다. 매번 번거로움.
목표¶
Dev Console Auth 탭에서 직접 Sign Up / Log In 을 호출하고, 성공 시 JWT 가 자동 저장되도록 한다.
설계¶
CORS 회피 + 단일 진입점 위해 admin 서버를 GoTrue proxy 로 둔다.
신규 admin 엔드포인트¶
-
POST /api/auth/gotrue/signup— body{email, password}→ GoTrue/signup으로 forward -
POST /api/auth/gotrue/login— body{email, password}→ GoTrue/token?grant_type=password으로 forward - 응답은 GoTrue 의 JSON 그대로 (성공 시 access_token / 에러 시 GoTrue 의 에러 message)
Config / 인프라¶
-
Config.gotrue_url필드 추가 (envGOTRUE_URL, 기본http://localhost:9011) - Docker 환경:
app.environment.GOTRUE_URL=http://gotrue:9011(in-cluster) - HTTP 클라이언트:
reqwest = "0.12"(rustls-tls, json features) -
AppState.http_client: reqwest::Client— 공유 instance
UI¶
Auth 탭의 기존 "GoTrue Quick Endpoints" info 카드 제거 → 두 카드 신설:
- Sign Up — email / password 입력 + Sign Up 버튼. autoconfirm=true 환경에서는 즉시 세션 반환되므로 access_token 자동 저장.
-
Log In — email / password 입력 + Log In 버튼. 응답의 access_token 을
setJwt()로 자동 저장.
기존 "Paste GoTrue JWT" 카드는 유지 (외부 토큰을 그대로 쓰고 싶을 때).
의존¶
JL James Lee이(가) 6달 전에 변경
- 상태을(를) 신규에서 해결(으)로 변경되었습니다.
구현 완료¶
commit:server|01fe63d
변경 요약¶
Config / 인프라
-
Cargo.toml:reqwest 0.12(rustls-tls, json) — admin 의 outbound HTTP 클라이언트 -
src/config.rs:Config.gotrue_url필드. envGOTRUE_URL, 기본http://localhost:9011 -
src/server/mod.rs,src/main.rs:AppState.http_client: reqwest::Client— 공유 instance -
docker-compose.yml:app.environment.GOTRUE_URL=http://gotrue:9011(in-cluster 서비스 이름). 외부 GoTrue 사용 시${GOTRUE_INTERNAL_URL}로 override 가능
Admin proxy (src/admin/mod.rs)
-
proxy_gotrue()헬퍼 — POST 본문을 GoTrue 로 forward, 응답 JSON / 에러를 그대로 반환 (4xx →BadRequest, 5xx →Internal) -
POST /api/auth/gotrue/signup→ GoTrue/signup -
POST /api/auth/gotrue/login→ GoTrue/token?grant_type=password
UI 변경 (Auth 탭)
기존 "GoTrue Quick Endpoints" 안내 카드를 실제 호출 카드 2개로 교체:
-
Sign Up — email / password 입력 →
gtSignup(). autoconfirm=true 환경(현재 docker-compose 기본)에서는 즉시 세션 반환되어access_token자동 저장. -
Log In — email / password 입력 →
gtLogin(). 응답의access_token자동 저장.
"Paste JWT (manual)" 카드는 외부 토큰용으로 유지.
gtPickToken() — /token 의 top-level access_token 또는 /signup 의 session.access_token 둘 다 처리.
Clippy 정리 (rust 1.88 의 if let chains 안정화로 새로 활성화된 collapsible_if 5건):
src/admin/mod.rs:316src/domain/auth/crypto.rs:132-
src/handler/node.rs:185(2건 → 한 번에 collapse) src/store/redeem.rs:417
검증¶
-
cargo build성공 -
cargo test --lib37 passed -
cargo clippy --all-targetsclean (warnings 0)
사용 흐름¶
- Dev Console → Auth 탭
- Sign Up — 새 이메일/비번 입력 → 클릭 → JWT 자동 저장
- (또는) Log In — 기존 사용자 → 클릭 → JWT 자동 저장
- 다른 탭 (Node, Wallet, Redeem) 의 보호 RPC 가 자동으로 JWT 사용
서버 배포 시 git pull && docker compose build app && docker compose up -d 로 반영.
JL James Lee이(가) 6달 전에 변경
후속 — .env.example 정리¶
commit:server|10e589c
GoTrue 통합 후속으로, docker-compose.yml + src/config.rs 양쪽을 audit 해서 사용되는 환경변수를 모두 .env.example 에 반영.
추가 (GoTrue / 인프라)¶
-
ADMIN_PORT,GOTRUE_PORT,GOTRUE_INTERNAL_URL,GOTRUE_URL,GOTRUE_EXTERNAL_URL,GOTRUE_MAILER_AUTOCONFIRM,SITE_URL - SMTP (
SMTP_HOST/PORT/USER/PASS) — 운영 환경에서autoconfirm=false일 때만 필요. 주석 처리. - 소셜 OAuth (
GOOGLE_*,APPLE_*,KAKAO_*) — 주석 처리.
그룹화 + 주석 보강¶
- App / PostgreSQL / JWT / GoTrue / SMTP / Social 섹션으로 분리
-
GOTRUE_INTERNAL_URL(docker in-cluster) vsGOTRUE_URL(로컬 cargo run) 차이 주석으로 설명 -
JWT_SECRET이 alphea ↔ GoTrue 양쪽에서 동일해야 함 + 운영에서 교체 권고
제거¶
-
AUTH_SALT,PASSWORD_SALT— #411 GoTrue 전환 후 코드에서 미사용 (잔재)
의도적으로 제외¶
-
REDIS_URL— CLAUDE.md 에는 optional 로 언급되지만 실제 코드 통합 없음 (src/handler/system.rs의redis_connected는 하드코드false). 추가하면 오해 유발.
비고¶
docker-compose.yml 의 app.environment.DATABASE_URL 은 하드코드 (postgres://alphea:alphea@postgres:5432/alphea) — 즉 docker 환경에서는 .env 의 DATABASE_URL 이 사용되지 않는다. PostgreSQL 자격증명을 바꾸려면 docker-compose.yml 직접 편집 필요. 추후 ${DATABASE_URL:-...} 로 override 가능하게 정리할지는 별도 판단.
JL James Lee이(가) 6달 전에 변경
후속 — GoTrue DB 부트스트랩 fix¶
commit:server|028596e
문제¶
docker compose up 시 GoTrue v2.158.1 가 깨끗한 Postgres 에서 마이그레이션 / gen_random_uuid() 호출에 실패하고 재시작 루프에 빠짐. 기존 docker-compose 의 ?search_path=auth 는 검색 경로만 설정할 뿐 schema 를 만들지 않으며, postgres:17-alpine 은 pgcrypto extension 을 자동 활성화하지 않음.
Fix¶
-
db/init/01-gotrue-schema.sql신설:CREATE EXTENSION IF NOT EXISTS pgcrypto; CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE SCHEMA IF NOT EXISTS auth; GRANT ALL ON SCHEMA auth TO alphea; -
docker-compose.ymlpostgres.volumes 에./db/init:/docker-entrypoint-initdb.d:ro마운트 추가 - gotrue 서비스의 잘못된 comment ("GoTrue creates its own 'auth' schema") 를 실제 동작에 맞게 정정
적용 시 주의¶
/docker-entrypoint-initdb.d/ 는 postgres entrypoint 가 데이터 디렉토리가 비어 있을 때만 실행한다. 따라서 적용 방법은 환경별로 다름:
A. 새 환경 / dev (데이터 폐기 OK)
docker compose down -v # ⚠️ postgres-data 볼륨 삭제 = 모든 데이터 손실
docker compose up -d
B. 기존 데이터 보존 환경
docker compose exec postgres psql -U alphea -d alphea -c "
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";
CREATE SCHEMA IF NOT EXISTS auth;
GRANT ALL ON SCHEMA auth TO alphea;
"
docker compose restart gotrue
검증¶
docker compose logs gotrue 가 마이그레이션 통과 + listening 메시지로 끝나면 성공. 이후 Dev Console Auth 탭의 Sign Up 으로 동작 확인 가능.
JL James Lee이(가) 6달 전에 변경
후속 — Supabase 표준 role 세트 생성¶
commit:server|392fb8a
문제¶
이전 fix (#424 의 028596e) 로 schema/extension 은 통과했지만 GoTrue 마이그레이션 20240612123726_enable_rls_update_grants.up.sql 가 다음 에러로 실패:
grant select on auth.users to postgres with grant option;
ERROR: role "postgres" does not exist (SQLSTATE 42704)
GoTrue v2.140+ 의 RLS 관련 마이그레이션이 표준 Supabase role 5개 (postgres, anon, authenticated, service_role, supabase_auth_admin) 의 존재를 가정하고 GRANT 를 수행. POSTGRES_USER=alphea 환경에서는 그 role 들이 자동 생성되지 않음.
Fix¶
db/init/01-gotrue-schema.sql 에 추가:
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'postgres') THEN
CREATE ROLE postgres NOLOGIN;
END IF;
-- ... anon, authenticated, service_role, supabase_auth_admin
END $$;
-- PostgreSQL 16+ 의 grantor 멤버십 요구사항
GRANT postgres, anon, authenticated, service_role, supabase_auth_admin TO alphea;
핵심 포인트¶
- 5개 role 모두
NOLOGIN— GRANT 의 대상으로만 필요하고 실제 접속하지 않음. superuser 권한 불필요. -
PostgreSQL 16+ 부터는 grantor (alphea) 가 grantee role 의 member 여야
GRANT ... WITH GRANT OPTION이 가능 → 마지막 줄에서 alphea 에게 멤버십 부여. -
CREATE ROLE은IF NOT EXISTS문법이 없어DOblock 으로 idempotent 처리.
적용 (이전 fix 와 동일 가이드)¶
A. 새 환경:
docker compose down -v && docker compose up -d
B. 기존 데이터 보존:
docker compose exec postgres psql -U alphea -d alphea -c "
DO \$\$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'postgres') THEN CREATE ROLE postgres NOLOGIN; END IF;
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'anon') THEN CREATE ROLE anon NOLOGIN; END IF;
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'authenticated') THEN CREATE ROLE authenticated NOLOGIN; END IF;
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'service_role') THEN CREATE ROLE service_role NOLOGIN; END IF;
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'supabase_auth_admin') THEN CREATE ROLE supabase_auth_admin NOLOGIN; END IF;
END \$\$;
GRANT postgres, anon, authenticated, service_role, supabase_auth_admin TO alphea;
"
docker compose restart gotrue
GoTrue 가 Listening on :9011 로 startup 완료하면 OK.
JL James Lee이(가) 6달 전에 변경
Go 백포트 Phase 1 — 인프라만 먼저 반영¶
commit:server|03c6c64 (이슈 #434)
본 이슈의 Admin Dev Console GoTrue Sign Up / Log In UI / proxy 라우팅 은 Go 측 Phase 3 에서 처리. 이번 커밋에서는 그에 선행하는 인프라 설정만 동반:
-
alphea-rpc/docker-compose.yml에supabase/gotrue:v2.158.1서비스 정의 (:9011,GOTRUE_JWT_SECRET=$JWT_SECRET,MAILER_AUTOCONFIRM=true,service-name으로 서버 컨테이너와 통신) -
alphea-rpc/db/init/01-gotrue-schema.sql가 PG17 첫 기동 시pgcrypto/uuid-ossp/auth스키마 / supabase role 5종 (postgres / anon / authenticated / service_role / supabase_auth_admin) 을 처리. PostgreSQL 16+ 의 grantor 멤버십 요구사항까지 고려해alphea로에 멤버십 부여 -
.env.example에GOTRUE_URL(로컬) /GOTRUE_INTERNAL_URL(in-cluster) /GOTRUE_PORT/GOTRUE_MAILER_AUTOCONFIRM/SITE_URL추가 - 서버 컨테이너는
GOTRUE_URL=$GOTRUE_INTERNAL_URL로 환경변수를 받아 GoTrue 의 REST API 로 프록시 호출할 수 있는 상태이며, Admin 프록시 라우팅과 UI 는 Phase 3 이슈에서 도입
결과¶
GoTrue 서비스가 기동 후 외부에서 POST :9011/signup 및 POST :9011/token?grant_type=password 로 직접 sign-up / login 가능. 발급된 access_token 을 Authorization: Bearer <token> 로 보내면 alphea-rpc 의 AuthInterceptor 가 검증해 AuthContext 에 user_id / email 을 주입한다.
JL James Lee이(가) 6달 전에 변경
Go 백포트 Phase 3 구현 완료¶
후속 이슈 #436 에서 진행. Rust 측 본 이슈의 핵심(GoTrue Sign Up / Log In proxy + Admin UI 카드 + audit 로그 + Cloudflare 우선순위 IP) 을 Go 원본(alphea-rpc-next)으로 백포트.
commit:server|cf27194
Go 측에서의 차이¶
-
경로: Rust
axum라우팅과 달리 Gonet/httpServeMux. 경로는/admin/api/auth/gotrue/{signup,login}으로 가져온 (원본은/api/auth/gotrue/...었고 admin sub-mount 구조에 따라/adminprefix 추가) -
HTTP 클라이언트:
reqwest대신 표준net/http.Client(10s timeout) -
Audit 로그: 원본은 tracing
audit::authtarget 을 사용. Go 측은 기존 admin access_logs 테이블에 기록 (source="admin", path="/admin/api/auth/gotrue/..."). Dev Console Logs 탭에서 검색 가능 - IP 우선순위: 원본과 동일 CF-Connecting-IP > X-Real-IP > X-Forwarded-For > axum ConnectInfo(→ Go는 r.RemoteAddr)
UI 구성¶
Rust 원본과 동일한 구조:
- 상단의 JWT bar(user_id 레이블 + copy/clear 버튼)
- Sign Up 카드(email/password 입력 → autoconfirm=true 일 때 즉시 session)
- Log In 카드(email/password 입력 → access_token 자동 저장)
- Paste JWT (manual) 카드 외부 토큰 수용
gtPickToken 이 session.access_token (signup) 또는 access_token (login) 둘 다 처리하는 패턴 동일.
Phase 3 마무리¶
Go 측 GoTrue 백포트의 제일 조세대 phase 완료. 후속 작업(FriendsService user_id 전환, owner_wallet_address 제거, virtual_node 스키마 재설계)은 별도 phase 이슈로 후속 예정.