InfoGrab Docs

이메일 일회용 비밀번호(Email OTP) 개발

요약

이메일 일회용 비밀번호(Email OTP)는 비밀번호로 로그인하는 GitLab.com 사용자를 위한 이중 인증(2FA) 방법입니다. 개발 특화되지 않은 이 기능에 대한 정보는 기능 문서를 참조하세요. 2026년 1월부터 GitLab.com은 Email OTP를 필수 최소 요건으로 도입하고 있습니다.

이메일 일회용 비밀번호(Email OTP)는 비밀번호로 로그인하는 GitLab.com 사용자를 위한 이중 인증(2FA) 방법입니다. 사용자는 로그인 중 이메일로 일회용 코드를 받고 인증을 완료하기 위해 입력해야 합니다.

개발 특화되지 않은 이 기능에 대한 정보는 기능 문서를 참조하세요.

2026년 1월부터 GitLab.com은 Email OTP를 필수 최소 요건으로 도입하고 있습니다. 이 기능의 개발자는 피처 플래그, GitLab 인스턴스 설정 및 미래 날짜 등록 필요성에 유의해야 합니다.

로깅#

GitLab 프로덕션 로그를 사용하여 Email OTP에서 발생하는 이슈를 트리아지하고 디버그할 수 있습니다.

로그인 중 Email OTP 이벤트#

Email OTP 검증 이벤트 쿼리:

json.message: "Email Verification" AND json.username:replace_username_here

이벤트 유형을 보려면 json.event 열을 추가합니다. 이 로그는 다음 경우에 나타납니다:

  • 계정이 Email OTP를 필요로 함.
  • 계정이 경고 기간에 있음(email_otp_required_after가 7일 이하)
  • 계정이 잠겨 있음(기존 VerifiesWithEmail 동작)

IP 주소로 검색하는 성공적인 로그인 흐름을 보여주는 로그 예시:

Email OTP 로그인 로그 - 실패한 코드 입력 및 코드 재전송을 포함한 사용자 로그인 표시

이벤트 이유는 VerifiesWithEmail 상수에 정의되어 있습니다.

등록 변경#

사용자 환경 설정 수정 보기:

json.meta.caller_id: "UserSettings::ProfilesController#update" AND json.params.value: "email_otp_required_as_boolean"

레코드를 펼쳐 제출되는 환경 설정 옵션을 확인합니다. 파라미터 값 1은 사용자가 Email OTP에 등록하는 것을 나타내고, 0은 등록 해제를 나타냅니다.

추가 검색#

모든 사용자 활동:

json.username: "USERNAME" OR json.meta.user: "USERNAME"

세션 이벤트:

json.controller: "SessionsController" AND json.action: (new OR create OR resend_verification_code OR successful_verification)

비밀번호 인증 가능 작업:

json.controller: (Repositories::GitHttpController OR JwtController) AND json.path: "/PROJECT_PATH"

아키텍처#

Email OTP는 이메일 검증 로직의 일부입니다. 여기에는 사용자가 새 IP 주소에서 로그인하거나 잠긴 후 로그인할 때 제공된 코드의 검증이 포함됩니다.

이것은 사용자 등록 흐름에서 발생하는 Identity Verification 기능 및 Devise의 Confirmable 기능과는 다릅니다.

코드#

컨트롤러:

모델:

헬퍼:

데이터베이스 스키마#

user_details 테이블은 다음을 저장합니다:

  • email_otp - 해시된 OTP 코드(사용 후 nil)
  • email_otp_required_after - 등록 상태를 제어하는 적용 타임스탬프
  • email_otp_last_sent_at - 마지막 코드 전달 시간
  • email_otp_last_sent_to - 코드가 전송된 주소

상태 관리#

email_otp_required_after 값은 Users::EmailOtpEnrollment#set_email_otp_required_after_based_on_restrictions에 의해 자동으로 관리됩니다. 등록 상태에는 nil(미등록), 미래 날짜(다가오거나 현재 경고 기간) 또는 과거 날짜(적용 활성화)가 포함됩니다.

Users::UpdateService를 통해 사용자를 업데이트하면 set_email_otp_required_after_based_on_restrictions를 사용하여 상태 관리를 강제하고 값을 잠재적으로 재정의합니다. 이것은 롤아웃 목적으로 수행되었으며 향후 제거될 수 있습니다.

동일한 set_email_otp_required_after_based_on_restrictions 메서드 호출은 User#email_based_otp_required?에서도 발생합니다. 이 메서드는 사용자에게 email OTP가 필요한지 확인하기 위한 SSoT이며 email OTP 요구 사항이 적용 가능한 모든 흐름에서 사용됩니다.

