langgenius/dify · error · BadRequest

redirect_uri is invalid

Error message

redirect_uri is invalid

What it means

Flask BadRequest (HTTP 400) raised at oauth_server.py:163 in OAuthServerAppApi.post (POST /console/api/oauth/provider) when the payload.redirect_uri is not present in oauth_provider_app.redirect_uris. This is the standard OAuth 2.0 redirect_uri allow-list check performed before returning app metadata (icon/label/scope) to the client.

Source

Thrown at api/controllers/console/auth/oauth_server.py:163

        return view(self, oauth_provider_app, account, *args, **kwargs)

    return decorated


@console_ns.route("/oauth/provider")
class OAuthServerAppApi(Resource):
    @setup_required
    @console_ns.expect(console_ns.models[OAuthProviderRequest.__name__])
    @console_ns.response(200, "Success", console_ns.models[OAuthProviderAppResponse.__name__])
    @oauth_server_client_id_required
    @model_validate(OAuthProviderRequest)
    def post(self, payload: OAuthProviderRequest, oauth_provider_app: OAuthProviderApp):
        redirect_uri = payload.redirect_uri

        # check if redirect_uri is valid
        if redirect_uri not in oauth_provider_app.redirect_uris:
            raise BadRequest("redirect_uri is invalid")

        return jsonable_encoder(
            {
                "app_icon": oauth_provider_app.app_icon,
                "app_label": oauth_provider_app.app_label,
                "scope": oauth_provider_app.scope,
            }
        )


@console_ns.route("/oauth/provider/authorize")
class OAuthServerUserAuthorizeApi(Resource):
    @setup_required
    @login_required
    @account_initialization_required
    @with_current_user
    @console_ns.expect(console_ns.models[OAuthClientPayload.__name__])
    @console_ns.response(200, "Success", console_ns.models[OAuthProviderAuthorizeResponse.__name__])

View on GitHub (pinned to ef8544b173)

Solutions

  1. Register the exact redirect_uri (scheme, host, port, path, and trailing slash) in the OAuthProviderApp.redirect_uris list.
  2. Copy the redirect_uri from the registered list verbatim into the request rather than retyping it.
  3. If multiple environments are needed, register all of them rather than reusing one app across envs.
  4. Pre-validate the URI locally against the fetched allow-list before calling the endpoint.
Defensive patterns

Strategy: validation

Validate before calling

// Fetch the registered redirect_uris and ensure yours is in the list before calling.
const meta = await fetch('/console/api/oauth/provider', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({client_id: cid, redirect_uri: ru})}).then(r=>r.json());
if (!meta || meta.error) { throw new Error('redirect_uri not allowed'); }

Type guard

function redirectUriAllowed(uri: string, allowed: string[]): boolean {
  return allowed.includes(uri);
}

Try / catch

try {
  await getAppMetadata(cid, redirectUri);
} catch (e) {
  if (/redirect_uri is invalid/i.test(e.message)) { registerRedirectUri(redirectUri); }
  else throw e;
}

Prevention

When it happens

Trigger: POST /console/api/oauth/provider with a valid client_id and a redirect_uri that is not in the registered allow-list for that OAuthProviderApp. The exact-match membership test `redirect_uri not in oauth_provider_app.redirect_uris` fails.

Common situations: Client changed its callback URL (e.g. localhost -> production domain) without updating the app registration; trailing slash mismatch; http vs https mismatch; or a completely wrong callback entered.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/b813e071eaddf118. Report an issue: GitHub.