Hugging Face로 로그인하기

Hugging Face로 로그인하기 (Sign in with Hugging Face)

HF OAuth / OpenID Connect 흐름을 쓰면 어떤 웹사이트나 앱에도 "Sign in with HF" 버튼을 쉽게 넣을 수 있어요. 사용자가 자신의 HF 계정으로 로그인하도록 유도하는 가장 표준적인 방법이죠.

출처: 문서

본문

HF OAuth / OpenID Connect 흐름을 사용하면 어떤 웹사이트나 앱에도 "Hugging Face로 로그인" 흐름을 만들 수 있어요. 이렇게 하면 사용자가 HF 계정으로 버튼 하나만 눌러 로그인할 수 있습니다.

Sign in with Hugging Face

버튼을 누르면 사용자에게 앱을 승인할 권한 모달(permissions modal)이 표시됩니다.

OAuth 앱 만들기 (Creating an oauth app)

애플리케이션은 설정에서 만들 수 있어요.

공개 OAuth 앱 (비밀번호 없음, Public OAuth apps)

클라이언트 시크릿 없이도 OAuth 앱을 만들거나 사용할 수 있어요. 네이티브 앱, CLI, 또는 시크릿을 안전하게 보관하기 어려운 환경에 유용합니다.

  • 앱 생성 시: 새 OAuth 앱을 만들 때 시크릿 없이 만들도록 선택할 수 있어요.
  • 생성 후: 기존 앱의 앱 설정에서 클라이언트 시크릿을 삭제하면 공개 앱으로 동작합니다.

공개 앱은 클라이언트 ID만으로 인증합니다(예: device code 흐름이나 PKCE를 쓰는 authorization code 흐름). 시크릿이 있는 앱은 필요할 때 여전히 시크릿을 사용할 수 있어요.

리다이렉트 URI (Redirect URIs)

인증 요청에 보내는 redirect_uri는 앱에 등록된 리다이렉트 URI 중 하나와 정확히 일치해야 합니다.

루프백(loopback) 리다이렉트 URI는 한 가지 예외: 루프백 호스트(localhost, 127.0.0.1, [::1])의 http 스킴을 쓰는 URI는 다른 모든 구성이 등록된 URI와 일치하기만 하면 요청 시점에 어떤 포트든 허용됩니다. 이는 RFC 8252 §7.3 / OAuth 2.1을 따르는 것으로, 네이티브 앱·CLI·MCP 클라이언트가 http://localhost/callback 같은 포트 없는 URI를 등록하고 운영체제가 할당하는 임시 포트(예: http://localhost:49282/callback)에서 대기하도록 해줍니다.