이 동작은 예상된 것이며 event.messageset_email_otp_required_after_based_on_restrictions 메서드 이름이 있는 로그를 생성합니다. 코드 주석에 상태 전환이 설명되어 있습니다.

보안#

Email OTP는 그룹 또는 인스턴스 2FA 요구 사항을 만족하지 않습니다. 앱 기반 TOTP와 WebAuthn만 이 정책을 이행합니다. 그러나 사용자에게 다른 2FA 방법이 구성되어 있지 않은 경우 앱 기반 TOTP 또는 WebAuthn 방법을 추가할 때까지 Email OTP가 필요합니다. 이 요구 사항은 보안을 위해 의도적입니다.

이메일 검증 흐름에 대한 무차별 대입 공격을 방지하기 위해 속도 제한이 존재합니다. 이 모듈은 두 가지 속도 제한을 구현합니다:

  1. 로그인 속도 제한 (user_sign_in): 사용자가 올바른 비밀번호를 입력하지만 이메일 검증이 필요할 때 적용됩니다. 이는 이메일 검증 페이지가 표시될 때를 관찰하여 공격자가 비밀번호를 추측하는 것을 방지합니다.
  2. 이메일 검증 코드 재전송 속도 제한 (email_verification_code_send): 사용자가 검증 코드 재전송을 요청할 때 적용되어 이메일 전송 메커니즘 남용을 방지합니다.
  3. 이메일 검증 토큰 유효성 검사 속도 제한 (email_verification): 사용자가 검증 토큰을 제출할 때 적용되어 토큰을 추측하는 무차별 대입 시도를 방지합니다.

검증 코드는 고정 기간 후에 만료됩니다. 코드가 만료되기 전에 사용자가 검증하지 않으면 새 코드를 요청할 수 있습니다.

검증 코드는 기본 이메일 주소로 전송됩니다. 사용자에게 확인된 보조 주소가 있는 경우 거기에도 새 코드를 보낼 수 있습니다. 이 경우 기본 이메일 주소에도 보안 알림이 전송됩니다.

인증 우선순위#

이중 인증은 다음 순서로 제공됩니다:

  1. WebAuthn (구성된 경우)
  2. 앱 기반 TOTP (구성된 경우)
  3. Email OTP (허용되고 필요한 경우)

확인된 보조 이메일 주소를 가진 사용자는 기본 이메일 주소에 접근할 수 없는 경우 새 코드를 재전송할 수 있습니다.

구성#

피처 플래그:

애플리케이션 설정:

테스트#

GitLab.com과 일치하도록 GDK 구성:

# Admin > Settings > General > New user account restrictions
ApplicationSetting.current.update!(
  require_admin_approval_after_user_signup: false,
  email_confirmation_setting: 'hard' )

# Admin > Settings > General > New user account restrictions
ApplicationSetting.current.update!(
  anti_abuse_settings: {
    require_email_verification_on_account_locked: true
  }
)

아래와 같은 명령을 사용하여 등록 상태를 테스트합니다:

user = User.find_by(username: 'test_user')

# Enable Email OTP
Feature.enable(:email_based_mfa, user)
# Disable Email OTP
Feature.disable(:email_based_mfa, user)

# Require Email OTP as a minimum (also enrols new users with passwords)
ApplicationSetting.current.update!(sign_in_restrictions: {require_minimum_email_based_otp_for_users_with_passwords: true })
# Or allow users to disable it
ApplicationSetting.current.update!(sign_in_restrictions: {require_minimum_email_based_otp_for_users_with_passwords: false })

# Set enrollment date via UpdateService (triggers automatic enrollment logic)
Users::UpdateService.new( user, { user: user, email_otp_required_after: date } ).execute!
# Or set directly, bypassing set_email_otp_required_after_based_on_restrictions
user.update(email_otp_required_after: date) # nil to unenroll

https://gdk.test:3443/rails/letter_opener에서 이메일을 확인합니다.

경고 기간 단계는 코드에 정의되어 있습니다 - 임계값은 VerifiesWithEmailVerifiesWithEmailHelper를 참조하세요.

QA 통합#

프로덕션 및 스테이징 엔드투엔드 테스트가 올바르게 기능하기 위해 GitLab은 요청의 User-Agent가 구성된 GITLAB_QA_USER_AGENT와 일치할 때 QA 사용자가 Email OTP를 우회할 수 있도록 합니다.

관련 코드#

테스트 파일:

추가 리소스#

사용자 문서:

기술 문서:

내부 지원:

