yikart/AiToEarn · error · AppException
ChannelAuthorizationFailed
ChannelAuthorizationFailed
Error message
ResponseCode.ChannelAuthorizationFailed
What it means
exchangeMiniAppCallback is the mini-app branch of the Douyin auth exchange, but it double-checks that the provider is actually configured for AuthType.QrCode. If config.authType is anything else, the mini-app callback is not a valid flow for this channel configuration and ChannelAuthorizationFailed is thrown — a configuration/flow mismatch, not a user denial.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/douyin/douyin-auth.provider.ts:157
country: userInfo.country,
eAccountRole: userInfo.eAccountRole,
},
}
}
private async exchangeMiniAppCallback(
input: AuthCallbackInput,
callback: DouyinMiniAppCallback,
): Promise<CredentialResult> {
const sessionInfo = await this.douyinMiniAppService.code2Session(callback.token)
if (!sessionInfo?.openid) {
throw new AppException(ResponseCode.ChannelAccessTokenFailed)
}
const openId = sessionInfo.openid
const unionId = sessionInfo.unionid
if (this.config.authType !== AuthType.QrCode) {
throw new AppException(ResponseCode.ChannelAuthorizationFailed)
}
if (!callback.tickets) {
throw new AppException(ResponseCode.ChannelAuthorizationFailed)
}
const userDataTicket = callback.tickets[DOUYIN_MINIAPP_USER_DATA_SCOPE]
const videoBindTicket = callback.tickets[DOUYIN_MINIAPP_VIDEO_BIND_SCOPE]
const homepageCredential = await this.douyinMiniAppService.getUserAccessToken(userDataTicket)
const videoCredential = userDataTicket === videoBindTicket
? homepageCredential
: await this.douyinMiniAppService.getUserAccessToken(videoBindTicket)
if (homepageCredential.openId !== openId || videoCredential.openId !== openId) {
throw new AppException(ResponseCode.ChannelAuthorizationFailed)
}
if (!this.hasMiniAppScope(homepageCredential.scope, DOUYIN_MINIAPP_USER_DATA_SCOPE)) {
throw new AppException(ResponseCode.ChannelAuthorizationFailed)View on GitHub (pinned to d3aa8bea5b)
Solutions
- Set the Douyin channel config authType to AuthType.QrCode for environments serving the mini-app flow.
- Verify the client is calling the callback endpoint that matches its flow (mini-app callback vs web OAuth redirect).
- Review recent config/env changes to DOUYIN auth settings and redeploy with the correct authType.
Example fix
// before (config)
{ "authType": "web_oauth" }
// after (config)
{ "authType": "qr_code" } // AuthType.QrCode — required for mini-app callbacks Defensive patterns
Strategy: validation
Validate before calling
// before driving the mini-app flow, assert config supports it
if (douyinConfig.authType !== AuthType.QrCode) {
throw new Error(`mini-app callback requires authType=QrCode, got ${douyinConfig.authType}`)
} Type guard
function supportsMiniAppFlow(cfg: { authType: AuthType }): cfg is { authType: AuthType.QrCode } {
return cfg.authType === AuthType.QrCode
} Try / catch
try {
await douyinAuth.exchangeCode(callback)
} catch (e) {
if (e.code === 'ChannelAuthorizationFailed') {
logger.error('authType mismatch or consent failure — check channel config authType')
}
throw e
} Prevention
- Keep authType config per environment in version-controlled settings.
- Route mini-app callbacks only to providers configured for QrCode.
- Add a startup assertion that mini-app-enabled channels use AuthType.QrCode.
When it happens
Trigger: A mini-app callback reaches exchangeCode → exchangeMiniAppCallback while the Douyin channel config's authType is not QrCode (e.g. set to a web/OAuth type), so the guard `this.config.authType !== AuthType.QrCode` trips.
Common situations: Environment config pointing the channel at the wrong auth type, a mini-app client calling a backend configured for the web OAuth flow, or authType renamed/changed in a config migration.
Related errors
- ChannelAccessTokenFailed
- ChannelAuthRefreshTokenMissing
- ChannelAuthPlatformUidMissing
- ChannelAuthCsrfInvalid
- ChannelAuthCodeMissing
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/290c46182a4c4917.
Report an issue: GitHub.