Skip to content

비밀번호 관리

Potato에서 PBKDF2-SHA256 비밀번호 해싱, 관리자 CLI 및 API 재설정, 셀프 서비스 토큰 재설정 링크, SQLite 또는 PostgreSQL 자격 증명 저장을 구성합니다.

v2.4.0의 새로운 기능

Potato의 인증 시스템은 100,000회 반복의 PBKDF2-SHA256과 사용자별 솔트를 사용하며, 이는 안전한 비밀번호 저장을 위해 NIST가 권장하는 것과 동일한 방식입니다. 이 페이지에서는 비밀번호가 저장되는 방식, 재설정 방법, 서버 재시작 후에도 자격 증명을 유지하는 방법을 다룹니다.

이 내용은 in_memory와 database 방식에 적용됩니다. OAuth에서는 ID 공급자가 비밀번호를 관리하므로, 혼합 모드의 로컬 계정을 제외하면 여기에 해당하는 내용이 없습니다.

보안 구현

비밀번호는 salt$hash 형식으로 저장됩니다.

  • 사용자별로 고유한 32자 16진수 솔트
  • 64자 16진수 다이제스트. 비밀번호에 해당 솔트와 100,000회 반복을 적용해 PBKDF2-HMAC-SHA256으로 도출합니다
  • 타이밍 공격을 방지하기 위해 hmac.compare_digest를 통한 상수 시간 비교

솔트를 붙인 비밀번호에 SHA-256을 한 번 적용하는 것만으로는 대규모 무차별 대입 공격이 가능할 만큼 빠릅니다. 추측 한 번 한 번의 비용을 높이는 것은 100,000회의 반복입니다.

user_config.json 파일에 있는 기존 평문 비밀번호는 Potato가 로드할 때 고유한 솔트로 자동으로 다시 해싱됩니다. 수동 마이그레이션이 필요하지 않습니다.

기본 구성

기본적으로 Potato는 인메모리 인증을 사용합니다. require_password는 authentication 블록의 일부가 아니라 최상위 키입니다.

yaml
require_password: true
 
authentication:
  method: in_memory
 
user_config:
  users:
    - username: "annotator1"
      password: "initial-password"   # will be hashed on first load
    - username: "annotator2"
      password: "initial-password"

영구 자격 증명

가입 양식으로 만든 계정은 JSONL 파일에 기록되고 다음 부팅 시 다시 읽힙니다. in_memory에서는 다른 파일을 지정하지 않는 한 이 파일이 출력 디렉터리 옆의 user_config.json입니다.

파일 기반 영속성

yaml
authentication:
  method: in_memory
  user_config_path: /shared/path/to/user_config.jsonl

여러 서버 인스턴스가 하나의 사용자 명단을 공유하거나, 명단을 주석 옆이 아닌 다른 위치에 두고 싶을 때 경로를 지정하십시오. 새 가입과 비밀번호 변경은 발생하는 즉시 기록됩니다.

사용자 명단은 주석 출력과 함께 보관하십시오. 주석자의 디렉터리는 사용자 이름을 따라 이름이 붙습니다. 출력 디렉터리는 남아 있는데 명단이 사라지면, 다음에 그 사용자 이름을 입력하는 사람이 다른 사람의 작업을 물려받게 됩니다. 그래서 Potato는 가입을 거부하며, 이는 파일을 복원할 때까지 해당 주석자가 다시 들어올 수 없다는 뜻입니다.

v2.8.3 이전에는 user_config_path를 명시적으로 설정하지 않으면 in_memory가 아무것도 기록하지 않았기 때문에 계정이 재시작 후에 남지 않았습니다. 이전 빌드에서 연구를 진행했다면 그 계정들은 사라졌지만, 주석은 사라지지 않았습니다.

데이터베이스 백엔드

SQLite (추가 의존성 없음):

yaml
authentication:
  method: database
  database_url: "sqlite:///auth/users.db"

PostgreSQL (psycopg2-binary 필요):

yaml
authentication:
  method: database
  database_url: "postgresql://user:password@localhost:5432/potato_auth"

