microsoft/semantic-kernel · error · HTTPException

Invalid credentials

Error message

Invalid credentials

What it means

Thrown by the MCP OAuth sample after the state is validated but the submitted username/password do not equal the configured demo credentials (self.settings.demo_username / demo_password). It is a plain HTTP 401 rejecting the login form submission. The sample uses fixed demo credentials, not a real user store.

Source

Thrown at python/samples/demos/mcp_with_oauth/server/mcp_simple_auth/simple_auth_provider.py:175

        """Handle simple authentication callback and return redirect URI."""
        state_data = self.state_mapping.get(state)
        if not state_data:
            raise HTTPException(400, "Invalid state parameter")

        redirect_uri = state_data["redirect_uri"]
        code_challenge = state_data["code_challenge"]
        redirect_uri_provided_explicitly = state_data["redirect_uri_provided_explicitly"] == "True"
        client_id = state_data["client_id"]
        resource = state_data.get("resource")  # RFC 8707

        # These are required values from our own state mapping
        assert redirect_uri is not None
        assert code_challenge is not None
        assert client_id is not None

        # Validate demo credentials
        if username != self.settings.demo_username or password != self.settings.demo_password:
            raise HTTPException(401, "Invalid credentials")

        # Create MCP authorization code
        new_code = f"mcp_{secrets.token_hex(16)}"
        auth_code = AuthorizationCode(
            code=new_code,
            client_id=client_id,
            redirect_uri=AnyHttpUrl(redirect_uri),
            redirect_uri_provided_explicitly=redirect_uri_provided_explicitly,
            expires_at=time.time() + 300,
            scopes=[self.settings.mcp_scope],
            code_challenge=code_challenge,
            resource=resource,  # RFC 8707
        )
        self.auth_codes[new_code] = auth_code

        # Store user data
        self.user_data[username] = {
            "username": username,

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Use the exact demo credentials the server is configured with — check DEMO_USERNAME and DEMO_PASSWORD in the server's env/.env and match them exactly.
  2. Use the pre-filled defaults in the rendered login form (demo_user / demo_password) if you have not customized the env.
  3. Trim leading/trailing whitespace from submitted values and confirm no caps-lock/autocorrect altered the password.
  4. Restart the server after editing .env so the new settings are loaded.

Example fix

# .env for the sample server
DEMO_USERNAME=demo_user
DEMO_PASSWORD=demo_password
# Submit exactly these in the login form.
Defensive patterns

Strategy: validation

Validate before calling

import os
assert os.getenv('DEMO_USERNAME'), 'DEMO_USERNAME not set'
assert os.getenv('DEMO_PASSWORD'), 'DEMO_PASSWORD not set
# Submit exactly these values in the login form.

Try / catch

try:
    redirect = await provider.handle_simple_callback(username, password, state)
except HTTPException as e:
    if e.status_code == 401:
        # surface 'check DEMO_USERNAME/DEMO_PASSWORD' to the user
        ...
    raise

Prevention

When it happens

Trigger: Submitting the /login/callback form with credentials that differ from settings.demo_username/demo_password; leaving the .env values at defaults while typing other values; misconfigured DEMO_USERNAME/DEMO_PASSWORD env vars.

Common situations: Developer changed the demo credential env vars on the server but submitted the old defaults shown in the form HTML; form pre-fills 'demo_user'/'demo_password' but env was overridden to something else; copy-paste whitespace differences.

Understand the failure class

Related errors


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