- OpenID Connect
- OAuth 2.1
- PKCE
- WebAuthn
- JWKS
- DPoP
- TOTP
Lobby
캐묻지 않고 맞이하는 로그인 페이지.
Lobby는 Usher Identity가 앱을 위해 호스팅하는 로그인 페이지입니다. 사용자가 어디로 가는지 항상 알려 주고, 어느 앱에서 왔든 똑같은 모습이라 사람들이 믿고 쓸 수 있습니다.
- 이동할 제품의 이름을 매번 보여 줍니다.
- 패스키, 이메일 코드, 매직 링크를 지원하며, 원할 때만 암호를 사용합니다.
- 라이트든 다크든, 모든 제품에서 똑같이 차분한 페이지.
실제로 작동하는 Lobby 사본입니다. 이 페이지 안에서만 실행되며, 아무것도 전송하지 않고 아무도 로그인시키지 않습니다.
종속이 아닌 표준
지금 쓰는 스택이 이미 아는 프로토콜로 말합니다.
Usher Identity는 무엇보다 OpenID Connect 공급자입니다. 편하다면 Usher Identity SDK를, 아니면 어떤 언어의 어떤 OIDC 라이브러리든 사용하세요. 언젠가 Usher Identity를 떠나더라도 앱의 로그인 방식을 바꿀 필요가 없습니다.
- OIDC Core · Discovery
OpenID Connect
환경마다 디스커버리 문서, ID 토큰, userinfo를 제공합니다. 인증받은 클라이언트 라이브러리라면 무엇이든 작동합니다.
- S256만 지원
PKCE를 적용한 OAuth 2.1
공개 클라이언트든 기밀 클라이언트든 모든 클라이언트에 PKCE를 적용한 인가 코드 방식을 사용합니다. 암시적 흐름도 없고, 토큰 엔드포인트로 암호를 보내는 일도 없습니다.
- RS256 · ES256 · EdDSA
JWKS와 키 교체
각 환경은 자체 키로 서명하고, 그 키를 해당 환경의 jwks_uri에 공개합니다. 로그인한 사용자에게 영향을 주지 않고 키를 교체할 수 있습니다.
- RFC 7662 · RFC 7009
인트로스펙션과 폐기
토큰이 아직 유효한지 확인하거나, 지금 바로 무효화하세요. Usher Identity는 요청마다 자체 세션을 확인하므로, 세션을 끝내면 즉시 반영됩니다.
RP 시작 로그아웃과 백채널 로그아웃
앱에서 로그아웃하거나, 어디서든 세션이 끝나면 Usher Identity가 모든 앱에 알리도록 하세요.
- RFC 9449
DPoP
클라이언트가 가진 키에 토큰을 묶어, 토큰을 탈취당해도 그것만으로는 쓸 수 없게 합니다.
- WebAuthn
패스키
부가 기능이 아닌 기본 기능입니다. 지문, 얼굴 또는 보안 키로 로그인하며, 피싱당할 정보가 아예 없습니다.
- TOTP
인증 앱
모든 인증 앱의 시간 기반 코드를 백업 코드와 함께 지원합니다. 2차 인증을 선택 사항으로 둘지 필수로 할지 정할 수 있습니다.
매직 링크
받은편지함에서 한 번만 탭하면 됩니다. 유효 시간이 짧고, 한 번만 쓸 수 있으며, 링크를 보낸 환경에 묶여 있습니다.
이메일 코드
한 기기에서 로그인하고 다른 기기에서 이메일을 확인하는 사람을 위한 6자리 숫자.
소셜 로그인
Google, GitHub, Microsoft, Apple. 이메일이 확인된 경우에만 계정을 연결합니다.
조직과 팀
앱을 사용하는 기업을 위한 구성원, 역할, 초대.
- 출시 예정
SAML
고객사의 직원용 ID 공급자를 통한 통합 로그인(SSO).
- 출시 예정
SCIM
고객사 디렉터리와 연동한 계정 프로비저닝 및 디프로비저닝.
로그인 과정
다섯 단계, 모두 표준.
OpenID Connect의 PKCE 인가 코드 흐름입니다. 제대로 된 ID 공급자라면 모두 사용하는 바로 그 흐름입니다. 스크롤하며 살펴보세요.
- 01
앱이 사용자를 Lobby로 보냅니다.
누군가 ‘Usher Identity로 계속하기’를 선택하면, 앱은 PKCE 챌린지와 나중에 확인할 state 값을 담아 사용자를 해당 환경의 인가 엔드포인트로 리디렉션합니다.
GET acme.usherid.com/api/auth/oauth2/authorize ?response_type=code &client_id=acme_web &redirect_uri=https://app.acme.example/callback &scope=openid profile email offline_access &state=k3Jx… &code_challenge=E9Mel…cM &code_challenge_method=S256
- 02
원하는 방법으로 로그인합니다.
패스키, 이메일 코드, 매직 링크, 소셜 계정 또는 암호. Lobby는 환경에서 허용한 방법만 제공하며, 사용자가 어느 앱으로 가는지 항상 보여 줍니다.
Usher IdentityUsher IdentityAcme(으)로 이동다시 오신 것을 환영합니다.
패스키 사용이메일로 코드 받기 - 03
정보 공유에 동의합니다.
처음 한 번은 앱이 요청하는 정보(프로필, 이메일, 로그인 상태 유지)를 확인하고 동의합니다.
Acme에서 다음 권한을 요청합니다.
- 이름과 사진 보기
- 이메일 주소 보기
- 로그인 상태 유지
취소허용 - 04
Usher Identity가 코드를 돌려줍니다.
브라우저는 5분 동안 유효한 일회용 코드와 앱이 보냈던 state를 가지고 리디렉션 URI로 돌아오며, 앱은 이 state를 확인합니다.
302 Found Location: https://app.acme.example/callback ?code=SplxlOBeZQQYbYS6WxSbIA &state=k3Jx…
- 05
앱이 코드를 토큰으로 교환합니다.
서버가 코드와 PKCE 검증자(verifier)를 토큰 엔드포인트로 보냅니다. 그러면 사용자가 누구인지 알려 주는 ID 토큰, API용 액세스 토큰, 로그인 상태를 유지하는 리프레시 토큰이 돌아옵니다.
POST acme.usherid.com/api/auth/oauth2/token grant_type=authorization_code&code=Splx… &code_verifier=dBjftJeZ4CVP… { "token_type": "Bearer", "access_token": "eyJhbGciOiJSUzI1NiIs…", "id_token": "eyJhbGciOiJSUzI1NiIs…", "refresh_token": "8xLOxBtZp8…", "expires_in": 600 }
설계부터 격리
모든 환경은 각자 독립된 건물입니다.
프로덕션 환경과 개발 환경, 그리고 다른 모든 고객의 환경은 중요한 것을 하나도 공유하지 않습니다. 한 환경에서 실수가 생겨도 다른 환경을 읽거나, 대신 서명하거나, 다른 환경에 로그인할 수 없습니다.
- 자체 Postgres 스키마
- 공유 테이블의 테넌트 열이 아니라, 그 환경만을 위해 만들고 다른 것은 하나도 담지 않은 스키마입니다.
- 자체 서명 키
- 한 환경의 토큰은 절대 다른 환경의 키로 검증되지 않습니다.
- 자체 봉인 시크릿
- 환경 고유의 데이터 키로 봉인되며, 이 데이터 키는 다시 마스터 키로 래핑됩니다.
- 자체 호스트
- 발급자는 Usher 사이트 및 Console과 다른 도메인에 있으며, 호스트 전용 쿠키를 사용합니다.
usheridentity.com
사이트, Usher Identity Console, Usher Identity 계정
*.usherid.com
환경마다 하나의 발급자, 별도의 도메인에
사용자, 세션, 토큰은 이 환경을 위해 만든 스키마에 저장됩니다. 쿼리는 항상 이 스키마를 대상으로 실행되며, 테넌트 열이 있는 공유 테이블은 절대 사용하지 않습니다.
Acme 프로덕션 환경의 봉인된 Google 클라이언트 시크릿을 Northwind 프로덕션 환경으로 복사해 보세요.
개발자를 위해
첫 로그인을 만드는 세 가지 방법.
SDK가 나오면 바로 넣어 쓰거나, 이미 신뢰하는 OIDC 라이브러리를 사용하거나, 디스커버리 문서부터 읽어 보세요. 바탕은 모두 같은 프로토콜입니다.
// app/layout.tsx
import { UsherProvider } from '@usher/nextjs'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<UsherProvider>{children}</UsherProvider>
</body>
</html>
)
}
// app/page.tsx
import { SignIn, UserButton, currentUser } from '@usher/nextjs'
export default async function Page() {
const user = await currentUser()
return user ? <UserButton /> : <SignIn />
}직접 운영하기
내 서버, 내 키.
Usher Identity를 서비스로 이용하거나, 같은 플랫폼을 자체 서버에서 자체 키와 자체 데이터베이스로 운영하세요.
Docker
Compose 파일 하나에 앱, Postgres, Valkey, Caddy 에지, 이그레스 프록시가 모두 들어 있습니다. 컨테이너는 새 권한을 얻을 수 없고, 불필요한 권한(capabilities)을 제거한 상태로 실행됩니다.
Ubuntu
일반 Ubuntu 서버면 충분합니다. Caddy가 TLS를 종료하며, 시크릿은 이미지에 넣지 않고 언제나 파일로 컨테이너에 전달됩니다.
Postgres
모든 데이터는 Postgres에 환경마다 하나의 스키마로 저장됩니다. Postgres와 Valkey는 인터넷으로 나가는 경로가 없는 네트워크에 있습니다.
# on an Ubuntu server with Docker Engine and the Compose plugin
bash infra/scripts/setup-env.sh --prod \
--domain usher.example --tenant-domain usherid.example
docker compose -f compose.yaml -f compose.prod.yaml \
--profile core --profile apps --profile edge up -d --wait
pnpm db:migrate # applies the database migrations전체 셀프 호스팅 가이드는 준비 중입니다. 위 명령어로 대략적인 모습을 확인할 수 있습니다.
사용자를 안으로 모시세요.
워크스페이스와 프로젝트를 만들면 첫 번째 환경이 자체 발급자, 키, Lobby와 함께 준비됩니다.
한 번 로그인하면 어디서든 환영받습니다.