본문으로 건너뛰기

사용자 데이터 구조

사용자는 아이덴티티 서비스의 핵심 엔티티입니다. Logto에서는 OpenID Connect 프로토콜을 기반으로 한 기본 인증 (Authentication) 데이터와 사용자 정의 데이터를 포함합니다.

사용자 프로필

각 사용자는 모든 사용자 정보를 포함하는 프로필을 가집니다.

이는 다음과 같은 유형의 데이터로 구성됩니다:

  • 기본 데이터: 사용자 프로필의 기본 정보입니다. 소셜 identitiescustom_data를 제외한 모든 사용자 속성을 저장합니다. 예를 들어 사용자 ID, 사용자 이름, 이메일, 전화번호, 마지막 로그인 시간 등이 있습니다.
  • 소셜 아이덴티티: Facebook, GitHub, WeChat 등 소셜 커넥터로 소셜 로그인 시 가져온 사용자 정보를 저장합니다.
  • 사용자 정의 데이터: 미리 정의된 사용자 속성에 포함되지 않은 추가 사용자 정보를 저장합니다. 예를 들어 사용자가 선호하는 색상과 언어 등이 있습니다.

다음은 Facebook으로 로그인하여 가져온 사용자 데이터 샘플입니다:

{
"id": "iHXPuSb9eMzt",
"username": null,
"primaryEmail": null,
"primaryPhone": null,
"name": "John Doe",
"avatar": "https://example.com/avatar.png",
"customData": {
"preferences": {
"language": "en",
"color": "#f236c9"
}
},
"identities": {
"facebook": {
"userId": "106077000000000",
"details": {
"id": "106077000000000",
"name": "John Doe",
"email": "[email protected]",
"avatar": "https://example.com/avatar.png"
}
}
},
"lastSignInAt": 1655799453171,
"applicationId": "admin_console"
}

Logto Console 또는 Logto Management API, 예를 들어 GET /api/users/:userId 를 사용하여 사용자 프로필을 조회할 수 있습니다.

기본 데이터

사용자의 기본 데이터에 포함된 모든 속성을 살펴보겠습니다.

id

id는 Logto에서 사용자를 식별하는 고유 자동 생성 키입니다.

username

usernameusername과 비밀번호로 로그인할 때 사용됩니다.

값은 사용자가 처음 등록할 때 입력한 사용자 이름에서 가져옵니다. null일 수 있습니다. null이 아닌 값은 128자 이하여야 하며, 영문자, 숫자, 밑줄(_)만 포함할 수 있고 숫자로 시작할 수 없습니다. 대소문자를 구분합니다.

primary_email

primary_email은 사용자의 이메일 주소로, 이메일과 비밀번호 / 인증 코드로 로그인할 때 사용됩니다.

값은 사용자가 처음 등록할 때 입력한 이메일 주소에서 가져옵니다. null일 수 있습니다. 최대 길이는 128자입니다.

primary_phone

primary_phone은 사용자의 전화번호로, 전화번호와 비밀번호 / SMS 인증 코드로 로그인할 때 사용됩니다.

값은 사용자가 처음 등록할 때 입력한 전화번호에서 가져옵니다. null일 수 있습니다. null이 아닌 값은 국가 전화 코드로 시작하는 숫자여야 하며, 플러스 기호 +는 제외합니다.

name

name은 사용자의 전체 이름입니다. 최대 길이는 128자입니다.

avatar

avatar는 사용자의 아바타 이미지 URL입니다. 최대 길이는 2048자입니다.

Google, Facebook 등 소셜 커넥터로 가입한 경우, 해당 소셜 사용자 정보에서 값을 가져올 수 있습니다.

노트:

이 속성은 OpenID Connect 표준의 picture 클레임 (Claim)에 매핑됩니다.

profile

profile은 사용자의 속성에 포함되지 않은 추가 OpenID Connect 표준 클레임 (Claim)을 저장합니다.

타입 정의는 이 파일에서 확인할 수 있습니다. 아래는 타입 정의 복사본입니다:

type UserProfile = Partial<{
familyName: string;
givenName: string;
middleName: string;
nickname: string;
preferredUsername: string;
profile: string;
website: string;
gender: string;
birthdate: string;
zoneinfo: string;
locale: string;
address: Partial<{
formatted: string;
streetAddress: string;
locality: string;
region: string;
postalCode: string;
country: string;
}>;
}>;
노트:

Partial은 모든 속성이 선택적임을 의미합니다.

