2026-05-21 06:45:35 +00:00
|
|
|
|
syntax = "v1"
|
|
|
|
|
|
|
|
|
|
|
|
type (
|
|
|
|
|
|
RegisterReq {
|
2026-05-21 09:15:25 +00:00
|
|
|
|
TenantSlug string `json:"tenant_slug" validate:"required"` // 租戶 slug(小寫英數)
|
|
|
|
|
|
InviteCode string `json:"invite_code" validate:"required"` // 邀請碼
|
|
|
|
|
|
Email string `json:"email" validate:"required,email"` // 電子郵件
|
|
|
|
|
|
Password string `json:"password" validate:"required,min=8,max=128"` // 密碼(8-128 字元)
|
|
|
|
|
|
DisplayName string `json:"display_name,optional"` // 顯示名稱(可選)
|
|
|
|
|
|
Language string `json:"language,optional"` // 語系代碼,如 zh-TW / en(可選)
|
|
|
|
|
|
AcceptTermsVersion string `json:"accept_terms_version" validate:"required"` // 使用者接受的服務條款版本
|
|
|
|
|
|
MarketingOptIn bool `json:"marketing_opt_in,optional"` // 是否同意接收行銷訊息
|
2026-05-21 06:45:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RegisterData {
|
|
|
|
|
|
ChallengeID string `json:"challenge_id"`
|
|
|
|
|
|
ExpiresIn int `json:"expires_in"`
|
|
|
|
|
|
UID string `json:"uid"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RegisterConfirmReq {
|
2026-05-21 09:15:25 +00:00
|
|
|
|
TenantSlug string `json:"tenant_slug" validate:"required"` // 租戶 slug
|
|
|
|
|
|
ChallengeID string `json:"challenge_id" validate:"required"` // 註冊流程的 OTP challenge ID(由 /register 回傳)
|
|
|
|
|
|
Code string `json:"code" validate:"required,len=6"` // 6 位數 OTP 驗證碼
|
2026-05-21 06:45:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RegisterResendReq {
|
2026-05-21 09:15:25 +00:00
|
|
|
|
TenantSlug string `json:"tenant_slug" validate:"required"` // 租戶 slug
|
|
|
|
|
|
ChallengeID string `json:"challenge_id" validate:"required"` // 註冊流程的 OTP challenge ID
|
2026-05-21 06:45:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-26 16:55:37 +00:00
|
|
|
|
RegisterResumeReq {
|
|
|
|
|
|
TenantSlug string `json:"tenant_slug" validate:"required"` // 租戶 slug
|
|
|
|
|
|
Email string `json:"email" validate:"required,email"` // 註冊 Email
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PasswordForgotReq {
|
|
|
|
|
|
TenantSlug string `json:"tenant_slug" validate:"required"` // 租戶 slug
|
|
|
|
|
|
Email string `json:"email" validate:"required,email"` // 登入 Email
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PasswordForgotData {
|
|
|
|
|
|
ChallengeID string `json:"challenge_id"`
|
|
|
|
|
|
ExpiresIn int `json:"expires_in"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PasswordResetReq {
|
|
|
|
|
|
TenantSlug string `json:"tenant_slug" validate:"required"` // 租戶 slug
|
|
|
|
|
|
ChallengeID string `json:"challenge_id" validate:"required"` // 忘記密碼 OTP challenge ID
|
|
|
|
|
|
Code string `json:"code" validate:"required,len=6"` // 6 位數 OTP
|
|
|
|
|
|
NewPassword string `json:"new_password" validate:"required,min=8,max=128"` // 新密碼
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PasswordResetData {
|
|
|
|
|
|
OK bool `json:"ok"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-21 06:45:35 +00:00
|
|
|
|
AuthTokenData {
|
|
|
|
|
|
AccessToken string `json:"access_token"`
|
|
|
|
|
|
RefreshToken string `json:"refresh_token"`
|
|
|
|
|
|
ExpiresIn int64 `json:"expires_in"`
|
|
|
|
|
|
UID string `json:"uid"`
|
|
|
|
|
|
TokenType string `json:"token_type"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RegisterSocialStartReq {
|
2026-05-21 09:15:25 +00:00
|
|
|
|
TenantSlug string `json:"tenant_slug" validate:"required"` // 租戶 slug
|
|
|
|
|
|
InviteCode string `json:"invite_code" validate:"required"` // 邀請碼
|
|
|
|
|
|
Provider string `json:"provider,options=google" validate:"required,oneof=google"` // 第三方登入提供者;可選值: google
|
|
|
|
|
|
AcceptTermsVersion string `json:"accept_terms_version" validate:"required"` // 使用者接受的服務條款版本
|
|
|
|
|
|
Language string `json:"language,optional"` // 語系代碼,如 zh-TW / en(可選)
|
|
|
|
|
|
RedirectURI string `json:"redirect_uri" validate:"required,url"` // OAuth 完成後要 redirect 回的 URI
|
|
|
|
|
|
MarketingOptIn bool `json:"marketing_opt_in,optional"` // 是否同意接收行銷訊息
|
2026-05-21 06:45:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RegisterSocialStartData {
|
|
|
|
|
|
OauthURL string `json:"oauth_url"`
|
|
|
|
|
|
SessionID string `json:"session_id"`
|
|
|
|
|
|
ExpiresIn int `json:"expires_in"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RegisterSocialCallbackReq {
|
2026-05-21 09:15:25 +00:00
|
|
|
|
Code string `form:"code" validate:"required"` // IdP 回傳的 OAuth authorization code
|
|
|
|
|
|
State string `form:"state" validate:"required"` // IdP 回傳的 OAuth state(對應 session)
|
2026-05-21 06:45:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LoginReq {
|
2026-05-21 09:15:25 +00:00
|
|
|
|
TenantSlug string `json:"tenant_slug" validate:"required"` // 租戶 slug
|
|
|
|
|
|
Email string `json:"email" validate:"required,email"` // 電子郵件
|
|
|
|
|
|
Password string `json:"password" validate:"required,min=8,max=128"` // 密碼(8-128 字元)
|
2026-05-21 06:45:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-26 16:55:37 +00:00
|
|
|
|
LoginData {
|
|
|
|
|
|
AccessToken string `json:"access_token,optional"`
|
|
|
|
|
|
RefreshToken string `json:"refresh_token,optional"`
|
|
|
|
|
|
ExpiresIn int64 `json:"expires_in,optional"`
|
|
|
|
|
|
UID string `json:"uid,optional"`
|
|
|
|
|
|
TokenType string `json:"token_type,optional"`
|
|
|
|
|
|
MFARequired bool `json:"mfa_required,optional"`
|
|
|
|
|
|
MFAChallengeID string `json:"mfa_challenge_id,optional"`
|
|
|
|
|
|
MFAExpiresIn int `json:"mfa_expires_in,optional"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LoginMFAConfirmReq {
|
|
|
|
|
|
TenantSlug string `json:"tenant_slug" validate:"required"` // 租戶 slug
|
|
|
|
|
|
ChallengeID string `json:"challenge_id" validate:"required"` // 密碼登入後回傳的 MFA challenge ID
|
|
|
|
|
|
Code string `json:"code" validate:"required,len=6"` // TOTP 或備援碼(6 位數)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-21 06:45:35 +00:00
|
|
|
|
TokenRefreshReq {
|
2026-05-21 09:15:25 +00:00
|
|
|
|
RefreshToken string `json:"refresh_token" validate:"required"` // 先前核發的 refresh token
|
2026-05-21 06:45:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TokenExchangeReq {
|
2026-05-21 09:15:25 +00:00
|
|
|
|
TenantSlug string `json:"tenant_slug" validate:"required"` // 租戶 slug
|
|
|
|
|
|
IDToken string `json:"id_token" validate:"required"` // ZITADEL 發行的 id_token
|
2026-05-21 06:45:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LoginSocialStartReq {
|
2026-05-21 09:15:25 +00:00
|
|
|
|
TenantSlug string `json:"tenant_slug" validate:"required"` // 租戶 slug
|
|
|
|
|
|
Provider string `json:"provider,options=google" validate:"required,oneof=google"` // 第三方登入提供者;可選值: google
|
|
|
|
|
|
RedirectURI string `json:"redirect_uri" validate:"required,url"` // OAuth 完成後要 redirect 回的 URI
|
2026-05-21 06:45:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LoginSocialStartData {
|
|
|
|
|
|
OauthURL string `json:"oauth_url"`
|
|
|
|
|
|
SessionID string `json:"session_id"`
|
|
|
|
|
|
ExpiresIn int `json:"expires_in"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LoginSocialCallbackReq {
|
2026-05-21 09:15:25 +00:00
|
|
|
|
Code string `form:"code" validate:"required"` // IdP 回傳的 OAuth authorization code
|
|
|
|
|
|
State string `form:"state" validate:"required"` // IdP 回傳的 OAuth state(對應 session)
|
2026-05-21 06:45:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LogoutData {
|
|
|
|
|
|
OK bool `json:"ok"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 文件用:成功回應 envelope(HTTP 200, code=102000, message=SUCCESS)
|
|
|
|
|
|
RegisterOKStatus {
|
|
|
|
|
|
Code int64 `json:"code"`
|
|
|
|
|
|
Message string `json:"message"`
|
|
|
|
|
|
Data RegisterData `json:"data"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AuthTokenOKStatus {
|
|
|
|
|
|
Code int64 `json:"code"`
|
|
|
|
|
|
Message string `json:"message"`
|
|
|
|
|
|
Data AuthTokenData `json:"data"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-26 16:55:37 +00:00
|
|
|
|
LoginOKStatus {
|
|
|
|
|
|
Code int64 `json:"code"`
|
|
|
|
|
|
Message string `json:"message"`
|
|
|
|
|
|
Data LoginData `json:"data"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-21 06:45:35 +00:00
|
|
|
|
RegisterSocialStartOKStatus {
|
|
|
|
|
|
Code int64 `json:"code"`
|
|
|
|
|
|
Message string `json:"message"`
|
|
|
|
|
|
Data RegisterSocialStartData `json:"data"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LoginSocialStartOKStatus {
|
|
|
|
|
|
Code int64 `json:"code"`
|
|
|
|
|
|
Message string `json:"message"`
|
|
|
|
|
|
Data LoginSocialStartData `json:"data"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LogoutOKStatus {
|
|
|
|
|
|
Code int64 `json:"code"`
|
|
|
|
|
|
Message string `json:"message"`
|
|
|
|
|
|
Data LogoutData `json:"data"`
|
|
|
|
|
|
}
|
2026-05-26 16:55:37 +00:00
|
|
|
|
|
|
|
|
|
|
PasswordForgotOKStatus {
|
|
|
|
|
|
Code int64 `json:"code"`
|
|
|
|
|
|
Message string `json:"message"`
|
|
|
|
|
|
Data PasswordForgotData `json:"data"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PasswordResetOKStatus {
|
|
|
|
|
|
Code int64 `json:"code"`
|
|
|
|
|
|
Message string `json:"message"`
|
|
|
|
|
|
Data PasswordResetData `json:"data"`
|
|
|
|
|
|
}
|
2026-05-21 06:45:35 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@server(
|
2026-05-21 09:15:25 +00:00
|
|
|
|
group: auth
|
|
|
|
|
|
prefix: /api/v1/auth
|
2026-05-21 09:30:50 +00:00
|
|
|
|
tags: "Auth - 認證(公開)"
|
|
|
|
|
|
summary: "註冊 / 登入 / Token 交換(不需 Bearer)"
|
2026-05-21 06:45:35 +00:00
|
|
|
|
)
|
|
|
|
|
|
service gateway {
|
|
|
|
|
|
@doc "Email 註冊(建立 ZITADEL + member,寄 registration OTP)"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (RegisterOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
) // 參數錯誤 / 驗證失敗
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) tenant 不允許註冊
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant 不存在(Member scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-409 (
|
|
|
|
|
|
28303000: (APIErrorStatus) email 已註冊(Auth scope)
|
|
|
|
|
|
) // 資源衝突
|
|
|
|
|
|
@respdoc-423 (
|
|
|
|
|
|
28313000: (APIErrorStatus) invite 消耗鎖定中
|
|
|
|
|
|
) // 資源鎖定
|
|
|
|
|
|
@respdoc-429 (
|
|
|
|
|
|
28604000: (APIErrorStatus) OTP 重送冷卻
|
|
|
|
|
|
28310000: (APIErrorStatus) invite 次數用盡
|
|
|
|
|
|
) // 請求過於頻繁
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28201000: (APIErrorStatus) 資料庫錯誤
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
@respdoc-502 (
|
|
|
|
|
|
28802000: (APIErrorStatus) ZITADEL 第三方錯誤
|
|
|
|
|
|
) // 第三方服務錯誤
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler register
|
|
|
|
|
|
post /register (RegisterReq) returns (RegisterData)
|
|
|
|
|
|
|
|
|
|
|
|
@doc "確認 registration OTP 並核發 JWT"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (AuthTokenOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
) // 參數錯誤 / 驗證失敗
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) challenge tenant 或 purpose 不符(Auth scope)
|
|
|
|
|
|
29505000: (APIErrorStatus) OTP 無效(Member scope)
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant / OTP challenge 不存在(Member scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-409 (
|
|
|
|
|
|
28309000: (APIErrorStatus) registration challenge 狀態無效(Auth scope)
|
|
|
|
|
|
29309000: (APIErrorStatus) OTP challenge 鎖定(Member scope)
|
|
|
|
|
|
) // 資源狀態衝突
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28201000: (APIErrorStatus) 資料庫錯誤
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler registerConfirm
|
|
|
|
|
|
post /register/confirm (RegisterConfirmReq) returns (AuthTokenData)
|
|
|
|
|
|
|
|
|
|
|
|
@doc "重寄 registration OTP"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (RegisterOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) challenge tenant 或 purpose 不符
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant / OTP challenge 不存在(Member scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-409 (
|
|
|
|
|
|
28309000: (APIErrorStatus) registration challenge 不完整(Auth scope)
|
|
|
|
|
|
) // 資源狀態衝突
|
|
|
|
|
|
@respdoc-429 (
|
|
|
|
|
|
28604000: (APIErrorStatus) OTP 重送冷卻
|
|
|
|
|
|
) // 請求過於頻繁
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28201000: (APIErrorStatus) 資料庫錯誤
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler registerResend
|
|
|
|
|
|
post /register/resend (RegisterResendReq) returns (RegisterData)
|
|
|
|
|
|
|
2026-05-26 16:55:37 +00:00
|
|
|
|
@doc "恢復未完成註冊(依 Email 重寄 registration OTP)"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (RegisterOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant / 待驗證 member 不存在(Member scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-409 (
|
|
|
|
|
|
28309000: (APIErrorStatus) 帳號已完成驗證(Auth scope)
|
|
|
|
|
|
) // 資源狀態衝突
|
|
|
|
|
|
@respdoc-429 (
|
|
|
|
|
|
28604000: (APIErrorStatus) OTP 重送冷卻
|
|
|
|
|
|
) // 請求過於頻繁
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28201000: (APIErrorStatus) 資料庫錯誤
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler registerResume
|
|
|
|
|
|
post /register/resume (RegisterResumeReq) returns (RegisterData)
|
|
|
|
|
|
|
|
|
|
|
|
@doc "忘記密碼:寄送重設 OTP(僅 platform_native 平台帳號)"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (PasswordForgotOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) 外部身份帳號不可重設密碼(Auth scope)
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant / member 不存在(Member scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-429 (
|
|
|
|
|
|
29604000: (APIErrorStatus) OTP 重送冷卻
|
|
|
|
|
|
) // 請求過於頻繁
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler passwordForgot
|
|
|
|
|
|
post /password/forgot (PasswordForgotReq) returns (PasswordForgotData)
|
|
|
|
|
|
|
|
|
|
|
|
@doc "忘記密碼:驗證 OTP 並重設密碼(僅 platform_native)"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (PasswordResetOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) OTP 無效(Auth scope)
|
|
|
|
|
|
29505000: (APIErrorStatus) OTP 無效(Member scope)
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant / OTP challenge 不存在(Member scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-502 (
|
|
|
|
|
|
28802000: (APIErrorStatus) ZITADEL 第三方錯誤
|
|
|
|
|
|
) // 第三方服務錯誤
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler passwordReset
|
|
|
|
|
|
post /password/reset (PasswordResetReq) returns (PasswordResetData)
|
|
|
|
|
|
|
2026-05-21 06:45:35 +00:00
|
|
|
|
@doc "Social 註冊:建立 session 並回傳 OAuth URL"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (RegisterSocialStartOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
28101000: (APIErrorStatus) invite 已過期(Auth scope)
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) tenant 不允許註冊
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant 不存在(Member scope)
|
|
|
|
|
|
28301000: (APIErrorStatus) invite 不存在(Auth scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-429 (
|
|
|
|
|
|
28310000: (APIErrorStatus) invite 次數用盡
|
|
|
|
|
|
) // 配額不足
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28201000: (APIErrorStatus) 資料庫錯誤
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
@respdoc-502 (
|
|
|
|
|
|
28802000: (APIErrorStatus) ZITADEL 第三方錯誤
|
|
|
|
|
|
) // 第三方服務錯誤
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler registerSocialStart
|
|
|
|
|
|
post /register/social/start (RegisterSocialStartReq) returns (RegisterSocialStartData)
|
|
|
|
|
|
|
|
|
|
|
|
@doc "Social 註冊 OAuth callback"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (AuthTokenOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
28101000: (APIErrorStatus) oauth state 無效(Auth scope)
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) social email 未驗證
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
28301000: (APIErrorStatus) registration session 不存在(Auth scope)
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant 不存在(Member scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-409 (
|
|
|
|
|
|
28303000: (APIErrorStatus) 帳號已存在(引導 login)
|
|
|
|
|
|
) // 資源衝突
|
|
|
|
|
|
@respdoc-423 (
|
|
|
|
|
|
28313000: (APIErrorStatus) invite 消耗鎖定中
|
|
|
|
|
|
) // 資源鎖定
|
|
|
|
|
|
@respdoc-429 (
|
|
|
|
|
|
28310000: (APIErrorStatus) invite 次數用盡
|
|
|
|
|
|
) // 配額不足
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28201000: (APIErrorStatus) 資料庫錯誤
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
@respdoc-502 (
|
|
|
|
|
|
28802000: (APIErrorStatus) ZITADEL 第三方錯誤
|
|
|
|
|
|
) // 第三方服務錯誤
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler registerSocialCallback
|
|
|
|
|
|
get /register/social/callback (RegisterSocialCallbackReq) returns (AuthTokenData)
|
|
|
|
|
|
|
2026-05-26 16:55:37 +00:00
|
|
|
|
@doc "Email + 密碼登入(ZITADEL ROPG → CloudEP JWT;若已啟用 TOTP 則回傳 MFA challenge)"
|
2026-05-21 06:45:35 +00:00
|
|
|
|
/*
|
2026-05-26 16:55:37 +00:00
|
|
|
|
@respdoc-200 (LoginOKStatus) // 成功(code=102000);mfa_required=true 時僅含 challenge
|
2026-05-21 06:45:35 +00:00
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-401 (
|
|
|
|
|
|
28501000: (APIErrorStatus) 帳密錯誤
|
|
|
|
|
|
) // 未授權
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) 帳號未驗證 / 停權 / 不允許登入
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant 不存在(Member scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28201000: (APIErrorStatus) 資料庫錯誤
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
@respdoc-502 (
|
|
|
|
|
|
28802000: (APIErrorStatus) ZITADEL 第三方錯誤
|
|
|
|
|
|
) // 第三方服務錯誤
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler login
|
2026-05-26 16:55:37 +00:00
|
|
|
|
post /login (LoginReq) returns (LoginData)
|
|
|
|
|
|
|
|
|
|
|
|
@doc "確認登入 MFA(TOTP / 備援碼)並核發 JWT"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (AuthTokenOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) TOTP 無效 / challenge tenant 不符(Auth scope)
|
|
|
|
|
|
29505000: (APIErrorStatus) OTP 無效(Member scope)
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant 不存在(Member scope)
|
|
|
|
|
|
28301000: (APIErrorStatus) login mfa challenge 不存在(Auth scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28201000: (APIErrorStatus) 資料庫錯誤
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler loginMfaConfirm
|
|
|
|
|
|
post /login/mfa (LoginMFAConfirmReq) returns (AuthTokenData)
|
2026-05-21 06:45:35 +00:00
|
|
|
|
|
|
|
|
|
|
@doc "以 refresh_token 換發新的 access/refresh token"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (AuthTokenOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少 refresh_token
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-401 (
|
|
|
|
|
|
28501000: (APIErrorStatus) refresh token 無效或已撤銷
|
|
|
|
|
|
) // 未授權
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler tokenRefresh
|
|
|
|
|
|
post /token/refresh (TokenRefreshReq) returns (AuthTokenData)
|
|
|
|
|
|
|
|
|
|
|
|
@doc "ZITADEL id_token 換 CloudEP JWT(企業 SSO)"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (AuthTokenOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-401 (
|
|
|
|
|
|
28501000: (APIErrorStatus) id_token 無效
|
|
|
|
|
|
) // 未授權
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) 帳號未驗證 / 停權 / 不允許登入
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant / member 不存在(Member scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28201000: (APIErrorStatus) 資料庫錯誤
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
@respdoc-502 (
|
|
|
|
|
|
28802000: (APIErrorStatus) ZITADEL 第三方錯誤
|
|
|
|
|
|
) // 第三方服務錯誤
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler tokenExchange
|
|
|
|
|
|
post /token/exchange (TokenExchangeReq) returns (AuthTokenData)
|
|
|
|
|
|
|
|
|
|
|
|
@doc "Social 登入:建立 login session 並回傳 OAuth URL(不含 invite)"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (LoginSocialStartOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) tenant 不允許登入
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant 不存在(Member scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28201000: (APIErrorStatus) 資料庫錯誤
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
@respdoc-502 (
|
|
|
|
|
|
28802000: (APIErrorStatus) ZITADEL 第三方錯誤
|
|
|
|
|
|
) // 第三方服務錯誤
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler loginSocialStart
|
|
|
|
|
|
post /login/social/start (LoginSocialStartReq) returns (LoginSocialStartData)
|
|
|
|
|
|
|
|
|
|
|
|
@doc "Social 登入 OAuth callback"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (AuthTokenOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-400 (
|
|
|
|
|
|
10101000: (APIErrorStatus) 參數格式錯誤
|
|
|
|
|
|
10104000: (APIErrorStatus) 缺少必填欄位
|
|
|
|
|
|
28101000: (APIErrorStatus) oauth state 無效(Auth scope)
|
|
|
|
|
|
) // 參數錯誤
|
|
|
|
|
|
@respdoc-403 (
|
|
|
|
|
|
28505000: (APIErrorStatus) social email 未驗證 / 帳號狀態不允許登入
|
|
|
|
|
|
) // 禁止存取
|
|
|
|
|
|
@respdoc-404 (
|
|
|
|
|
|
28301000: (APIErrorStatus) login session 不存在(Auth scope)
|
|
|
|
|
|
29301000: (APIErrorStatus) tenant / member 不存在(Member scope)
|
|
|
|
|
|
) // 資源不存在
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28201000: (APIErrorStatus) 資料庫錯誤
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
@respdoc-502 (
|
|
|
|
|
|
28802000: (APIErrorStatus) ZITADEL 第三方錯誤
|
|
|
|
|
|
) // 第三方服務錯誤
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler loginSocialCallback
|
|
|
|
|
|
get /login/social/callback (LoginSocialCallbackReq) returns (AuthTokenData)
|
2026-05-21 09:30:50 +00:00
|
|
|
|
}
|
2026-05-21 06:45:35 +00:00
|
|
|
|
|
2026-05-21 09:30:50 +00:00
|
|
|
|
@server(
|
|
|
|
|
|
group: auth
|
|
|
|
|
|
prefix: /api/v1/auth
|
|
|
|
|
|
middleware: AuthJWT
|
|
|
|
|
|
tags: "Auth - 認證(需 Bearer)"
|
|
|
|
|
|
summary: "登出(需 access token)"
|
|
|
|
|
|
)
|
|
|
|
|
|
service gateway {
|
2026-05-21 06:45:35 +00:00
|
|
|
|
@doc "登出(撤銷 access JWT 及配對 refresh JWT)"
|
|
|
|
|
|
/*
|
|
|
|
|
|
@respdoc-200 (LogoutOKStatus) // 成功(code=102000)
|
|
|
|
|
|
@respdoc-401 (
|
|
|
|
|
|
28501000: (APIErrorStatus) 缺少或無效 access token
|
|
|
|
|
|
) // 未授權
|
|
|
|
|
|
@respdoc-500 (
|
|
|
|
|
|
28601000: (APIErrorStatus) 系統內部錯誤
|
|
|
|
|
|
) // 內部錯誤
|
|
|
|
|
|
@respdoc-501 (
|
|
|
|
|
|
28605000: (APIErrorStatus) 功能未配置
|
|
|
|
|
|
) // 未實作
|
|
|
|
|
|
*/
|
|
|
|
|
|
@handler logout
|
|
|
|
|
|
post /logout returns (LogoutData)
|
|
|
|
|
|
}
|