Rails + Inertia.js + Svelte
Source:
integrations/inertia-svelte.md· Live: https://docs.1pass.dev/integrations/inertia-svelte LLM-sanitized: internal links absolutized, VitePress containers → admonitions, line numbers in the Jump-to Index reference this rendered file (1-indexed).
📍 Jump-to Index
- L34-L51: ## ① 로그인 시작 — 클라이언트 라우터를 우회하라 (가장 중요)
- L52-L84: ## ② 로그인 상태 —
inertia_share로 current_user 전달 - L85-L106: ## ③ Svelte 측 —
page는 store 가 아니라 rune (page.props) - L107-L113: ## 체크리스트
- L114-L119: ## 더 보기
Rails + Inertia.js + Svelte
ℹ️ Note: 먼저 읽어주세요 이 페이지는 Rails 8 가이드의 보완편입니다. 컨트롤러 · PKCE · 토큰 교환 · JWT 검증 등 서버 측 로직은 모두 Rails 가이드와 동일합니다. 여기서는 Inertia.js + Svelte 프론트엔드에서만 달라지는 3가지만 다룹니다.
⚠️ Warning: 📋 Confidential client 등록이 필요합니다 서버(Rails)에서
client_secret을/oauth/token에 전달하므로 RP 등록 시 Client type: Confidential 을 선택하세요. 프론트엔드(Svelte)에는 secret 을 절대 노출하지 않습니다.
Inertia 앱은 페이지 전환을 클라이언트 라우터(@inertiajs/svelte 의 router, use:inertia, <Link>)가 가로채는 SPA 입니다. 1pass 로그인은 cross-origin 302 리다이렉트로 시작하는데, 클라이언트 라우터는 이 302 를 XHR 로 따라가려다 조용히 실패합니다 (Turbo Drive 와 동일한 함정). 그래서 세 군데에서 처리가 달라집니다.
① 로그인 시작 — 클라이언트 라우터를 우회하라 (가장 중요)
"1pass 로 로그인" 버튼은 반드시 전체 페이지 네비게이션이어야 합니다. use:inertia / <Link> / router.visit 를 쓰면 안 됩니다.
<a href="/auth/logi/start" data-no-inertia>1pass 로 로그인</a>/auth/logi/start 라우트는 RP 가 자체 결정합니다 (로그인 버튼 참고). 서버 컨트롤러의 redirect_to(..., allow_other_host: true) 는 Rails 가이드와 동일합니다.
💡 Tip: 콜백은 신경 쓸 게 없습니다
/auth/logi/callback은 서버 컨트롤러가 받아redirect_to root_path로 끝내므로 Inertia 가 자연스럽게 다음 페이지를 렌더합니다. 시작(②아님 ①)만 우회하면 됩니다.
② 로그인 상태 — inertia_share 로 current_user 전달
별도 API 왕복 없이 모든 Inertia 페이지에 로그인 사용자를 내려주려면 ApplicationController#inertia_share 를 씁니다.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
inertia_share do
{
auth: {
user: current_user && {
id: current_user.id,
email: current_user.email,
displayName: current_user.display_name
}
},
flash: { notice: flash[:notice], alert: flash[:alert] }
}
end
private
def current_user
@current_user ||= User.find_by(id: session[:user_id]) if session[:user_id]
end
end⚠️ Warning: front-channel 데이터로 User 를 만들지 마세요
current_user는 서버 세션(session[:user_id])에서만 옵니다. 사용자 생성은 서버 측userinfo호출 결과로만 하세요 — Rails 가이드: 첫 로그인.
③ Svelte 측 — page 는 store 가 아니라 rune (page.props)
🚨 Danger: @inertiajs/svelte v3 함정 v2 의
$pagestore 패턴은 v3 에서 깨집니다. v3 의page는$staterune 객체라서$page로 구독하면store_invalid_shape로 hydration 이 실패합니다.page.props를 직접 읽으세요.
<header>
{#if user}
<span title={user.email}>👤 {user.displayName}</span>
<button type="button" onclick={logout}>로그아웃</button>
{:else}
<a href="/auth/logi/start" data-no-inertia>1pass 로 로그인</a>
{/if}
</header>로그아웃은 router.delete 로 안전합니다 (same-origin DELETE — cross-origin 302 가 아니므로 클라이언트 라우터로 처리해도 됨).
체크리스트
- [ ] 로그인 시작 버튼이 plain
<a href>(use:inertia/<Link>아님) - [ ]
inertia_share로auth.user내려줌,current_user는 세션 기반 - [ ] Svelte 에서
$page가 아니라page.props직접 접근 - [ ] RP 등록 = Confidential, secret 은 서버 env 에만
더 보기
- Rails 8 — 컨트롤러 · PKCE · 토큰 교환 · JWT 검증 (서버 측 전부)
- SPA + 서버리스 — 백엔드 없는 순수 SPA (Public client)
- 로그인 버튼 — 버튼 디자인 · 시작 라우트 컨벤션