InfoGrab DocsInfoGrab Docs

인증 개발 가이드라인

요약

Authentication 팀은 System Access와 User Profile 두 가지 기능 카테고리를 담당합니다. GitLab의 인증 및 인가에 관한 심층적인 보안 지식은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

Authentication 팀은 System AccessUser Profile 두 가지 기능 카테고리를 담당합니다. 이 가이드는 해당 카테고리의 주요 주제, 참조 위치, 그리고 주의해야 할 사항을 다룹니다.

GitLab의 인증 및 인가에 관한 심층적인 보안 지식은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

요청 흐름 개요#

모든 인증 흐름은 current_user로 수렴됩니다:

HTTP Request
    │
    ▼
Rack Middleware (Labkit → Rack::Attack → Warden → CSRF)
    │
    ├── Web Request ──► SessionsController / OmniauthCallbacks ──► Warden Strategies
    │
    └── API Request ──► API::APIGuard ──► AuthFinders (token lookup)
                                              │
                                              ▼
                                         current_user

API 요청의 경우, AuthFinders(lib/gitlab/auth/auth_finders.rb)는 다음 순서로 인증 소스를 확인합니다:

  • Deploy token

  • Bearer token (job token, PAT, 또는 OAuth)

  • Job token (헤더 또는 파라미터)

  • Session fallback (웹에서 시작된 API 호출의 경우)

가드레일:

  • AuthFinders의 토큰 확인 순서를 변경하지 마세요. Deploy token, bearer token, job token, session은 특정 우선순위에 따라 확인됩니다. 순서를 변경하면 한 토큰 유형이 다른 토큰을 가릴 수 있습니다.

토큰 접두사#

토큰 접두사를 사용하여 디버깅 및 코드 리뷰 중 토큰 유형을 식별합니다.

접두사 토큰 유형 저장 방식
glpat- Personal, project, 또는 group access token SHA-256 digest
gldt- Deploy token AES-256-GCM 암호화
glcbt- CI job token AES-256-GCM 암호화
gloas- OAuth application secret SHA-512 digest

토큰 유형 및 저장 전략의 전체 목록은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

로그인 및 세션#

웹 로그인은 Devise와 Warden을 사용합니다. 설정은 config/initializers/8_devise.rb에 있으며 (8_ 접두사는 로드 순서를 제어합니다).

참조 위치 목적
app/controllers/sessions_controller.rb 웹 로그인 및 로그아웃.
config/initializers/warden.rb Warden 콜백, 세션 설정.
app/models/active_session.rb Redis 세션 추적.
app/controllers/admin/sessions_controller.rb Admin 모드 인증.

가드레일:

  • 병렬 세션 저장소를 생성하지 마세요. ActiveSession과 결합된 Devise를 사용하세요.

  • 로그인 제한에는 Rack::Attack(config/initializers/rack_attack.rb)을 사용하세요.

  • 기능 수준의 속도 제한(예: 토큰 생성, 비밀번호 재설정)에는 Gitlab::ApplicationRateLimiter를 사용하세요. 자세한 내용은 application rate limiter를 참조하세요.

  • 자격 증명(비밀번호, 토큰, 2FA 코드, 복구 코드)을 검증하는 모든 엔드포인트는 속도 제한이 적용되어야 합니다. 속도 제한 키잉은 가능한 경우 소스 IP만이 아닌 자격 증명 주체(로그인 또는 사용자)를 포함해야 합니다. 성공 시 초기화되는 IP 전용 스로틀은 자격 증명 스터핑으로 우회될 수 있습니다.

  • 권한 변경 시 세션 ID를 재생성하세요: 로그인, 2FA 통과, 비밀번호 변경, admin 모드 진입. 세션 고정 공격을 방어합니다.

세션 기반 인증에 대한 자세한 내용은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

액세스 토큰#

Personal access token(PAT), group access token, project access token, service account PAT는 모두 personal_access_tokens 테이블에 저장되며 동일한 인증 흐름을 공유합니다. 이들은 생성 방식, 소유하는 사용자 유형, 인증 후 적용되는 인가 검사에서 차이가 있습니다.

Personal access token#

참조 위치 목적
app/models/personal_access_token.rb PAT 모델, 스코프, 만료 유효성 검사.
lib/api/personal_access_tokens.rb PAT REST API (목록 조회, 취소, 교체).
app/controllers/user_settings/personal_access_tokens_controller.rb PAT UI.
app/services/personal_access_tokens/ 생성, 취소, 교체 서비스.

Group 및 project access token#

참조 위치 목적
lib/api/resource_access_tokens.rb group/project 토큰용 REST API.
app/services/resource_access_tokens/create_service.rb bot 사용자 프로비저닝을 포함한 토큰 생성.
app/controllers/groups/settings/access_tokens_controller.rb Group 토큰 UI.
app/controllers/projects/settings/access_tokens_controller.rb Project 토큰 UI.

Service account#

Service account(user_type: :service_account)는 외부 통합 및 자동화를 위한 전용 사용자입니다. 인스턴스, 그룹, 또는 프로젝트 수준에서 프로비저닝할 수 있습니다.

  • 인스턴스 관리자만 인스턴스 수준 service account를 생성할 수 있습니다 (app/services/users/service_accounts/create_service.rb).

  • 그룹 Owner만 그룹 수준 service account를 생성할 수 있습니다 (app/services/namespaces/service_accounts/group_create_service.rb).

  • Project Maintainer 이상만 프로젝트 수준 service account를 생성할 수 있습니다 (app/services/namespaces/service_accounts/project_create_service.rb).

  • composite_identity_enforced: true인 service account는 시트 계산에서 제외됩니다.

참조 위치 목적
lib/api/service_accounts.rb 인스턴스 SA REST API.
lib/api/group_service_accounts.rb Group SA REST API.
lib/api/project_service_accounts.rb Project SA REST API.