Potato는 첫 시작 시 users 테이블을 만들고, 동시 읽기 성능을 높이기 위해 SQLite를 WAL 모드로 실행합니다. database_url은 sqlite:/// 또는 postgresql://로 시작해야 합니다. 환경 변수 POTATO_DB_CONNECTION을 설정할 수도 있으며, 둘 다 있으면 database_url이 우선합니다.

참고: method: database와 user_config_path는 상호 배타적입니다. 하나의 영속성 전략을 선택하십시오. 둘 다 구성하면 Potato가 오류를 발생시킵니다.

비밀번호 재설정

관리자 CLI

명령줄에서 비밀번호를 재설정합니다.

bash
# Prompts for username and password
potato reset-password config.yaml
 
# Prompts for the password only
potato reset-password config.yaml --username annotator1

관리자 API

관리자 API 키로 프로그래밍 방식으로 재설정합니다.

bash
curl -X POST http://localhost:8000/admin/reset_password \
  -H "X-API-Key: $ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"username": "annotator1", "new_password": "new-secure-password"}'

키는 최상위 admin_api_key 설정, POTATO_ADMIN_API_KEY 환경 변수, 작업 디렉터리에 생성된 admin_api_key.txt 순서로 가져옵니다.

셀프 서비스 토큰 재설정

비밀번호를 잊은 주석자는 직접 재설정할 수 있습니다. /forgot-password로 이동해 사용자 이름을 입력하면 Potato가 24시간 동안 유효한 일회용 토큰을 생성합니다. 재설정 링크는 관리자가 전달할 수 있도록 화면에 표시되며, Potato는 이메일을 보내지 않습니다. 주석자가 /reset/<token>을 열어 새 비밀번호를 설정하면 토큰이 소진됩니다.

이 흐름에는 별도의 구성이 필요하지 않습니다. require_password: true가 설정되어 있으면 로그인 페이지에 "Forgot Password?" 링크가 나타납니다.

관리자가 토큰을 직접 발급할 수도 있습니다.

bash
curl -X POST http://localhost:8000/admin/create_reset_token \
  -H "X-API-Key: $ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"username": "annotator1"}'
 
# {"reset_link": "http://localhost:8000/reset/abc123...",
#  "token": "abc123...", "expires_in_hours": 24}

만료 시간을 다르게 하려면 요청 본문에 "ttl_hours": 48을 전달하십시오.

비밀번호 없는 모드

강의실 데모, 빠른 연구, 또는 외부 인증(MTurk, Prolific)을 사용하는 작업의 경우 비밀번호를 완전히 비활성화할 수 있습니다.

yaml
require_password: false
 
authentication:
  method: in_memory

주석자는 아무 사용자 이름이나 입력하여 로그인합니다. 비밀번호 입력 창이 나타나지 않습니다. 민감한 데이터나 검증된 신원이 필요한 작업에는 권장되지 않습니다.

자세한 내용은 비밀번호 없는 로그인을 참조하십시오.

전체 참조

yaml
# Top-level: require a password at login (default: true)
require_password: true
 
# Top-level: key for the admin endpoints
admin_api_key: ${POTATO_ADMIN_API_KEY}
 
authentication:
  # in_memory (default) | database | clerk | oauth
  method: in_memory
 
  # in_memory only, mutually exclusive with method: database
  user_config_path: users.jsonl
 
  # database only; sqlite:/// or postgresql://
  # database_url: "sqlite:///auth.db"
 
user_config:
  users:
    - username: "researcher"
      password: "secure-passphrase"
    - username: "annotator1"
      password: "initial-pass"
엔드포인트메서드인증설명
/forgot-passwordGET, POST없음재설정 토큰 요청
/reset/<token>GET, POST없음새 비밀번호 설정
/admin/reset_passwordPOSTAPI 키관리자 비밀번호 재설정
/admin/create_reset_tokenPOSTAPI 키재설정 토큰 생성

추가 자료

구현 세부 사항은 원본 문서를 참조하십시오.