다른 표준 클레임 (Claim)과의 차이점은, profile의 속성 값이 비어 있지 않을 때만 ID 토큰 또는 userinfo 엔드포인트 응답에 포함된다는 점입니다. 반면, 다른 표준 클레임 (Claim)은 값이 비어 있으면 null을 반환합니다.

application_id

application_id의 값은 사용자가 처음 로그인한 애플리케이션에서 가져옵니다. null일 수 있습니다.

last_sign_in_at

last_sign_in_at은 사용자가 마지막으로 로그인한 시점의 타임존이 포함된 타임스탬프입니다.

created_at

created_at은 사용자가 계정을 등록한 시점의 타임존이 포함된 타임스탬프입니다.

updated_at

updated_at은 사용자의 프로필 정보가 마지막으로 업데이트된 시점의 타임존이 포함된 타임스탬프입니다.

has_password

has_password는 사용자가 비밀번호를 가지고 있는지 여부를 나타내는 불리언 값입니다. Console > 사용자 관리의 상세 페이지에서 이 상태를 확인하고 새 비밀번호 설정 또는 비밀번호 재설정이 가능합니다.

password_encrypted

password_encrypted는 사용자의 암호화된 비밀번호를 저장합니다.

값은 사용자가 처음 등록할 때 입력한 비밀번호에서 가져옵니다. null일 수 있습니다. null이 아닌 경우, 암호화 전 원본 내용은 최소 6자 이상이어야 합니다.

password_encryption_method

password_encryption_method는 사용자의 비밀번호를 암호화하는 데 사용됩니다. 사용자가 사용자 이름과 비밀번호로 등록할 때 초기화됩니다. null일 수 있습니다.

Logto는 기본적으로 Argon2의 구현체인 node-argon2를 암호화 방식으로 사용합니다. 자세한 내용은 참고 자료를 확인하세요.

비밀번호가 123456인 사용자의 password_encryptedpassword_encryption_method 샘플:

{
"password_encryption_method": "Argon2i",
"password_encrypted": "$argon2i$v=19$m=4096,t=10,p=1$aZzrqpSX45DOo+9uEW6XVw$O4MdirF0mtuWWWz68eyNAt2u1FzzV3m3g00oIxmEr0U"
}

is_suspended

is_suspended는 사용자가 정지되었는지 여부를 나타내는 불리언 값입니다. 값은 Logto Management API 호출 또는 Logto Console을 통해 관리할 수 있습니다.

사용자가 정지되면, 사전에 부여된 리프레시 토큰 (Refresh token)은 즉시 폐기되며, 더 이상 Logto를 통해 인증 (Authentication)받을 수 없습니다.

mfa_verification_factors

mfa_verification_factors는 사용자의 계정에 연결된 다단계 인증 (MFA) 방법 목록입니다. 가능한 값에는 Totp (인증 앱 OTP), WebAuthn (패스키), BackupCode가 있습니다.

mfaVerificationFactors: ("Totp" | "WebAuthn" | "BackupCode")[];

소셜 아이덴티티

identities소셜 로그인 (즉, 소셜 커넥터로 로그인)에서 가져온 사용자 정보를 포함합니다. 각 사용자의 identities는 개별 JSON 객체로 저장됩니다.

사용자 정보는 소셜 아이덴티티 제공자(즉, 소셜 네트워크 플랫폼)에 따라 다르며, 일반적으로 다음을 포함합니다:

  • 아이덴티티 제공자의 target (예: "facebook" 또는 "google")
  • 해당 제공자에서의 사용자의 고유 식별자
  • 사용자의 이름
  • 사용자의 인증된 이메일
  • 사용자의 아바타

사용자 계정은 소셜 로그인으로 여러 소셜 아이덴티티 제공자와 연결될 수 있으며, 각 제공자로부터 가져온 사용자 정보는 identities 객체에 저장됩니다.

Google과 Facebook으로 모두 로그인한 사용자의 identities 샘플:

{
"facebook": {
"userId": "5110888888888888",
"details": {
"id": "5110888888888888",
"name": "John Doe",
"email": "[email protected]",
"avatar": "https://example.com/avatar.png"
}
},
"google": {
"userId": "111000000000000000000",
"details": {
"id": "111000000000000000000",
"name": "John Doe",
"email": "[email protected]",
"avatar": "https://example.com/avatar.png"
}
}
}

SSO 아이덴티티