액세스 토큰 가드레일#

  • 임시 토큰 칼럼이나 수동 해싱을 생성하지 마세요. add_authentication_token_field와 함께 TokenAuthenticatable concern을 사용하세요. 자세한 내용은 TokenAuthenticatable concern 사용하기를 참조하세요.

  • insecure: true 저장 전략으로 새 토큰 유형을 추가하지 마세요. SHA-256 digest 저장에는 digest: true를, AES-256-GCM 암호화 저장에는 encrypted: :required를 사용하세요. 자세한 내용은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

  • MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS(365)는 날짜가 제공되지 않을 때 적용되는 기본 만료 설정입니다. require_personal_access_token_expiry가 비활성화된 경우 상한선으로 강제 적용되지 않습니다.

  • 교체 중에는 토큰 만료 로직을 변경하지 마세요. 토큰 교체는 원래의 만료 정책을 유지해야 합니다. 과거 사례: PAT 교체 시 service account 만료 날짜와 그룹 멤버십 만료 날짜가 변경된 사례가 있습니다.

  • 사용자를 차단할 때, 모든 서브시스템에서 모든 활성 토큰이 무효화되었는지 확인하세요. 과거 사례: 차단된 사용자의 PAT가 계속해서 유효한 컨테이너 레지스트리 JWT를 발급했습니다.

  • 새 토큰 유형에는 기본적으로 만료를 설정하세요. 명시적으로 필요한 경우가 아니라면 만료 없이 토큰을 생성할 수 없도록 하세요.

  • 새 엔드포인트에서 URL 쿼리 파라미터로 토큰을 허용하지 마세요. PAT에는 PRIVATE-TOKEN 헤더를, OAuth에는 Authorization: Bearer를 사용하세요.

액세스 토큰 인증에 대한 자세한 내용은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

CI job token#

CI job token은 파이프라인 job이 GitLab API에 인증하도록 합니다.

참조 위치 목적
lib/ci/job_token/jwt.rb JWT 생성 및 서명.
lib/gitlab/auth/auth_finders.rb Job token 추출 및 조회.
app/models/ci/build.rb Build 모델, 토큰 저장 (암호화).
ee/app/models/concerns/ee/ci/job_token/jwt.rb EE 확장 (composite identity).

가드레일:

  • CI job token은 RSA로 서명된 JWT입니다. 평문으로 저장하거나 문자열 동등 비교를 사용하지 마세요.

  • Job token은 특정 파이프라인 job에 스코프가 지정되며 job과 함께 만료됩니다. job 기간 이상으로 수명을 연장하지 마세요.

자세한 내용은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

OAuth 및 OpenID Connect#

GitLab은 OAuth 제공자이자 클라이언트 역할을 모두 수행합니다. GitLab은 또한 doorkeeper-openid_connect를 통해 OpenID Connect(OIDC) 제공자로도 작동합니다.

GitLab의 OAuth 및 OIDC 제공자 역할#

외부 애플리케이션이 Doorkeeper를 사용하여 GitLab을 통해 사용자를 인증합니다. OIDC는 OAuth 위에 ID 레이어를 추가하여 액세스 토큰과 함께 ID 토큰을 발급합니다.

참조 위치 목적
app/controllers/oauth/authorizations_controller.rb 인가 프롬프트 및 코드 생성.
app/controllers/oauth/tokens_controller.rb 토큰 교환 엔드포인트.
app/models/authn/oauth_application.rb OAuth 애플리케이션 등록.
app/models/oauth_access_token.rb 액세스 토큰 저장 (Sha512Hash).
config/initializers/doorkeeper.rb Doorkeeper 설정, 스코프, 부여 흐름.
config/initializers/doorkeeper_openid_connect.rb OIDC 제공자 설정, 클레임, 서명 키.
app/controllers/oauth/discovery_controller.rb OIDC 검색 엔드포인트 (/.well-known/openid-configuration).

