openapi: 3.0.3 info: title: Baron SSO API version: "0.2.0" description: | Baron SSO Backend API 문서입니다. 이 문서는 Swagger UI/ReDoc 단일 엔드포인트에서 확인할 수 있으며, 도메인별 API 스펙은 점진적으로 확장합니다. servers: - url: / description: 동일 호스트 기준 tags: - name: System description: 공통/헬스/문서 - name: Auth description: 인증/세션/비밀번호/링크 로그인 - name: Signup description: 회원가입/검증 - name: User description: 사용자 프로필 - name: Session description: 세션 관리(계획) - name: Admin description: 관리자 기능/테넌트 - name: Dev description: RP/Consent 관리 - name: Audit description: 감사 로그 - name: Webhook description: 외부 게이트웨이 연동 paths: /health: get: tags: [System] summary: 헬스 체크 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/HealthResponse" /openapi.yaml: get: tags: [System] summary: OpenAPI YAML responses: "200": description: OK content: application/yaml: schema: type: string /docs: get: tags: [System] summary: Swagger UI responses: "200": description: HTML content: text/html: schema: type: string /redoc: get: tags: [System] summary: ReDoc responses: "200": description: HTML content: text/html: schema: type: string /api/v1/auth/password/login: post: tags: [Auth] summary: 비밀번호 로그인 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PasswordLoginRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/PasswordLoginResponse" "401": description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/auth/password/reset/initiate: post: tags: [Auth] summary: 비밀번호 재설정 시작 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PasswordResetInitiateRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/password/reset/verify: get: tags: [Auth] summary: 비밀번호 재설정 토큰 확인 페이지 responses: "200": description: HTML content: text/html: schema: type: string post: tags: [Auth] summary: 비밀번호 재설정 토큰 처리 requestBody: required: false content: application/x-www-form-urlencoded: schema: type: object properties: token: type: string responses: "302": description: Redirect /api/v1/auth/password/reset/complete: post: tags: [Auth] summary: 비밀번호 재설정 완료 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PasswordResetCompleteRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/password/policy: get: tags: [Auth] summary: 비밀번호 정책 조회 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/PasswordPolicyResponse" /api/v1/auth/enchanted-link/init: post: tags: [Auth] summary: Enchanted Link 시작 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/EnchantedLinkInitRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/EnchantedLinkInitResponse" /api/v1/auth/enchanted-link/poll: post: tags: [Auth] summary: Enchanted Link 폴링 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/EnchantedLinkPollRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/EnchantedLinkPollResponse" /api/v1/auth/magic-link/verify: post: tags: [Auth] summary: 매직 링크 검증 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/MagicLinkVerifyRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MagicLinkVerifyResponse" /api/v1/auth/sms: post: tags: [Auth] summary: SMS 전송 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SmsSendRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/verify-sms: post: tags: [Auth] summary: SMS 인증 코드 검증 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SmsVerifyRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/SmsVerifyResponse" /api/v1/auth/qr/init: post: tags: [Auth] summary: QR 로그인 세션 생성 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/QrInitResponse" /api/v1/auth/qr/poll: post: tags: [Auth] summary: QR 로그인 폴링 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/QrPollRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/QrPollResponse" /api/v1/auth/qr/approve: post: tags: [Auth] summary: QR 로그인 승인 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/QrApproveRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/signup/check-email: post: tags: [Signup] summary: 회원가입 이메일 확인 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SignupEmailCheckRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/signup/send-email-code: post: tags: [Signup] summary: 회원가입 이메일 코드 발송 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SignupEmailCodeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/signup/send-sms-code: post: tags: [Signup] summary: 회원가입 SMS 코드 발송 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SignupSmsCodeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/signup/verify-code: post: tags: [Signup] summary: 회원가입 코드 검증 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SignupVerifyCodeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/signup: post: tags: [Signup] summary: 회원가입 완료 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SignupRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/SignupResponse" /api/v1/user/me: get: tags: [User] summary: 내 프로필 조회 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/UserProfileResponse" put: tags: [User] summary: 내 프로필 수정 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UserProfileUpdateRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/UserProfileResponse" /api/v1/user/me/send-code: post: tags: [User] summary: 프로필 변경 인증코드 전송 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UserProfileSendCodeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/user/me/password: post: tags: [User] summary: 비밀번호 변경 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UserPasswordChangeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/user/me/verify-code: post: tags: [User] summary: 프로필 변경 인증코드 검증 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UserProfileVerifyCodeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/user/rp/linked: get: tags: [User] summary: 연동된 RP 목록 조회 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/LinkedRpListResponse" "401": description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/sessions: get: tags: [Session] summary: 세션 목록 description: 세션 관리 API는 계획 단계입니다. x-status: planned responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/SessionListResponse" /api/v1/sessions/{id}: get: tags: [Session] summary: 세션 상세 description: 세션 관리 API는 계획 단계입니다. x-status: planned parameters: - in: path name: id required: true schema: type: string responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/SessionDetailResponse" delete: tags: [Session] summary: 세션 로그아웃(폐기) description: 세션 관리 API는 계획 단계입니다. x-status: planned parameters: - in: path name: id required: true schema: type: string responses: "204": description: No Content /api/v1/sessions/logout-all: post: tags: [Session] summary: 모든 세션 로그아웃 description: 세션 관리 API는 계획 단계입니다. x-status: planned responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/admin/check: get: tags: [Admin] summary: 관리자 인증 확인 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" "401": description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/admin/tenants: get: tags: [Admin] summary: 테넌트 목록 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/TenantListResponse" post: tags: [Admin] summary: 테넌트 생성 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TenantCreateRequest" responses: "201": description: Created content: application/json: schema: $ref: "#/components/schemas/TenantResponse" /api/v1/admin/tenants/{id}: get: tags: [Admin] summary: 테넌트 상세 parameters: - in: path name: id required: true schema: type: string responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/TenantResponse" put: tags: [Admin] summary: 테넌트 수정 parameters: - in: path name: id required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TenantUpdateRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/TenantResponse" delete: tags: [Admin] summary: 테넌트 삭제 parameters: - in: path name: id required: true schema: type: string responses: "204": description: No Content /api/v1/dev/clients: get: tags: [Dev] summary: RP 목록 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ClientListResponse" post: tags: [Dev] summary: RP 생성 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ClientCreateRequest" responses: "201": description: Created content: application/json: schema: $ref: "#/components/schemas/ClientDetailResponse" /api/v1/dev/clients/{id}: get: tags: [Dev] summary: RP 상세 parameters: - in: path name: id required: true schema: type: string responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ClientDetailResponse" put: tags: [Dev] summary: RP 수정 parameters: - in: path name: id required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ClientUpdateRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ClientDetailResponse" delete: tags: [Dev] summary: RP 삭제 parameters: - in: path name: id required: true schema: type: string responses: "204": description: No Content /api/v1/dev/clients/{id}/status: patch: tags: [Dev] summary: RP 상태 변경 parameters: - in: path name: id required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ClientStatusPatchRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ClientDetailResponse" /api/v1/dev/consents: get: tags: [Dev] summary: Consent 목록 parameters: - in: query name: subject required: true schema: type: string - in: query name: client_id required: false schema: type: string responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ConsentListResponse" delete: tags: [Dev] summary: Consent 회수 parameters: - in: query name: subject required: true schema: type: string - in: query name: client_id required: false schema: type: string responses: "204": description: No Content /api/v1/audit: post: tags: [Audit] summary: 감사 로그 수집 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/AuditLogRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/client-log: post: tags: [Audit] summary: 클라이언트 로그 수집 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ClientLogRequest" responses: "200": description: OK components: schemas: ErrorResponse: type: object properties: error: type: string code: type: string details: type: object additionalProperties: true MessageResponse: type: object properties: message: type: string status: type: string HealthResponse: type: object properties: status: type: string checks: type: object PasswordLoginRequest: type: object required: [loginId, password] properties: loginId: type: string password: type: string PasswordLoginResponse: type: object properties: sessionJwt: type: string refreshJwt: type: string status: type: string provider: type: string subject: type: string PasswordResetInitiateRequest: type: object required: [loginId] properties: loginId: type: string PasswordResetCompleteRequest: type: object required: [newPassword] properties: newPassword: type: string PasswordPolicyResponse: type: object properties: minLength: type: integer lowercase: type: boolean uppercase: type: boolean number: type: boolean nonAlphanumeric: type: boolean minCharacterTypes: type: integer EnchantedLinkInitRequest: type: object properties: loginId: type: string uri: type: string method: type: string EnchantedLinkInitResponse: type: object properties: linkId: type: string pendingRef: type: string maskedEmail: type: string expiresIn: type: integer EnchantedLinkPollRequest: type: object properties: pendingRef: type: string EnchantedLinkPollResponse: type: object properties: status: type: string sessionJwt: type: string MagicLinkVerifyRequest: type: object properties: token: type: string verifyOnly: type: boolean MagicLinkVerifyResponse: type: object properties: token: type: string status: type: string pendingRef: type: string message: type: string SmsSendRequest: type: object properties: phoneNumber: type: string SmsVerifyRequest: type: object properties: phoneNumber: type: string code: type: string SmsVerifyResponse: type: object properties: token: type: string message: type: string QrInitResponse: type: object properties: qrCode: type: string pendingRef: type: string expiresIn: type: integer QrPollRequest: type: object properties: pendingRef: type: string QrPollResponse: type: object properties: status: type: string sessionJwt: type: string QrApproveRequest: type: object properties: pendingRef: type: string token: type: string SignupEmailCheckRequest: type: object properties: email: type: string SignupEmailCodeRequest: type: object properties: email: type: string SignupSmsCodeRequest: type: object properties: phone: type: string SignupVerifyCodeRequest: type: object properties: target: type: string code: type: string SignupRequest: type: object properties: email: type: string phone: type: string name: type: string password: type: string department: type: string affiliationType: type: string companyCode: type: string SignupResponse: type: object properties: success: type: boolean message: type: string provider: type: string subject: type: string UserProfileResponse: type: object properties: id: type: string email: type: string name: type: string phone: type: string sessionAuthenticatedAt: type: string format: date-time department: type: string affiliationType: type: string companyCode: type: string UserProfileUpdateRequest: type: object properties: name: type: string phone: type: string department: type: string affiliationType: type: string companyCode: type: string UserPasswordChangeRequest: type: object properties: currentPassword: type: string newPassword: type: string UserProfileSendCodeRequest: type: object properties: phone: type: string UserProfileVerifyCodeRequest: type: object properties: phone: type: string code: type: string LinkedRpSummary: type: object properties: id: type: string name: type: string logo: type: string lastAuthenticatedAt: type: string status: type: string scopes: type: array items: type: string LinkedRpListResponse: type: object properties: items: type: array items: $ref: "#/components/schemas/LinkedRpSummary" SessionSummary: type: object properties: id: type: string issuedAt: type: string expiresAt: type: string device: type: string ip: type: string userAgent: type: string SessionListResponse: type: object properties: items: type: array items: $ref: "#/components/schemas/SessionSummary" SessionDetailResponse: type: object properties: session: $ref: "#/components/schemas/SessionSummary" TenantResponse: type: object properties: id: type: string name: type: string slug: type: string description: type: string status: type: string createdAt: type: string updatedAt: type: string TenantListResponse: type: object properties: items: type: array items: $ref: "#/components/schemas/TenantResponse" limit: type: integer offset: type: integer total: type: integer TenantCreateRequest: type: object required: [name] properties: name: type: string slug: type: string description: type: string status: type: string TenantUpdateRequest: type: object properties: name: type: string slug: type: string description: type: string status: type: string ClientSummary: type: object properties: id: type: string name: type: string type: type: string status: type: string createdAt: type: string redirectUris: type: array items: type: string scopes: type: array items: type: string metadata: type: object additionalProperties: true ClientListResponse: type: object properties: items: type: array items: $ref: "#/components/schemas/ClientSummary" limit: type: integer offset: type: integer ClientEndpoints: type: object properties: discovery: type: string issuer: type: string authorization: type: string token: type: string userinfo: type: string ClientDetailResponse: type: object properties: client: $ref: "#/components/schemas/ClientSummary" endpoints: $ref: "#/components/schemas/ClientEndpoints" ClientCreateRequest: type: object required: [redirectUris] properties: id: type: string name: type: string type: type: string status: type: string redirectUris: type: array items: type: string scopes: type: array items: type: string grantTypes: type: array items: type: string responseTypes: type: array items: type: string tokenEndpointAuthMethod: type: string metadata: type: object additionalProperties: true ClientUpdateRequest: type: object properties: name: type: string type: type: string status: type: string redirectUris: type: array items: type: string scopes: type: array items: type: string grantTypes: type: array items: type: string responseTypes: type: array items: type: string tokenEndpointAuthMethod: type: string metadata: type: object additionalProperties: true ClientStatusPatchRequest: type: object required: [status] properties: status: type: string ConsentSummary: type: object properties: subject: type: string clientId: type: string clientName: type: string grantedScopes: type: array items: type: string authenticatedAt: type: string ConsentListResponse: type: object properties: items: type: array items: $ref: "#/components/schemas/ConsentSummary" AuditLogRequest: type: object properties: service: type: string event: type: string payload: type: object additionalProperties: true ClientLogRequest: type: object properties: level: type: string message: type: string data: type: object additionalProperties: true