인증
SecureCodingHub는 여러 인증 방법을 지원합니다. 브라우저 세션은 JWT bearer 토큰을 사용합니다. 공개 API는 스코프 기반 인가 및 키당 요청 한도가 있는 장기간 사용 가능한 API 키를 사용합니다.
인증 방법
조직에 가장 적합한 인증 방법을 선택하세요:
Magic Code (이메일 OTP)
이메일로 전송된 6자리 코드를 통한 비밀번호 없는 로그인입니다. 모든 사용자의 기본 방법입니다. 코드는 10분 후 만료됩니다. 관리하거나 기억할 비밀번호가 없습니다.
OIDC (OpenID Connect)
Azure AD, Okta 또는 호환 공급자를 통한 엔터프라이즈 SSO입니다. PKCE와 함께 authorization code flow입니다. 조직에 권장됩니다.
SAML 2.0
엔터프라이즈 환경을 위한 페더레이션 기반 SSO입니다. SP 시작 로그인 흐름입니다.
Magic Code 흐름
기본 비밀번호 없는 인증 흐름은 다음과 같이 작동합니다:
사용자가 이메일 주소를 입력
서버가 6자리 OTP를 이메일로 전송
사용자가 코드를 입력
서버가 코드를 검증하고 JWT를 발급
JWT가 세션 관리를 위해 브라우저에 저장됨
SSO 흐름
조직에 SSO가 구성되면 인증 흐름이 변경됩니다:
사용자가 조직의 SSO 진입점을 엽니다(링크에는 조직 식별자가 포함되어 있습니다. 오늘 자동 이메일 → 도메인 감지는 없습니다)
브라우저가 구성된 신원 공급자로 리다이렉트
사용자가 기업 자격 증명으로 인증
IdP가 SecureCodingHub 콜백에 authorization code(OIDC) 또는 SAML 어설션을 반환
서버가 응답을 검증하고, 첫 로그인 시 사용자를 JIT 프로비저닝하고, JWT를 발급
사용자가 로그인됨
JWT 토큰
모든 브라우저 대면 인증된 세션은 매직 코드 또는 SSO 단계가 성공한 후 백엔드에서 발급된 JSON Web Tokens로 관리됩니다.
| 속성 | 값 |
|---|---|
| 알고리즘 | HS256 |
| 수명 | 발급 후 30일입니다. 앱 내 새로 고침 흐름이 없습니다. 토큰이 만료되면 사용자는 매직 코드 또는 SSO를 통해 재인증합니다. |
| 클레임 | 사용자 ID, 조직 ID, 역할, 이름, 이메일, 만료. |
| 전송 | 모든 내부 API 호출에서 Authorization: Bearer … 헤더입니다. |
| 저장소 | sch-token 키 아래의 localStorage에 클라이언트 측에 저장됩니다. 오늘 HttpOnly 쿠키 옵션이 없습니다. |
API 키 Bearer (공개 API)
/api/public/v1/* 아래의 공개 REST 및 웹훅 화면은 JWT 대신 장기간 사용 가능한 API 키를 사용합니다. 키는 조직 → API 키의 관리자 콘솔에서 생성되며 표준 bearer 헤더로 모든 요청에서 전송됩니다:
Authorization: Bearer scs_live_…| 속성 | 값 |
|---|---|
| 형식 | scs_live_ + 32개의 무작위 base62 문자입니다. 총 41자입니다. |
| 저장소 | SHA-256 해시, 접두사 및 마지막 4자만 서버에 보관됩니다. 전체 토큰은 생성 시 한 번 표시되며 다시 검색할 수 없습니다. |
| 스코프 | 16개의 세분화된 스코프(예: users:read, assignments:write, sarif:ingest)입니다. 필요한 스코프가 없는 요청은 403 insufficient_scope를 반환합니다. |
| 수명 | 기본적으로 무기한입니다. 생성 시 선택적 만료 날짜를 설정할 수 있습니다. 키는 언제든지 취소할 수 있으며, 취소는 즉시 적용됩니다. |
| 마지막 사용 추적 | 각 성공적인 호출은 감사 및 회전 위생을 위해 키의 lastUsedAt 필드를 업데이트합니다. |
전체 참조는 API → 인증 및 스코프에 있습니다.
요청 한도
모든 공개 API 키는 플랫폼을 폭주하는 스크립트로부터 보호하고 한 테넌트가 다른 테넌트를 굶주리지 않도록 하는 두 개의 슬라이딩 윈도우에 의해 제한됩니다:
| 윈도우 | 한도 | 응답 헤더 |
|---|---|---|
| 분당 | 60회 요청 | Retry-After, X-RateLimit-Window: per_minute, X-RateLimit-Limit: 60 |
| 시간당 | 1,000회 요청 | Retry-After, X-RateLimit-Window: per_hour, X-RateLimit-Limit: 1000 |
어느 윈도우든 초과하는 요청은 초 단위의 Retry-After 헤더와 함께 429 rate_limited를 받습니다. 별도의 IP 기반 제한기(15분당 5회 요청)는 익명 웹 문의 양식을 다룹니다. JWT 보호 관리자 API에 대한 내부 브라우저 세션 트래픽은 오늘 요청 한도가 없습니다.
자세한 재시도 안내 및 샘플 지수 백오프 클라이언트는 API → 요청 한도에 있습니다.
감사 로깅
모든 변경 작업 — 브라우저의 관리자 사용자 또는 공개 API 키에서 발생하든 — 은 조직별 감사 로그 테이블에 기록됩니다. 읽기 전용 작업(목록, 가져오기, 대시보드 쿼리)은 감사되지 않습니다. 다운스트림 영향이 있는 변경에 중점을 둡니다.
| 필드 | 의미 |
|---|---|
action | 발생한 일의 점 표기 식별자(예: user.updated, assignment.created, apikey.revoked, sarif.ingested)입니다. |
actorEmail / actorRole | 작업자의 이메일과 역할입니다. 관리자 UI 변경에는 사람의 이메일과 org_admin이 있습니다. API 키 변경에는 apikey:<api-key-uuid>와 역할 api_key이 있습니다. |
targetType, targetId, targetLabel | 변경된 리소스입니다. 레이블은 감사 로그 UI에서 사용되는 짧은 사람이 읽을 수 있는 설명입니다. |
metadata | 정확히 무엇이 변경되었는지 설명하는 JSON 문자열화된 컨텍스트(예: API 키의 새 스코프, 과제의 변경 전후 마감일)입니다. |
ipAddress | 변경을 일으킨 요청의 소스 IP입니다. |
createdAt | UTC 타임스탬프입니다. |
전체 감사 스트림은 관리자 UI(조직 → 감사 로그)에서 또는 GET /api/public/v1/audit-log을 통해 프로그래밍 방식으로 쿼리할 수 있습니다. 두 화면 모두 작업, 작업자 및 날짜 범위별로 필터링을 지원하며, 관리자 UI는 증거 패키지를 위한 CSV 내보내기를 노출합니다.
세션 보안
- 토큰은 모든 API 요청에서 검증됩니다
- 잘못되거나 만료된 토큰은 거부됩니다
- SSO 세션은 IdP 세션 정책을 존중합니다
- 매직 코드는 단일 사용이며 시간 제한이 있습니다
SecureCodingHub가 만든 인증 설계 선택과 그 이유
SecureCodingHub의 기본 인증 경로는 비밀번호 없음입니다. 우리는 의도적으로 그 결정을 내렸습니다. 고객 교육 데이터에서 보이는 대다수의 자격 증명 침해는 여전히 비밀번호 재사용, 약한 비밀번호 선택, 그리고 정적 시크릿의 피싱으로 거슬러 올라갑니다. 기본 로그인 흐름에서 비밀번호를 제거하면 어떤 정책도 완전히 완화할 수 없는 실패 모드 클래스를 제거합니다. 전통적인 비밀번호 폴백이 필요한 조직의 경우, 현재 NIST 안내와 일치하는 최소값을 시행합니다: 복잡성 규칙 세트가 아닌 길이 하한, 알려진 침해 비밀번호 코퍼스에 대한 스크리닝, 그리고 침해 증거가 없는 경우 강제 회전 없음입니다.
이메일 기반 복구는 SSO 지원 계정에 대해서도 의도적으로 유지됩니다. 신원 공급자에 도달할 수 없거나, 계약 중인 계약직의 기업 디렉터리 항목이 제거될 때, 우리는 여전히 검증된 소유자가 계정으로 돌아가는 결정적이고 감사 가능한 경로가 필요합니다. 복구 채널은 요청 한도가 있고, 단일 사용이며, 표준 로그인 이벤트 스트림과 별도로 기록되므로 보안 팀이 정상 로그인 노이즈에 사라지지 않고 비정상 복구 활동을 감지할 수 있습니다.
공유 계정은 완전히 차단되는 대신 제품 수준에서 권장되지 않습니다. 단일 좌석이 여러 사람에게 공유되고 있음을 사용 패턴이 시사할 때 관리자 콘솔에서 경고를 표시합니다. 공유 좌석은 개별 책임을 깨고, 진행 보고를 왜곡하며, 향후 사고 조사를 복잡하게 만들기 때문입니다. 대시보드에 대한 교차 팀 액세스가 필요한 조직은 자격 증명을 재사용하는 대신 데이터 보안에 설명된 역할 할당 및 SCIM 프로비저닝 학습자 역할을 사용해야 합니다.
인증을 컴플라이언스에 매핑
SecureCodingHub는 SOC 2 Type II를 준비 중이며 아직 감사를 완료하지 않았으므로 인증을 주장하지 않습니다. 그러나 보안 팀이 해당 감사를 위해 공급업체를 평가할 때 예상할 동일한 통제 패밀리에 대해 인증 하위 시스템을 설계합니다. 논리적 액세스에 대한 SOC 2 CC6.1 기대치 — 각 사용자의 고유 식별, 민감한 작업에 대한 다중 요소 또는 동등한 단계 업, 그리고 종료 시 취소 — 는 사용자별 계정, 두 번째 요소로서의 매직 코드 또는 IdP 발급 자격 증명, 그리고 SCIM 주도 디프로비저닝을 통해 다뤄집니다.
액세스 제어 정책, 사용자 등록 및 특권 액세스를 다루는 ISO 27001 Annex A.9 통제는 문서화된 역할 정의, 요청 시 검증된 도메인으로 제한된 조직 범위 등록, 그리고 각 테넌트 내 명시적 org_admin / learner 역할 분할을 통해 다뤄집니다. PCI DSS 섹션 8의 적용을 받는 조직의 경우, 관련 통제는 카드 소지자 데이터를 절대 저장하지 않고 카드 소지자를 플랫폼에 대해 인증하지 않는다는 것입니다. SecureCodingHub는 결제 환경이 아니라 교육 환경이므로 PCI가 적용되는 표면은 의도적으로 좁습니다.
위의 어떤 것도 자신의 평가의 대체로 읽어서는 안 됩니다. 하위 처리자 목록, 데이터 흐름 다이어그램 및 현재 감사 자세를 포함한 증거 패키지는 security@securecodinghub.com에서 요청 시 사용할 수 있습니다.
SSO가 활성화될 때 변경되는 사항
SSO를 활성화하는 것은 단지 하나의 로그인 화면을 다른 것으로 교체하는 것이 아닙니다 — 출시 전에 보안 팀이 이해해야 하는 여러 런타임 동작을 변경합니다. 조직이 신원 공급자에 연결되면, 검증된 도메인과 일치하는 이메일을 가진 사용자에게 로컬 매직 코드 경로가 더 이상 제공되지 않습니다. 대신 IdP로 리다이렉트됩니다. 이것은 올바른 기본값이지만, IdP 중단 중 복구가 SecureCodingHub 지원이 아니라 완전히 IT 팀으로 이동함을 의미합니다. 대규모 사용자 베이스에 대해 SSO를 켜기 전에 내부적으로 그 에스컬레이션 경로를 문서화하는 것을 권장합니다.
잠금 동작도 이동합니다: 로컬 매직 코드 경로에서 요청 한도가 있는 실패한 시도는 SSO가 적용되면 동일한 사용자에게 더 이상 적용되지 않습니다. 모든 자격 증명 검증이 IdP에서 발생하기 때문입니다. 잠금 정책은 SecureCodingHub 기본값이 아니라 IdP 구성에 의해 관리됩니다. 사용자가 로그인 후 수행하는 변경에 의해 작성된 감사 로그 항목은 사용자의 이메일과 org_admin / learner 역할을 계속 전달합니다. 플랫폼은 현재 감사 행에 IdP 측 인증 방법(예: IdP에서 MFA가 충족되었는지)을 저장하지 않으므로, 그 세부 수준의 경우 중앙 신원 공급자의 자체 로그 스트림과 상관시킵니다.