microsoft/semantic-kernel · warning · HTTPException

Missing state parameter

Error message

Missing state parameter

What it means

Raised as HTTPException(400) by the login_page_handler in mcp_simple_auth's auth_server.py when the /login GET request lacks a 'state' query parameter. The state parameter ties the login page to an in-flight authorization request; without it the server cannot render a valid login form and rejects the request.

Solutions

  1. Ensure the authorization flow always appends a valid state to the /login URL.
  2. Start the OAuth flow from the proper authorize endpoint so the server generates and forwards state.
  3. Do not deep-link /login without going through the authorize step.
  4. Check reverse proxies / load balancers are not stripping query parameters.

Example fix

// before
# user opens http://host/login directly

// after
# start at the authorize endpoint; server redirects to /login?state=<generated>
Defensive patterns

Strategy: validation

Validate before calling

state = request.query_params.get('state')
if not state:
    return PlainTextResponse('Missing state. Start the flow at /authorize.', status_code=400)
await oauth_provider.get_login_page(state)

Type guard

def has_state_param(request) -> bool:
    return bool(request.query_params.get('state'))

Prevention

When it happens

Trigger: A GET /login request without ?state=...; the client/initiator omitted the state parameter when constructing the login URL; a user navigated directly to /login manually.

Common situations: Browser bookmarks hitting /login directly; a misconfigured client building the auth URL; the state was dropped by a redirect/proxy.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/463c490cc880bc17. Report an issue: GitHub.

Appendix: source

Thrown at python/samples/demos/mcp_with_oauth/server/mcp_simple_auth/auth_server.py:88

        required_scopes=[auth_settings.mcp_scope],
        resource_server_url=None,
    )

    # Create OAuth routes
    routes = create_auth_routes(
        provider=oauth_provider,
        issuer_url=mcp_auth_settings.issuer_url,
        service_documentation_url=mcp_auth_settings.service_documentation_url,
        client_registration_options=mcp_auth_settings.client_registration_options,
        revocation_options=mcp_auth_settings.revocation_options,
    )

    # Add login page route (GET)
    async def login_page_handler(request: Request) -> Response:
        """Show login form."""
        state = request.query_params.get("state")
        if not state:
            raise HTTPException(400, "Missing state parameter")
        return await oauth_provider.get_login_page(state)

    routes.append(Route("/login", endpoint=login_page_handler, methods=["GET"]))

    # Add login callback route (POST)
    async def login_callback_handler(request: Request) -> Response:
        """Handle simple authentication callback."""
        return await oauth_provider.handle_login_callback(request)

    routes.append(Route("/login/callback", endpoint=login_callback_handler, methods=["POST"]))

    # Add token introspection endpoint (RFC 7662) for Resource Servers
    async def introspect_handler(request: Request) -> Response:
        """
        Token introspection endpoint for Resource Servers.

        Resource Servers call this endpoint to validate tokens without
        needing direct access to token storage.

View on GitHub (pinned to c028a0c7dc)