몇 가지 유의할 점:

  • 예외는 http 스킴에만 적용돼요. https와 커스텀 스킴(예: myapp://callback) 리다이렉트 URI는 포트를 포함해 항상 정확히 일치해야 합니다.
  • 루프백 호스트는 개별적으로 매칭됩니다. http://localhost:49282/callback 요청은 등록된 http://127.0.0.1/callback과 매칭되지 않아요. 둘 다 쓸 수 있다면 둘 다 등록하세요.
  • 포트만 달라질 수 있어요. 경로, 쿼리, userinfo는 여전히 정확히 일치해야 합니다.

Spaces에 호스팅하는 경우 (If you are hosting in Spaces)

[!TIP] 앱을 Spaces에 호스팅하면 흐름 구현이 훨씬 쉬워집니다(그리고 Gradio에 바로 내장되어 있어요). Spaces OAuth 가이드를 확인해 보세요.

자동 OAuth 앱 생성 (Automated oauth app creation)

Hugging Face는 CIMD(Client ID Metadata Documents)를 지원해서 웹사이트용 OAuth 앱을 자동으로 만들 수 있어요:

  • 웹사이트에 /.well-known/oauth-cimd 엔드포인트를 추가해 다음 JSON을 반환하게 하세요:
{
  client_id:                  "[your website url]/.well-known/oauth-cimd",
  client_name:                "Your Website",
  redirect_uris:              ["[your website url]/oauth/callback/huggingface"],
  token_endpoint_auth_method: "none",
  logo_uri:                  "https://....", // optional
  client_uri:                 "[your website url]", // optional
}
  • "[your website url]/.well-known/oauth-cimd"를 클라이언트 ID로, PCKE를 인증 메커니즘으로 사용하세요.

로컬 포트에서 authorization code를 받는 네이티브 앱과 MCP 클라이언트는 redirect_uris에 포트 없는 루프백 URI를 나열할 수 있어요. 예: ["http://localhost/callback", "http://127.0.0.1/callback"]Redirect URIs 참고.

이 기능은 임시 환경이나 MCP 클라이언트에서 특히 유용해요. Hugging Chat의 구현 예시를 참고하세요.

디바이스 코드 OAuth (Device code OAuth)

디바이스 코드 흐름을 쓰면 사용자가 한 기기(예: CLI)에서 앱을 승인하고, 다른 기기(예: 폰이나 브라우저)에 짧은 코드를 입력해서 승인을 완료할 수 있어요. 앱이 실행 중인 기기에 리다이렉트 URI나 브라우저가 필요 없습니다.

예제 스크립트로 테스트하기 (Testing with a sample script)

다음 스크립트로 디바이스 코드 OAuth 앱을 테스트할 수 있어요. <Client ID>를 앱의 클라이언트 ID로 바꾸세요. 공개 앱(시크릿 없음)은 스크립트를 그대로 쓸 수 있어요. 시크릿이 있는 앱은 device 요청과 token 요청 양쪽에 Authorization: Basic 헤더(client_id:client_secret의 Base64)를 추가하세요.

#!/bin/bash
CLIENT_ID="<Client ID>"

# Step 1: Get device code
RESPONSE=$(curl -s -X POST https://huggingface.co/oauth/device \
  -d "client_id=$CLIENT_ID")

DEVICE_CODE=$(echo $RESPONSE | jq -r '.device_code')
USER_CODE=$(echo $RESPONSE | jq -r '.user_code')
VERIFICATION_URI=$(echo $RESPONSE | jq -r '.verification_uri')

echo "Device Code: $DEVICE_CODE"
echo "User Code: $USER_CODE"
echo ""
echo "Open: ${VERIFICATION_URI}"
echo "Enter the user code: $USER_CODE"
echo ""
read -p "Press Enter after authorizing..."

# Step 3: Get token
curl -X POST https://huggingface.co/oauth/token \
  -d "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
  -d "device_code=$DEVICE_CODE" \
  -d "client_id=$CLIENT_ID"

[!NOTE] 클라이언트 시크릿이 있는 OAuth 앱은 device code 요청과 token 요청 양쪽에 Authorization: Basic 헤더(Base64로 인코딩된 client_id:client_secret)를 포함해야 해요.

현재 지원되는 스코프 (Currently supported scopes)

현재 지원되는 스코프는 다음과 같아요:

  • openid: access token에 더해 ID token을 받습니다.
  • profile: 사용자 프로필 정보(사용자명, 아바타 등)를 읽습니다.
  • email: 사용자의 이메일 주소를 읽습니다.
  • read-billing: 사용자가 결제 수단을 설정했는지 알 수 있습니다.
  • read-memberships: 사용자가 속한 조직과 각 조직에서의 역할을 읽습니다. 조직의 설정이나 리소스 접근 권한은 부여하지 않아요.
  • read-repos: 사용자의 개인 리포지토리를 읽습니다.
  • gated-repos: 사용자가 접근 권한을 받은 공개 gated 리포지토리의 내용을 읽습니다. read-repos와 달리 비공개 리포지토리 접근은 부여하지 않아요.
  • contribute-repos: 리포지토리를 만들고 이 앱이 만든 리포지토리에 접근합니다. 추가 권한을 받지 않는 한 다른 리포지토리에는 접근할 수 없어요.
  • write-repos: 사용자의 개인 리포지토리를 읽고 씁니다.
  • manage-repos: 만들기와 삭제를 포함해 사용자의 개인 리포지토리를 완전히 관리합니다.
  • read-collections: 사용자의 개인 컬렉션을 읽습니다.
  • write-collections: 만들기와 삭제를 포함해 사용자의 개인 컬렉션을 읽고 씁니다.
  • inference-api: 사용자를 대신해 Inference Providers에 inference 요청을 보냅니다.
  • read-endpoints: 사용자의 Inference Endpoints를 보고 사용자를 대신해 inference 요청을 보냅니다.
  • write-endpoints: 만들기와 삭제를 포함해 사용자의 Inference Endpoints를 관리합니다. read-endpoints 접근을 포함합니다.
  • jobs: jobs를 실행합니다.
  • webhooks: webhooks를 관리합니다.
  • write-discussions: 사용자를 대신해 discussions와 Pull Requests를 열고, reactions, 댓글 작성/수정, discussion 닫기 등과 상호작용합니다. 비공개 리포지토리에 Pull Requests를 열려면 read-repos 스코프도 요청해야 해요.

그 외의 모든 정보는 OpenID 메타데이터에서 확인할 수 있어요.

[!WARNING] 추가 스코프가 필요하면 저희에게 연락해 주세요.

조직 리소스 접근 (Accessing organization resources)

기본적으로 OAuth 앱은 조직 리소스에 접근할 필요가 없어요.

하지만 read-reposread-billing 같은 일부 스코프는 조직에도 적용됩니다.

사용자는 앱을 승인할 때 접근을 허용할 조직을 선택할 수 있어요. 특정 조직에 접근이 필요하면 OAuth 승인 URL에 orgIds=ORG_ID 쿼리 파라미터를 추가하면 됩니다. ORG_ID는 userinfo 응답의 organizations.sub 필드에서 확인할 수 있는 조직 ID로 바꿔야 해요.

브랜딩 (Branding)

버튼 디자인은 자유롭게 만들 수 있어요. 아래는 유용하게 제공되는 SVG 이미지들입니다.

badges 페이지에서 markdown이나 HTML에 통합하는 방법과 함께 확인해 보세요.

Sign in with Hugging Face Sign in with Hugging Face

Sign in with Hugging Face Sign in with Hugging Face

Sign in with Hugging Face Sign in with Hugging Face

Sign in with Hugging Face Sign in with Hugging Face

조직용 토큰 교환 (RFC 8693, Token Exchange for Organizations)

[!WARNING] 이 기능은 Enterprise 플랜에 포함돼 있어요.

Token Exchange를 쓰면 조직이 대화형 사용자 동의 없이 프로그램적으로 멤버용 access token을 발급할 수 있어요. 조직 멤버를 대신해 Hugging Face 리소스에 접근해야 하는 내부 도구, 자동화 파이프라인, 엔터프라이즈 통합을 만들 때 특히 유용합니다.

[!TIP] 멤버별 토큰 발급 없이 CI/CD 워크플로(GitHub Actions, GitLab CI, CircleCI 등)에서 키 없는 인증만 필요하다면 Trusted Publishers를 참고하세요. 이 역시 /oauth/token을 사용하지만 CI 제공자가 발급한 OIDC id_token을 subject token으로 씁니다(Enterprise 플랜 불필요, 클라이언트 자격증명 불필요).

이 기능은 토큰 교환 시나리오의 표준 프로토콜인 RFC 8693 - OAuth 2.0 Token Exchange를 구현합니다.

사용 사례 (Use cases)

Token Exchange는 다음과 같은 시나리오를 위해 설계됐어요:

  • 내부 플랫폼 구축: 팀 멤버가 각자 수동으로 인증하지 않아도 팀 멤버를 대신해 Hugging Face 리소스에 접근하는 대시보드나 포털을 만듭니다.
  • CI/CD 파이프라인 자동화: 조직 리포지토리에 모델이나 데이터셋을 올려야 하는 자동화 워크플로용 단기·스코프된 토큰을 발급합니다.
  • 엔터프라이즈 ID 시스템 통합: 내부 사용자 디렉터리를 기반으로 토큰을 발급해 기존 ID 제공자와 Hugging Face를 연결합니다.
  • 커스텀 접근 제어 구현: 조직의 내부 정책에 따라 특정 스코프로 토큰을 발급하는 미들웨어를 만듭니다.

동작 방식 (How it works)

  1. 조직에 token-exchange 권한이 있는 OAuth 애플리케이션을 바인딩합니다.
  2. 백엔드 서비스가 클라이언트 자격증명으로 이 OAuth 앱에 인증합니다.
  3. 서비스가 특정 조직 멤버(이메일로 식별)의 access token을 요청합니다.
  4. Hugging Face가 사용자가 조직의 멤버인지 확인하고 스코프된 토큰을 발급합니다.
  5. 발급된 토큰은 조직 스코프 안의 리소스에만 접근할 수 있습니다.

사전 요구사항 (Prerequisites)

Token Exchange를 쓰려면 token-exchange 권한이 있는 조직 바인딩 OAuth 애플리케이션이 필요해요. 조직에 적격한 OAuth 앱을 설정하려면 Hugging Face 지원팀에 문의하세요.

설정이 끝나면 다음을 받게 됩니다:

  • Client ID (예: a1b2c3d4-e5f6-7890-abcd-ef1234567890)
  • Client Secret (안전하게 보관하세요!)

[!WARNING] 조직 관리자는 생성 후 OAuth 앱을 관리할 수 있어요. 클라이언트 시크릿 갱신과 토큰 유효기간 설정이 포함됩니다.

인증 (Authentication)

Token Exchange는 OAuth 앱 자격증명으로 HTTP Basic Authentication을 사용합니다. client_id:client_secret을 Base64로 인코딩해 authorization 헤더를 만드세요:

# Create the authorization header
export CLIENT_ID="your-client-id"
export CLIENT_SECRET="your-client-secret"
export AUTH_HEADER=$(echo -n "${CLIENT_ID}:${CLIENT_SECRET}" | base64)

이메일로 토큰 발급하기 (Issuing tokens by email)

조직 멤버의 이메일 주소로 access token을 발급하려면:

curl -X POST "https://huggingface.co/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Authorization: Basic ${AUTH_HEADER}" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
  -d "[email protected]" \
  -d "subject_token_type=urn:huggingface:token-type:user-email"

응답 (Response)

성공적인 요청은 access token을 반환합니다:

{
  "access_token": "hf_oauth_...",
  "token_type": "bearer",
  "expires_in": 28800,
  "scope": "openid profile email read-repos",
  "id_token": "eyJhbGciOiJS...",
  "issued_token_type": "urn:ietf:params:oauth:token-type:access_token"
}

id_token 필드는 openid 스코프를 요청했을 때 포함됩니다.

이 토큰을 사용해 사용자를 대신해 API 요청을 보낼 수 있어요:

curl "https://huggingface.co/api/whoami-v2" \
  -H "Authorization: Bearer ${TOKEN}"

스코프 제어 (Scope control)

기본적으로 발급된 토큰은 OAuth 앱에 구성된 모든 스코프를 상속합니다. scope 파라미터를 추가해 특정 스코프를 요청할 수 있어요. 사용 가능한 값은 Currently supported scopes를 참고하세요.

토큰의 유효 권한은 요청된 스코프와 사용자의 조직 내 역할 양쪽에 의해 제한됩니다.

curl -X POST "https://huggingface.co/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Authorization: Basic ${AUTH_HEADER}" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
  -d "[email protected]" \
  -d "subject_token_type=urn:huggingface:token-type:user-email" \
  -d "scope=openid profile"

[!TIP] 최소 권한 원칙을 따르세요. 애플리케이션이 실제로 필요한 스코프만 요청하세요.

보안 고려사항 (Security considerations)

Token Exchange로 발급된 토큰에는 보안 제한이 내장돼 있어요:

  • 조직 스코프: 토큰은 조직이 소유한 리소스(모델, 데이터셋, Spaces, 컬렉션) 안에서만 접근할 수 있어요. 조직 밖에서는 읽기 전용이며, 어떤 사용자/조직의 공개 컬렉션과 사용자가 개별적으로 접근 권한을 받은 공개 gated 리포지토리로 제한됩니다.
  • 개인 접근 없음: 토큰은 사용자의 개인 비공개 리포지토리나 다른 조직의 비공개 리포지토리에 접근할 수 없어요.
  • 단기 유효: 토큰은 기본적으로 8시간 후 만료됩니다. 조직 관리자는 OAuth 앱 설정에서 토큰 유효기간(최대 30일)을 구성할 수 있어요. refresh token은 제공되지 않습니다.
  • 감사 가능: 모든 토큰 교환은 기록되며 조직의 audit logs에 표시됩니다.

[!WARNING] OAuth 앱 자격증명을 안전하게 보호하세요. 클라이언트 시크릿에 접근할 수 있는 사람은 조직의 모든 멤버를 위해 토큰을 발급할 수 있어요.

오류 응답 (Error responses)

Error Description
invalid_client 클라이언트가 토큰 교환 권한이 없거나 앱이 조직에 바인딩되지 않음
invalid_grant 바인딩된 조직에서 사용자를 찾을 수 없음
invalid_scope 요청한 스코프가 유효하지 않음

참고 (Reference)

Grant type:

urn:ietf:params:oauth:grant-type:token-exchange

요청 파라미터 (subject_token_type):

Value Description
urn:huggingface:token-type:user-email 이메일 주소로 사용자 식별

응답 필드 (issued_token_type):

Value Description
urn:ietf:params:oauth:token-type:access_token access token이 발급됐음을 나타냄

관련 문서:

더 알아보기 (Learn more)

OAuth 앱을 만들고 나면 Spaces OAuth 가이드와 Trusted Publishers, 그리고 사용자 프로필·멤버십을 읽어오는 스코프 조합을 함께 살펴보는 걸 추천해요. 실제 동작 예시는 Hugging Chat의 구현 PR을 참고할 수 있습니다.