OIDC 클레임은 doorkeeper_openid_connect.rb에 정의됩니다. 표준 클레임에는 sub, name, email, groups, 그리고 권한 기반 그룹 클레임 (https://gitlab.org/claims/groups/owner 등)이 포함됩니다.

GitLab에서의 OAuth에 대한 자세한 내용은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

가드레일:

  • 데이터 노출을 고려하지 않고 새 OIDC 클레임을 추가하지 마세요. 각 클레임은 요청 애플리케이션에 표시되는 ID 토큰에 포함됩니다.

  • OIDC 서명 키(openid_connect_signing_key)는 Rails 자격 증명에 저장됩니다. 인프라 팀과 조율하지 않고 로깅, 노출, 또는 교체하지 마세요.

  • 항상 만료가 있는 토큰을 생성하세요. 만료를 가능한 짧게 유지하세요.

GitLab의 OAuth 클라이언트 역할#

사용자가 OmniAuth 전략을 사용하여 외부 제공자(Google, GitHub, Azure)를 통해 GitLab에 로그인합니다.

참조 위치 목적
app/controllers/omniauth_callbacks_controller.rb 모든 제공자의 콜백 핸들러.
lib/gitlab/auth/o_auth/user.rb 사용자 조회, 생성, ID 연결.
lib/gitlab/auth/o_auth/auth_hash.rb 제공자로부터 인증 데이터 파싱.
config/initializers/omniauth.rb OmniAuth 초기화.

가드레일:

  • 커스텀 OAuth 흐름을 구현하지 마세요. 외부 제공자에는 OmniAuth 전략을, 제공자 측에는 Doorkeeper를 사용하세요.

  • GitLab이 OAuth 클라이언트로 작동할 때 PKCE를 사용하세요.

SAML#

SAML은 ID 제공자(Okta, Azure AD)를 통해 SSO를 제공합니다. GitLab은 두 가지 SAML 모드를 지원합니다:

측면 인스턴스 SAML Group SAML (EE)
범위 전체 GitLab 인스턴스 최상위 그룹별
설정 gitlab.rb 또는 omniauth_providers Group Settings UI
라우트 /users/auth/saml /groups/:path/-/saml
전략 omniauth-saml gem 커스텀 GroupSaml 전략
적용 인스턴스 전체 그룹별 SSO 적용
참조 위치 목적
lib/gitlab/auth/saml/ 인스턴스 수준 SAML 전략 및 ID 연결자.
ee/lib/gitlab/auth/group_saml/ Group SAML: 사용자 확인, ID 연결, 멤버십 업데이트.
ee/app/controllers/groups/omniauth_callbacks_controller.rb Group SAML 콜백 핸들러.
ee/app/controllers/groups/sso_controller.rb Group SSO 페이지.
ee/app/controllers/groups/saml_providers_controller.rb SAML 제공자 설정 UI.
ee/lib/api/provider_identity.rb SAML/SCIM ID 및 extern_uid 관리 API.

가드레일:

  • API를 통해 extern_uid를 수정할 때 trusted_extern_uidfalse로 설정하세요. 기본 OAuth 로그인 클래스(lib/gitlab/auth/o_auth/user.rb)는 사용자를 확인하기 전에 trusted_extern_uid?를 검사합니다. 서브클래스에서 사용자 조회를 재정의할 때, 재정의도 이 플래그를 확인하는지 검증하세요.

  • SAML RelayState 파라미터를 리다이렉트 타깃으로 사용하기 전에 검증하세요. 과거 사례: SAML Single Logout에서 검증되지 않은 RelayState를 통한 오픈 리다이렉트.

  • 모든 SAML 응답에서 XML 서명을 검증하고 서명된 요소가 신뢰받는 어설션인지 확인하세요. XML 서명 래핑을 방어합니다. 과거 사례: #486565 — 인증되지 않은 SAML 로그인 우회.

SCIM#

SCIM은 사용자 수명 주기 관리(프로비저닝 및 디프로비저닝)를 자동화합니다. SCIM은 프로비저닝 전용이며 인증을 처리하지 않습니다.

참조 위치 목적
ee/app/models/scim_identity.rb SCIM ID 레코드.
ee/lib/api/scim/group_scim.rb Group SCIM API (RFC 7644).
ee/app/controllers/groups/settings/domain_verification_controller.rb SCIM용 도메인 검증.

자세한 내용은 SCIM 설정을 참조하세요.

LDAP#

LDAP는 디렉터리 서비스(Active Directory, OpenLDAP)에 대해 사용자를 인증합니다.

참조 위치 목적
lib/gitlab/auth/ldap/ LDAP 인증 및 어댑터.
ee/lib/gitlab/auth/ldap/ EE LDAP 동기화, 그룹 링크.
ee/app/controllers/groups/ldaps_controller.rb LDAP 그룹 동기화 UI.
ee/lib/api/ldap.rb LDAP REST API.

자세한 내용은 GitLab과 LDAP 통합을 참조하세요.

2단계 인증#

2단계 인증(2FA)은 로그인에 두 번째 인증 단계를 추가합니다.

참조 위치 목적
app/controllers/profiles/two_factor_auths_controller.rb 2FA 설정 UI (TOTP, WebAuthn).
app/controllers/profiles/passkeys_controller.rb Passkey 관리.
app/controllers/concerns/authenticates_with_two_factor.rb 로그인 흐름에서의 2FA 적용.
app/controllers/concerns/enforces_two_factor_authentication.rb 2FA 요구 사항 확인.

가드레일:

  • 인증 전에 로그인 파라미터(사용자 이름, 이메일)를 정제하세요. 과거 사례: 로그인 파라미터의 공백 문자가 WebAuthn 2FA를 우회했습니다 (#585333).

  • passkey 또는 2FA 장치가 삭제되면, 해당 자격 증명으로 인증된 모든 세션을 무효화하세요.

  • read_api 또는 다른 제한된 스코프 토큰이 sudo 모드 또는 상승된 인증 요구 사항을 우회하도록 허용하지 마세요.

SSH 키#

SSH 키는 SSH를 통한 Git 작업을 인증합니다.

참조 위치 목적
app/controllers/user_settings/ssh_keys_controller.rb SSH 키 관리 UI.
lib/api/keys.rb SSH 키 REST API.
app/models/key.rb SSH 키 모델 및 유효성 검사.

ID 연결 및 extern_uid#

사용자가 외부 제공자를 통해 인증하면, GitLab은 GitLab 사용자를 제공자 계정에 연결하는 Identity 레코드를 생성합니다.

Identity 모델(app/models/identity.rb)은 다음을 저장합니다:

  • user_id: GitLab 사용자.

  • provider: 제공자 이름(예: google_oauth2, group_saml, ldapmain).

  • extern_uid: 제공자로부터 받은 사용자의 고유 식별자.

  • saml_provider_id: Group SAML의 경우, 그룹의 SAML 설정에 연결됩니다.

  • trusted_extern_uid: Boolean 플래그로 기본값은 true. API를 통해 extern_uid가 수정되면 false로 설정됩니다.

로그인 중 GitLab은 다음과 같이 ID를 통해 사용자를 확인합니다:

  • 외부 제공자가 UID가 포함된 인증 응답을 반환합니다.

  • GitLab은 제공자와 UID가 일치하는 Identity 레코드를 조회합니다.

  • 레코드가 발견되고 신뢰받는 경우, GitLab은 연결된 사용자로 로그인합니다.

  • 발견되지 않으면, GitLab은 새 사용자를 생성하거나 계정 연결을 요청합니다.

가드레일:

  • trusted_extern_uidfalse로 설정하지 않고 extern_uid를 업데이트하지 마세요. 검증되지 않은 extern_uid 변경은 계정 탈취를 가능하게 할 수 있습니다.

  • OAuth 서브클래스(예: GroupSaml::User)에서 사용자 조회를 재정의할 때, 재정의가 trusted_extern_uid?를 확인하는지 검증하세요. 기본 클래스는 이를 확인하지만 재정의는 이를 우회할 수 있습니다.

  • ID가 신뢰받는지(trusted_extern_uid?) 확인하지 않고 extern_uid만으로 사용자를 확인하지 마세요.

비밀번호 관리#

참조 위치 목적
app/controllers/passwords_controller.rb 비밀번호 재설정 흐름.
app/controllers/user_settings/passwords_controller.rb 비밀번호 변경.
app/models/concerns/recoverable_by_any_email.rb 기본 또는 보조 이메일로 재설정.

가드레일:

  • 비밀번호 재설정 흐름에서 모든 사용자 제공 리다이렉트 타깃을 검증하기 위해 InternalRedirect#sanitize_redirect 또는 safe_redirect_path를 사용하세요. 원시 파라미터를 redirect_to에 전달하지 마세요. 항상 폴백을 제공하세요:
redirect_to sanitize_redirect(params[:redirect]) || root_path
  • 비밀번호 재설정 토큰은 단일 사용, 단기간, 성공적인 사용 후 무효화되어야 합니다. 성공적인 재설정은 사용자의 다른 모든 활성 세션을 무효화해야 합니다.

  • 비밀번호 재설정 엔드포인트는 이메일 파라미터가 단일 문자열 값인지 검증하고 배열 또는 다른 비문자열 유형으로 제공된 모든 요청을 거부해야 합니다. 과거 사례: #436084 — 비밀번호 재설정을 통한 계정 탈취.

  • 로그인 실패 및 비밀번호 재설정 응답은 "사용자는 존재하지만 자격 증명이 잘못됨"과 "사용자가 존재하지 않음" 간에 차이가 없어야 합니다. 동일한 응답 본문과 동일한 타이밍을 사용하세요. 계정 열거 공격을 방어합니다.

사용자 프로필#

참조 위치 목적
app/controllers/profiles_controller.rb 프로필 표시.
app/controllers/user_settings/profiles_controller.rb 프로필 편집.
app/controllers/profiles/emails_controller.rb 이메일 관리.
app/controllers/profiles/avatars_controller.rb 아바타 업로드.
app/controllers/profiles/preferences_controller.rb 사용자 환경 설정.

API 인증#

API 요청은 API::APIGuard(lib/api/api_guard.rb)를 통해 인증되며, OAuth2 bearer token, 스코프 적용, DPoP 검사, 오류 처리를 담당합니다.

참조 위치 목적
lib/api/api_guard.rb API 인증 모듈.
lib/gitlab/auth/auth_finders.rb API 요청의 토큰 조회.
lib/gitlab/auth/request_authenticator.rb Rack::Attack 및 로깅 전용 요청 ID 확인. 액세스 제어에는 사용하지 마세요.
app/services/auth/dpop_authentication_service.rb DPoP proof-of-possession 검증.

가드레일:

  • 커스텀 API 인증을 구현하지 마세요. API::APIGuard를 사용하세요.

  • JWT 또는 토큰 파싱을 직접 구현하지 마세요. Authn::IamService::JwtValidationService를 사용하세요.

  • 토큰 생성 및 검증 엔드포인트의 속도 제한에는 check_rate_limit!를 사용하세요.

공유 인프라#

인증 코드는 웹, API, OAuth, SAML 진입점 전체에 걸쳐 공유됩니다. 공유 인프라의 변경은 모든 흐름을 중단시킬 수 있습니다.

참조 위치 목적
app/models/authn/, app/services/authn/, lib/authn/ 인증 모델, 서비스, 토큰 프레임워크.
lib/gitlab/auth/ 핵심 인증 인프라.
app/controllers/concerns/internal_redirect.rb 안전한 리다이렉트 검증.

가드레일:

  • 모든 호출자를 감사하지 않고 인증 메서드의 반환 유형이나 nil-vs-value 시맨틱을 변경하지 마세요.

  • 인증 코드는 모든 진입점에 걸쳐 공유됩니다. 공유 인프라를 수정할 때 모든 흐름이 여전히 작동하는지 확인하세요.

  • 토큰 값, 비밀번호 값, 또는 세션 ID를 절대 로깅하지 마세요. 여기에는 오류 메시지, 감사 이벤트, 구조화된 로그, 백트레이스가 포함됩니다.

  • 토큰 동등 비교는 일정 시간 함수 (ActiveSupport::SecurityUtils.secure_compare)를 사용해야 합니다. 토큰 검증의 타이밍 공격을 방어합니다.

  • 사용자 차단, 금지, 또는 비활성화를 수정할 때, 차단 상태가 로그인 시점이 아닌 사용 시점에 확인되는지 검증하세요. 토큰, 세션, API 액세스는 모두 차단 상태를 존중해야 합니다.

  • 새 인증 경로 또는 토큰 유형을 추가할 때, user.blocked? 확인을 존중하는지 검증하세요.

  • 원시 사용자 제공 파라미터를 redirect_to에 전달하지 마세요. InternalRedirect#sanitize_redirect 또는 safe_redirect_path를 사용하세요. 리다이렉트 헬퍼는 유효하지 않은 타깃에 대해 nil을 반환합니다. 항상 폴백을 제공하세요.

기능 플래그#

인증 기능 플래그에는 group: group::authentication을 사용하세요.

관련 항목#

인증 개발 가이드라인

GitLab v19.1
원문 보기
요약

Authentication 팀은 System Access와 User Profile 두 가지 기능 카테고리를 담당합니다. GitLab의 인증 및 인가에 관한 심층적인 보안 지식은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

Authentication 팀은 System AccessUser Profile 두 가지 기능 카테고리를 담당합니다. 이 가이드는 해당 카테고리의 주요 주제, 참조 위치, 그리고 주의해야 할 사항을 다룹니다.

GitLab의 인증 및 인가에 관한 심층적인 보안 지식은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

요청 흐름 개요#

모든 인증 흐름은 current_user로 수렴됩니다:

HTTP Request
    │
    ▼
Rack Middleware (Labkit → Rack::Attack → Warden → CSRF)
    │
    ├── Web Request ──► SessionsController / OmniauthCallbacks ──► Warden Strategies
    │
    └── API Request ──► API::APIGuard ──► AuthFinders (token lookup)
                                              │
                                              ▼
                                         current_user

API 요청의 경우, AuthFinders(lib/gitlab/auth/auth_finders.rb)는 다음 순서로 인증 소스를 확인합니다:

  • Deploy token

  • Bearer token (job token, PAT, 또는 OAuth)

  • Job token (헤더 또는 파라미터)

  • Session fallback (웹에서 시작된 API 호출의 경우)

가드레일:

  • AuthFinders의 토큰 확인 순서를 변경하지 마세요. Deploy token, bearer token, job token, session은 특정 우선순위에 따라 확인됩니다. 순서를 변경하면 한 토큰 유형이 다른 토큰을 가릴 수 있습니다.

토큰 접두사#

토큰 접두사를 사용하여 디버깅 및 코드 리뷰 중 토큰 유형을 식별합니다.

접두사 토큰 유형 저장 방식
glpat- Personal, project, 또는 group access token SHA-256 digest
gldt- Deploy token AES-256-GCM 암호화
glcbt- CI job token AES-256-GCM 암호화
gloas- OAuth application secret SHA-512 digest

토큰 유형 및 저장 전략의 전체 목록은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

로그인 및 세션#

웹 로그인은 Devise와 Warden을 사용합니다. 설정은 config/initializers/8_devise.rb에 있으며 (8_ 접두사는 로드 순서를 제어합니다).

참조 위치 목적
app/controllers/sessions_controller.rb 웹 로그인 및 로그아웃.
config/initializers/warden.rb Warden 콜백, 세션 설정.
app/models/active_session.rb Redis 세션 추적.
app/controllers/admin/sessions_controller.rb Admin 모드 인증.

가드레일:

  • 병렬 세션 저장소를 생성하지 마세요. ActiveSession과 결합된 Devise를 사용하세요.

  • 로그인 제한에는 Rack::Attack(config/initializers/rack_attack.rb)을 사용하세요.

  • 기능 수준의 속도 제한(예: 토큰 생성, 비밀번호 재설정)에는 Gitlab::ApplicationRateLimiter를 사용하세요. 자세한 내용은 application rate limiter를 참조하세요.

  • 자격 증명(비밀번호, 토큰, 2FA 코드, 복구 코드)을 검증하는 모든 엔드포인트는 속도 제한이 적용되어야 합니다. 속도 제한 키잉은 가능한 경우 소스 IP만이 아닌 자격 증명 주체(로그인 또는 사용자)를 포함해야 합니다. 성공 시 초기화되는 IP 전용 스로틀은 자격 증명 스터핑으로 우회될 수 있습니다.

  • 권한 변경 시 세션 ID를 재생성하세요: 로그인, 2FA 통과, 비밀번호 변경, admin 모드 진입. 세션 고정 공격을 방어합니다.

세션 기반 인증에 대한 자세한 내용은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

액세스 토큰#

Personal access token(PAT), group access token, project access token, service account PAT는 모두 personal_access_tokens 테이블에 저장되며 동일한 인증 흐름을 공유합니다. 이들은 생성 방식, 소유하는 사용자 유형, 인증 후 적용되는 인가 검사에서 차이가 있습니다.

Personal access token#

참조 위치 목적
app/models/personal_access_token.rb PAT 모델, 스코프, 만료 유효성 검사.
lib/api/personal_access_tokens.rb PAT REST API (목록 조회, 취소, 교체).
app/controllers/user_settings/personal_access_tokens_controller.rb PAT UI.
app/services/personal_access_tokens/ 생성, 취소, 교체 서비스.

Group 및 project access token#

참조 위치 목적
lib/api/resource_access_tokens.rb group/project 토큰용 REST API.
app/services/resource_access_tokens/create_service.rb bot 사용자 프로비저닝을 포함한 토큰 생성.
app/controllers/groups/settings/access_tokens_controller.rb Group 토큰 UI.
app/controllers/projects/settings/access_tokens_controller.rb Project 토큰 UI.

Service account#

Service account(user_type: :service_account)는 외부 통합 및 자동화를 위한 전용 사용자입니다. 인스턴스, 그룹, 또는 프로젝트 수준에서 프로비저닝할 수 있습니다.

  • 인스턴스 관리자만 인스턴스 수준 service account를 생성할 수 있습니다 (app/services/users/service_accounts/create_service.rb).

  • 그룹 Owner만 그룹 수준 service account를 생성할 수 있습니다 (app/services/namespaces/service_accounts/group_create_service.rb).

  • Project Maintainer 이상만 프로젝트 수준 service account를 생성할 수 있습니다 (app/services/namespaces/service_accounts/project_create_service.rb).

  • composite_identity_enforced: true인 service account는 시트 계산에서 제외됩니다.

참조 위치 목적
lib/api/service_accounts.rb 인스턴스 SA REST API.
lib/api/group_service_accounts.rb Group SA REST API.
lib/api/project_service_accounts.rb Project SA REST API.

액세스 토큰 가드레일#

  • 임시 토큰 칼럼이나 수동 해싱을 생성하지 마세요. add_authentication_token_field와 함께 TokenAuthenticatable concern을 사용하세요. 자세한 내용은 TokenAuthenticatable concern 사용하기를 참조하세요.

  • insecure: true 저장 전략으로 새 토큰 유형을 추가하지 마세요. SHA-256 digest 저장에는 digest: true를, AES-256-GCM 암호화 저장에는 encrypted: :required를 사용하세요. 자세한 내용은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

  • MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS(365)는 날짜가 제공되지 않을 때 적용되는 기본 만료 설정입니다. require_personal_access_token_expiry가 비활성화된 경우 상한선으로 강제 적용되지 않습니다.

  • 교체 중에는 토큰 만료 로직을 변경하지 마세요. 토큰 교체는 원래의 만료 정책을 유지해야 합니다. 과거 사례: PAT 교체 시 service account 만료 날짜와 그룹 멤버십 만료 날짜가 변경된 사례가 있습니다.

  • 사용자를 차단할 때, 모든 서브시스템에서 모든 활성 토큰이 무효화되었는지 확인하세요. 과거 사례: 차단된 사용자의 PAT가 계속해서 유효한 컨테이너 레지스트리 JWT를 발급했습니다.

  • 새 토큰 유형에는 기본적으로 만료를 설정하세요. 명시적으로 필요한 경우가 아니라면 만료 없이 토큰을 생성할 수 없도록 하세요.

  • 새 엔드포인트에서 URL 쿼리 파라미터로 토큰을 허용하지 마세요. PAT에는 PRIVATE-TOKEN 헤더를, OAuth에는 Authorization: Bearer를 사용하세요.

액세스 토큰 인증에 대한 자세한 내용은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

CI job token#

CI job token은 파이프라인 job이 GitLab API에 인증하도록 합니다.

참조 위치 목적
lib/ci/job_token/jwt.rb JWT 생성 및 서명.
lib/gitlab/auth/auth_finders.rb Job token 추출 및 조회.
app/models/ci/build.rb Build 모델, 토큰 저장 (암호화).
ee/app/models/concerns/ee/ci/job_token/jwt.rb EE 확장 (composite identity).

가드레일:

  • CI job token은 RSA로 서명된 JWT입니다. 평문으로 저장하거나 문자열 동등 비교를 사용하지 마세요.

  • Job token은 특정 파이프라인 job에 스코프가 지정되며 job과 함께 만료됩니다. job 기간 이상으로 수명을 연장하지 마세요.

자세한 내용은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

OAuth 및 OpenID Connect#

GitLab은 OAuth 제공자이자 클라이언트 역할을 모두 수행합니다. GitLab은 또한 doorkeeper-openid_connect를 통해 OpenID Connect(OIDC) 제공자로도 작동합니다.

GitLab의 OAuth 및 OIDC 제공자 역할#

외부 애플리케이션이 Doorkeeper를 사용하여 GitLab을 통해 사용자를 인증합니다. OIDC는 OAuth 위에 ID 레이어를 추가하여 액세스 토큰과 함께 ID 토큰을 발급합니다.

참조 위치 목적
app/controllers/oauth/authorizations_controller.rb 인가 프롬프트 및 코드 생성.
app/controllers/oauth/tokens_controller.rb 토큰 교환 엔드포인트.
app/models/authn/oauth_application.rb OAuth 애플리케이션 등록.
app/models/oauth_access_token.rb 액세스 토큰 저장 (Sha512Hash).
config/initializers/doorkeeper.rb Doorkeeper 설정, 스코프, 부여 흐름.
config/initializers/doorkeeper_openid_connect.rb OIDC 제공자 설정, 클레임, 서명 키.
app/controllers/oauth/discovery_controller.rb OIDC 검색 엔드포인트 (/.well-known/openid-configuration).

OIDC 클레임은 doorkeeper_openid_connect.rb에 정의됩니다. 표준 클레임에는 sub, name, email, groups, 그리고 권한 기반 그룹 클레임 (https://gitlab.org/claims/groups/owner 등)이 포함됩니다.

GitLab에서의 OAuth에 대한 자세한 내용은 Authentication & Authorization Security Knowledge Base (내부 문서)를 참조하세요.

가드레일:

  • 데이터 노출을 고려하지 않고 새 OIDC 클레임을 추가하지 마세요. 각 클레임은 요청 애플리케이션에 표시되는 ID 토큰에 포함됩니다.

  • OIDC 서명 키(openid_connect_signing_key)는 Rails 자격 증명에 저장됩니다. 인프라 팀과 조율하지 않고 로깅, 노출, 또는 교체하지 마세요.

  • 항상 만료가 있는 토큰을 생성하세요. 만료를 가능한 짧게 유지하세요.

GitLab의 OAuth 클라이언트 역할#

사용자가 OmniAuth 전략을 사용하여 외부 제공자(Google, GitHub, Azure)를 통해 GitLab에 로그인합니다.

참조 위치 목적
app/controllers/omniauth_callbacks_controller.rb 모든 제공자의 콜백 핸들러.
lib/gitlab/auth/o_auth/user.rb 사용자 조회, 생성, ID 연결.
lib/gitlab/auth/o_auth/auth_hash.rb 제공자로부터 인증 데이터 파싱.
config/initializers/omniauth.rb OmniAuth 초기화.

가드레일:

  • 커스텀 OAuth 흐름을 구현하지 마세요. 외부 제공자에는 OmniAuth 전략을, 제공자 측에는 Doorkeeper를 사용하세요.

  • GitLab이 OAuth 클라이언트로 작동할 때 PKCE를 사용하세요.

SAML#

SAML은 ID 제공자(Okta, Azure AD)를 통해 SSO를 제공합니다. GitLab은 두 가지 SAML 모드를 지원합니다:

측면 인스턴스 SAML Group SAML (EE)
범위 전체 GitLab 인스턴스 최상위 그룹별
설정 gitlab.rb 또는 omniauth_providers Group Settings UI
라우트 /users/auth/saml /groups/:path/-/saml
전략 omniauth-saml gem 커스텀 GroupSaml 전략
적용 인스턴스 전체 그룹별 SSO 적용
참조 위치 목적
lib/gitlab/auth/saml/ 인스턴스 수준 SAML 전략 및 ID 연결자.
ee/lib/gitlab/auth/group_saml/ Group SAML: 사용자 확인, ID 연결, 멤버십 업데이트.
ee/app/controllers/groups/omniauth_callbacks_controller.rb Group SAML 콜백 핸들러.
ee/app/controllers/groups/sso_controller.rb Group SSO 페이지.
ee/app/controllers/groups/saml_providers_controller.rb SAML 제공자 설정 UI.
ee/lib/api/provider_identity.rb SAML/SCIM ID 및 extern_uid 관리 API.

가드레일:

  • API를 통해 extern_uid를 수정할 때 trusted_extern_uidfalse로 설정하세요. 기본 OAuth 로그인 클래스(lib/gitlab/auth/o_auth/user.rb)는 사용자를 확인하기 전에 trusted_extern_uid?를 검사합니다. 서브클래스에서 사용자 조회를 재정의할 때, 재정의도 이 플래그를 확인하는지 검증하세요.

  • SAML RelayState 파라미터를 리다이렉트 타깃으로 사용하기 전에 검증하세요. 과거 사례: SAML Single Logout에서 검증되지 않은 RelayState를 통한 오픈 리다이렉트.

  • 모든 SAML 응답에서 XML 서명을 검증하고 서명된 요소가 신뢰받는 어설션인지 확인하세요. XML 서명 래핑을 방어합니다. 과거 사례: #486565 — 인증되지 않은 SAML 로그인 우회.

SCIM#

SCIM은 사용자 수명 주기 관리(프로비저닝 및 디프로비저닝)를 자동화합니다. SCIM은 프로비저닝 전용이며 인증을 처리하지 않습니다.

참조 위치 목적
ee/app/models/scim_identity.rb SCIM ID 레코드.
ee/lib/api/scim/group_scim.rb Group SCIM API (RFC 7644).
ee/app/controllers/groups/settings/domain_verification_controller.rb SCIM용 도메인 검증.

자세한 내용은 SCIM 설정을 참조하세요.

LDAP#

LDAP는 디렉터리 서비스(Active Directory, OpenLDAP)에 대해 사용자를 인증합니다.

참조 위치 목적
lib/gitlab/auth/ldap/ LDAP 인증 및 어댑터.
ee/lib/gitlab/auth/ldap/ EE LDAP 동기화, 그룹 링크.
ee/app/controllers/groups/ldaps_controller.rb LDAP 그룹 동기화 UI.
ee/lib/api/ldap.rb LDAP REST API.

자세한 내용은 GitLab과 LDAP 통합을 참조하세요.

2단계 인증#

2단계 인증(2FA)은 로그인에 두 번째 인증 단계를 추가합니다.

참조 위치 목적
app/controllers/profiles/two_factor_auths_controller.rb 2FA 설정 UI (TOTP, WebAuthn).
app/controllers/profiles/passkeys_controller.rb Passkey 관리.
app/controllers/concerns/authenticates_with_two_factor.rb 로그인 흐름에서의 2FA 적용.
app/controllers/concerns/enforces_two_factor_authentication.rb 2FA 요구 사항 확인.

가드레일:

  • 인증 전에 로그인 파라미터(사용자 이름, 이메일)를 정제하세요. 과거 사례: 로그인 파라미터의 공백 문자가 WebAuthn 2FA를 우회했습니다 (#585333).

  • passkey 또는 2FA 장치가 삭제되면, 해당 자격 증명으로 인증된 모든 세션을 무효화하세요.

  • read_api 또는 다른 제한된 스코프 토큰이 sudo 모드 또는 상승된 인증 요구 사항을 우회하도록 허용하지 마세요.

SSH 키#

SSH 키는 SSH를 통한 Git 작업을 인증합니다.

참조 위치 목적
app/controllers/user_settings/ssh_keys_controller.rb SSH 키 관리 UI.
lib/api/keys.rb SSH 키 REST API.
app/models/key.rb SSH 키 모델 및 유효성 검사.

ID 연결 및 extern_uid#

사용자가 외부 제공자를 통해 인증하면, GitLab은 GitLab 사용자를 제공자 계정에 연결하는 Identity 레코드를 생성합니다.

Identity 모델(app/models/identity.rb)은 다음을 저장합니다:

  • user_id: GitLab 사용자.

  • provider: 제공자 이름(예: google_oauth2, group_saml, ldapmain).

  • extern_uid: 제공자로부터 받은 사용자의 고유 식별자.

  • saml_provider_id: Group SAML의 경우, 그룹의 SAML 설정에 연결됩니다.

  • trusted_extern_uid: Boolean 플래그로 기본값은 true. API를 통해 extern_uid가 수정되면 false로 설정됩니다.

로그인 중 GitLab은 다음과 같이 ID를 통해 사용자를 확인합니다:

  • 외부 제공자가 UID가 포함된 인증 응답을 반환합니다.

  • GitLab은 제공자와 UID가 일치하는 Identity 레코드를 조회합니다.

  • 레코드가 발견되고 신뢰받는 경우, GitLab은 연결된 사용자로 로그인합니다.

  • 발견되지 않으면, GitLab은 새 사용자를 생성하거나 계정 연결을 요청합니다.

가드레일:

  • trusted_extern_uidfalse로 설정하지 않고 extern_uid를 업데이트하지 마세요. 검증되지 않은 extern_uid 변경은 계정 탈취를 가능하게 할 수 있습니다.

  • OAuth 서브클래스(예: GroupSaml::User)에서 사용자 조회를 재정의할 때, 재정의가 trusted_extern_uid?를 확인하는지 검증하세요. 기본 클래스는 이를 확인하지만 재정의는 이를 우회할 수 있습니다.

  • ID가 신뢰받는지(trusted_extern_uid?) 확인하지 않고 extern_uid만으로 사용자를 확인하지 마세요.

비밀번호 관리#

참조 위치 목적
app/controllers/passwords_controller.rb 비밀번호 재설정 흐름.
app/controllers/user_settings/passwords_controller.rb 비밀번호 변경.
app/models/concerns/recoverable_by_any_email.rb 기본 또는 보조 이메일로 재설정.

가드레일:

  • 비밀번호 재설정 흐름에서 모든 사용자 제공 리다이렉트 타깃을 검증하기 위해 InternalRedirect#sanitize_redirect 또는 safe_redirect_path를 사용하세요. 원시 파라미터를 redirect_to에 전달하지 마세요. 항상 폴백을 제공하세요:
redirect_to sanitize_redirect(params[:redirect]) || root_path
  • 비밀번호 재설정 토큰은 단일 사용, 단기간, 성공적인 사용 후 무효화되어야 합니다. 성공적인 재설정은 사용자의 다른 모든 활성 세션을 무효화해야 합니다.

  • 비밀번호 재설정 엔드포인트는 이메일 파라미터가 단일 문자열 값인지 검증하고 배열 또는 다른 비문자열 유형으로 제공된 모든 요청을 거부해야 합니다. 과거 사례: #436084 — 비밀번호 재설정을 통한 계정 탈취.

  • 로그인 실패 및 비밀번호 재설정 응답은 "사용자는 존재하지만 자격 증명이 잘못됨"과 "사용자가 존재하지 않음" 간에 차이가 없어야 합니다. 동일한 응답 본문과 동일한 타이밍을 사용하세요. 계정 열거 공격을 방어합니다.

사용자 프로필#

참조 위치 목적
app/controllers/profiles_controller.rb 프로필 표시.
app/controllers/user_settings/profiles_controller.rb 프로필 편집.
app/controllers/profiles/emails_controller.rb 이메일 관리.
app/controllers/profiles/avatars_controller.rb 아바타 업로드.
app/controllers/profiles/preferences_controller.rb 사용자 환경 설정.

API 인증#

API 요청은 API::APIGuard(lib/api/api_guard.rb)를 통해 인증되며, OAuth2 bearer token, 스코프 적용, DPoP 검사, 오류 처리를 담당합니다.

참조 위치 목적
lib/api/api_guard.rb API 인증 모듈.
lib/gitlab/auth/auth_finders.rb API 요청의 토큰 조회.
lib/gitlab/auth/request_authenticator.rb Rack::Attack 및 로깅 전용 요청 ID 확인. 액세스 제어에는 사용하지 마세요.
app/services/auth/dpop_authentication_service.rb DPoP proof-of-possession 검증.

가드레일:

  • 커스텀 API 인증을 구현하지 마세요. API::APIGuard를 사용하세요.

  • JWT 또는 토큰 파싱을 직접 구현하지 마세요. Authn::IamService::JwtValidationService를 사용하세요.

  • 토큰 생성 및 검증 엔드포인트의 속도 제한에는 check_rate_limit!를 사용하세요.

공유 인프라#

인증 코드는 웹, API, OAuth, SAML 진입점 전체에 걸쳐 공유됩니다. 공유 인프라의 변경은 모든 흐름을 중단시킬 수 있습니다.

참조 위치 목적
app/models/authn/, app/services/authn/, lib/authn/ 인증 모델, 서비스, 토큰 프레임워크.
lib/gitlab/auth/ 핵심 인증 인프라.
app/controllers/concerns/internal_redirect.rb 안전한 리다이렉트 검증.

가드레일:

  • 모든 호출자를 감사하지 않고 인증 메서드의 반환 유형이나 nil-vs-value 시맨틱을 변경하지 마세요.

  • 인증 코드는 모든 진입점에 걸쳐 공유됩니다. 공유 인프라를 수정할 때 모든 흐름이 여전히 작동하는지 확인하세요.

  • 토큰 값, 비밀번호 값, 또는 세션 ID를 절대 로깅하지 마세요. 여기에는 오류 메시지, 감사 이벤트, 구조화된 로그, 백트레이스가 포함됩니다.

  • 토큰 동등 비교는 일정 시간 함수 (ActiveSupport::SecurityUtils.secure_compare)를 사용해야 합니다. 토큰 검증의 타이밍 공격을 방어합니다.

  • 사용자 차단, 금지, 또는 비활성화를 수정할 때, 차단 상태가 로그인 시점이 아닌 사용 시점에 확인되는지 검증하세요. 토큰, 세션, API 액세스는 모두 차단 상태를 존중해야 합니다.

  • 새 인증 경로 또는 토큰 유형을 추가할 때, user.blocked? 확인을 존중하는지 검증하세요.

  • 원시 사용자 제공 파라미터를 redirect_to에 전달하지 마세요. InternalRedirect#sanitize_redirect 또는 safe_redirect_path를 사용하세요. 리다이렉트 헬퍼는 유효하지 않은 타깃에 대해 nil을 반환합니다. 항상 폴백을 제공하세요.

기능 플래그#

인증 기능 플래그에는 group: group::authentication을 사용하세요.

관련 항목#