이메일 일회용 비밀번호(Email OTP) 개발

원문 보기
요약

이메일 일회용 비밀번호(Email OTP)는 비밀번호로 로그인하는 GitLab.com 사용자를 위한 이중 인증(2FA) 방법입니다. 개발 특화되지 않은 이 기능에 대한 정보는 기능 문서를 참조하세요. 2026년 1월부터 GitLab.com은 Email OTP를 필수 최소 요건으로 도입하고 있습니다.

이메일 일회용 비밀번호(Email OTP)는 비밀번호로 로그인하는 GitLab.com 사용자를 위한 이중 인증(2FA) 방법입니다. 사용자는 로그인 중 이메일로 일회용 코드를 받고 인증을 완료하기 위해 입력해야 합니다.

개발 특화되지 않은 이 기능에 대한 정보는 기능 문서를 참조하세요.

2026년 1월부터 GitLab.com은 Email OTP를 필수 최소 요건으로 도입하고 있습니다. 이 기능의 개발자는 피처 플래그, GitLab 인스턴스 설정 및 미래 날짜 등록 필요성에 유의해야 합니다.

로깅#

GitLab 프로덕션 로그를 사용하여 Email OTP에서 발생하는 이슈를 트리아지하고 디버그할 수 있습니다.

로그인 중 Email OTP 이벤트#

Email OTP 검증 이벤트 쿼리:

json.message: "Email Verification" AND json.username:replace_username_here

이벤트 유형을 보려면 json.event 열을 추가합니다. 이 로그는 다음 경우에 나타납니다:

  • 계정이 Email OTP를 필요로 함.
  • 계정이 경고 기간에 있음(email_otp_required_after가 7일 이하)
  • 계정이 잠겨 있음(기존 VerifiesWithEmail 동작)

IP 주소로 검색하는 성공적인 로그인 흐름을 보여주는 로그 예시:

Email OTP 로그인 로그 - 실패한 코드 입력 및 코드 재전송을 포함한 사용자 로그인 표시

이벤트 이유는 VerifiesWithEmail 상수에 정의되어 있습니다.

등록 변경#

사용자 환경 설정 수정 보기:

json.meta.caller_id: "UserSettings::ProfilesController#update" AND json.params.value: "email_otp_required_as_boolean"

레코드를 펼쳐 제출되는 환경 설정 옵션을 확인합니다. 파라미터 값 1은 사용자가 Email OTP에 등록하는 것을 나타내고, 0은 등록 해제를 나타냅니다.

추가 검색#

모든 사용자 활동:

json.username: "USERNAME" OR json.meta.user: "USERNAME"

세션 이벤트:

json.controller: "SessionsController" AND json.action: (new OR create OR resend_verification_code OR successful_verification)

비밀번호 인증 가능 작업:

json.controller: (Repositories::GitHttpController OR JwtController) AND json.path: "/PROJECT_PATH"

아키텍처#

Email OTP는 이메일 검증 로직의 일부입니다. 여기에는 사용자가 새 IP 주소에서 로그인하거나 잠긴 후 로그인할 때 제공된 코드의 검증이 포함됩니다.

이것은 사용자 등록 흐름에서 발생하는 Identity Verification 기능 및 Devise의 Confirmable 기능과는 다릅니다.

코드#

컨트롤러:

모델:

헬퍼:

데이터베이스 스키마#

user_details 테이블은 다음을 저장합니다:

  • email_otp - 해시된 OTP 코드(사용 후 nil)
  • email_otp_required_after - 등록 상태를 제어하는 적용 타임스탬프
  • email_otp_last_sent_at - 마지막 코드 전달 시간
  • email_otp_last_sent_to - 코드가 전송된 주소

상태 관리#

email_otp_required_after 값은 Users::EmailOtpEnrollment#set_email_otp_required_after_based_on_restrictions에 의해 자동으로 관리됩니다. 등록 상태에는 nil(미등록), 미래 날짜(다가오거나 현재 경고 기간) 또는 과거 날짜(적용 활성화)가 포함됩니다.

Users::UpdateService를 통해 사용자를 업데이트하면 set_email_otp_required_after_based_on_restrictions를 사용하여 상태 관리를 강제하고 값을 잠재적으로 재정의합니다. 이것은 롤아웃 목적으로 수행되었으며 향후 제거될 수 있습니다.

동일한 set_email_otp_required_after_based_on_restrictions 메서드 호출은 User#email_based_otp_required?에서도 발생합니다. 이 메서드는 사용자에게 email OTP가 필요한지 확인하기 위한 SSoT이며 email OTP 요구 사항이 적용 가능한 모든 흐름에서 사용됩니다.