sso_identities엔터프라이즈 SSO (즉, 엔터프라이즈 커넥터로 싱글 사인온 (SSO) 로그인](/connectors/enterprise-connectors))에서 가져온 사용자 정보를 포함합니다. 각 사용자의 ssoIdentities는 개별 JSON 객체로 저장됩니다.

SSO 아이덴티티 제공자로부터 동기화된 데이터는 엔터프라이즈 커넥터에서 요청하도록 구성된 스코프에 따라 다릅니다. 아래는 TypeScript 타입 정의 복사본입니다:

type SSOIdentity = {
issuer: string;
identityId: string;
detail: JsonObject; // See https://github.com/withtyped/withtyped/blob/master/packages/server/src/types.ts#L12
};

사용자 정의 데이터

custom_data는 미리 정의된 사용자 속성에 포함되지 않은 추가 사용자 정보를 저장합니다.

custom_data를 사용하여 다음과 같은 작업을 할 수 있습니다:

  • 사용자가 특정 작업(예: 환영 페이지를 본 적이 있는지 등)을 했는지 기록
  • 애플리케이션별로 사용자 프로필에 데이터 저장 (예: 사용자가 선호하는 언어, 애플리케이션별 테마 등)
  • 사용자와 관련된 기타 임의의 데이터 관리

Logto의 관리자 사용자의 custom_data 샘플:

{
"adminConsolePreferences": {
"language": "en",
"appearanceMode": "system",
"experienceNoticeConfirmed": true
},
"customDataFoo": {
"foo": "foo"
},
"customDataBar": {
"bar": "bar"
}
}

각 사용자의 custom_data는 개별 JSON 객체로 저장됩니다.

노트:

custom_data에 민감한 데이터를 저장하지 마세요.

사용자 로그인 후 커스텀 JWT 토큰 클레임 (Claim)을 통해 사용자 정의 데이터에 접근할 수 있으며, JWT 토큰은 base64로 인코딩(암호화 아님)되어 네트워크를 통해 자주 전송되므로 민감한 데이터가 쉽게 노출될 수 있습니다.

Management API를 통해 custom_data가 포함된 사용자 프로필을 조회하여 프론트엔드 앱이나 외부 백엔드 서비스로 전송할 수 있습니다. 따라서 custom_data에 민감한 정보를 넣으면 데이터 유출 위험이 있습니다.

그래도 custom_data에 민감한 정보를 저장해야 한다면, 먼저 암호화할 것을 권장합니다. 암호화/복호화는 백엔드 서비스 등 신뢰할 수 있는 파티에서만 수행하고, 프론트엔드 앱에서는 피하세요. 이렇게 하면 사용자의 custom_data가 실수로 유출되더라도 피해를 최소화할 수 있습니다.

사용자 정의 데이터 수집 및 업데이트 방법

업데이트 시 주의하세요. 사용자의 custom_data를 업데이트하면 기존 저장된 내용이 완전히 덮어써집니다.

예를 들어, custom_data 업데이트 API 호출 입력이 다음과 같고(기존 custom_data는 앞서 제시한 샘플 데이터라고 가정):

{
"customDataBaz": {
"baz": "baz"
}
}

업데이트 후 새로운 custom_data 값은 다음과 같습니다:

{
"customDataBaz": {
"baz": "baz"
}
}

즉, 업데이트된 필드 값은 이전 값과 무관합니다.

속성 참조

다음 DB 사용자 테이블 컬럼(password_encryptedpassword_encryption_method 제외)은 사용자 프로필에서 확인할 수 있으며, Management API로 조회할 수 있습니다.

이름타입설명고유필수
idstring고유 식별자
usernamestring로그인용 사용자 이름
primary_emailstring기본 이메일
primary_phonestring기본 전화번호
namestring전체 이름
avatarstring사용자 아바타 이미지 URL
profileobject사용자 프로필
identitiesobject소셜 로그인에서 가져온 사용자 정보
custom_dataobject커스터마이즈 가능한 속성의 추가 정보
application_idstring사용자가 처음 등록한 애플리케이션 ID
last_sign_in_atdate time사용자가 마지막으로 로그인한 시점의 타임스탬프
password_encryptedstring암호화된 비밀번호
password_encryption_methodstring비밀번호 암호화 방식
is_suspendedbool사용자 정지 여부 표시
mfa_verificationsobject[]MFA 인증 (Authentication) 요소
  • 고유: 데이터베이스 테이블 속성 값의 고유성을 보장합니다.
  • 필수: 데이터베이스 테이블 속성 값이 null이 될 수 없음을 보장합니다.

이동 중인 사용자 데이터를 위한 보안 허브