syntax = "v1" type ( RegisterReq { TenantSlug string `json:"tenant_slug" validate:"required"` InviteCode string `json:"invite_code" validate:"required"` Email string `json:"email" validate:"required,email"` Password string `json:"password" validate:"required,min=8,max=128"` DisplayName string `json:"display_name,optional"` Language string `json:"language,optional"` AcceptTermsVersion string `json:"accept_terms_version" validate:"required"` MarketingOptIn bool `json:"marketing_opt_in,optional"` } RegisterData { ChallengeID string `json:"challenge_id"` ExpiresIn int `json:"expires_in"` UID string `json:"uid"` } RegisterConfirmReq { TenantSlug string `json:"tenant_slug" validate:"required"` ChallengeID string `json:"challenge_id" validate:"required"` Code string `json:"code" validate:"required,len=6"` } RegisterResendReq { TenantSlug string `json:"tenant_slug" validate:"required"` ChallengeID string `json:"challenge_id" validate:"required"` } 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 { TenantSlug string `json:"tenant_slug" validate:"required"` InviteCode string `json:"invite_code" validate:"required"` Provider string `json:"provider" validate:"required,oneof=google"` AcceptTermsVersion string `json:"accept_terms_version" validate:"required"` Language string `json:"language,optional"` RedirectURI string `json:"redirect_uri" validate:"required,url"` MarketingOptIn bool `json:"marketing_opt_in,optional"` } RegisterSocialStartData { OauthURL string `json:"oauth_url"` SessionID string `json:"session_id"` ExpiresIn int `json:"expires_in"` } RegisterSocialCallbackReq { Code string `form:"code" validate:"required"` State string `form:"state" validate:"required"` } LoginReq { TenantSlug string `json:"tenant_slug" validate:"required"` Email string `json:"email" validate:"required,email"` Password string `json:"password" validate:"required,min=8,max=128"` } TokenRefreshReq { RefreshToken string `json:"refresh_token" validate:"required"` } TokenExchangeReq { TenantSlug string `json:"tenant_slug" validate:"required"` IDToken string `json:"id_token" validate:"required"` } LoginSocialStartReq { TenantSlug string `json:"tenant_slug" validate:"required"` Provider string `json:"provider" validate:"required,oneof=google"` RedirectURI string `json:"redirect_uri" validate:"required,url"` } LoginSocialStartData { OauthURL string `json:"oauth_url"` SessionID string `json:"session_id"` ExpiresIn int `json:"expires_in"` } LoginSocialCallbackReq { Code string `form:"code" validate:"required"` State string `form:"state" validate:"required"` } 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"` } 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"` } ) @server( group: auth prefix: /api/v1/auth ) 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) @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) @doc "Email + 密碼登入(ZITADEL ROPG → CloudEP JWT)" /* @respdoc-200 (AuthTokenOKStatus) // 成功(code=102000) @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 post /login (LoginReq) returns (AuthTokenData) @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) @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) }