이 동작은 예상된 것이며 event.messageset_email_otp_required_after_based_on_restrictions 메서드 이름이 있는 로그를 생성합니다. 코드 주석에 상태 전환이 설명되어 있습니다.

보안#

Email OTP는 그룹 또는 인스턴스 2FA 요구 사항을 만족하지 않습니다. 앱 기반 TOTP와 WebAuthn만 이 정책을 이행합니다. 그러나 사용자에게 다른 2FA 방법이 구성되어 있지 않은 경우 앱 기반 TOTP 또는 WebAuthn 방법을 추가할 때까지 Email OTP가 필요합니다. 이 요구 사항은 보안을 위해 의도적입니다.

이메일 검증 흐름에 대한 무차별 대입 공격을 방지하기 위해 속도 제한이 존재합니다. 이 모듈은 두 가지 속도 제한을 구현합니다:

  1. 로그인 속도 제한 (user_sign_in): 사용자가 올바른 비밀번호를 입력하지만 이메일 검증이 필요할 때 적용됩니다. 이는 이메일 검증 페이지가 표시될 때를 관찰하여 공격자가 비밀번호를 추측하는 것을 방지합니다.
  2. 이메일 검증 코드 재전송 속도 제한 (email_verification_code_send): 사용자가 검증 코드 재전송을 요청할 때 적용되어 이메일 전송 메커니즘 남용을 방지합니다.
  3. 이메일 검증 토큰 유효성 검사 속도 제한 (email_verification): 사용자가 검증 토큰을 제출할 때 적용되어 토큰을 추측하는 무차별 대입 시도를 방지합니다.

검증 코드는 고정 기간 후에 만료됩니다. 코드가 만료되기 전에 사용자가 검증하지 않으면 새 코드를 요청할 수 있습니다.

검증 코드는 기본 이메일 주소로 전송됩니다. 사용자에게 확인된 보조 주소가 있는 경우 거기에도 새 코드를 보낼 수 있습니다. 이 경우 기본 이메일 주소에도 보안 알림이 전송됩니다.

인증 우선순위#

이중 인증은 다음 순서로 제공됩니다:

  1. WebAuthn (구성된 경우)
  2. 앱 기반 TOTP (구성된 경우)
  3. Email OTP (허용되고 필요한 경우)

확인된 보조 이메일 주소를 가진 사용자는 기본 이메일 주소에 접근할 수 없는 경우 새 코드를 재전송할 수 있습니다.

구성#

피처 플래그:

애플리케이션 설정:

테스트#

GitLab.com과 일치하도록 GDK 구성:

# Admin > Settings > General > New user account restrictions
ApplicationSetting.current.update!(
  require_admin_approval_after_user_signup: false,
  email_confirmation_setting: 'hard' )

# Admin > Settings > General > New user account restrictions
ApplicationSetting.current.update!(
  anti_abuse_settings: {
    require_email_verification_on_account_locked: true
  }
)

아래와 같은 명령을 사용하여 등록 상태를 테스트합니다:

user = User.find_by(username: 'test_user')

# Enable Email OTP
Feature.enable(:email_based_mfa, user)
# Disable Email OTP
Feature.disable(:email_based_mfa, user)

# Require Email OTP as a minimum (also enrols new users with passwords)
ApplicationSetting.current.update!(sign_in_restrictions: {require_minimum_email_based_otp_for_users_with_passwords: true })
# Or allow users to disable it
ApplicationSetting.current.update!(sign_in_restrictions: {require_minimum_email_based_otp_for_users_with_passwords: false })

# Set enrollment date via UpdateService (triggers automatic enrollment logic)
Users::UpdateService.new( user, { user: user, email_otp_required_after: date } ).execute!
# Or set directly, bypassing set_email_otp_required_after_based_on_restrictions
user.update(email_otp_required_after: date) # nil to unenroll

https://gdk.test:3443/rails/letter_opener에서 이메일을 확인합니다.

경고 기간 단계는 코드에 정의되어 있습니다 - 임계값은 VerifiesWithEmailVerifiesWithEmailHelper를 참조하세요.

QA 통합#

프로덕션 및 스테이징 엔드투엔드 테스트가 올바르게 기능하기 위해 GitLab은 요청의 User-Agent가 구성된 GITLAB_QA_USER_AGENT와 일치할 때 QA 사용자가 Email OTP를 우회할 수 있도록 합니다.

관련 코드#

테스트 파일:

추가 리소스#

사용자 문서:

기술 문서:

내부 지원: