> ## Documentation Index
> Fetch the complete documentation index at: https://authsome.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# OAuth callback errors

> Diagnose `redirect_uri_mismatch`, port-in-use, browser-not-opening, and timeout errors during PKCE login.

The PKCE flow uses the local daemon on `127.0.0.1:7998` to receive the OAuth callback at `/auth/callback/oauth`. Most login failures fall into one of the categories below.

<AccordionGroup>
  <Accordion title="redirect_uri_mismatch" icon="link-slash">
    The provider's authorization page returns:

    ```text theme={null}
    The redirect_uri MUST match the registered callback URL for this application.
    ```

    Authsome listens on a single redirect URI:

    ```text theme={null}
    http://127.0.0.1:7998/auth/callback/oauth
    ```

    Fix it at the provider:

    <Steps>
      <Step title="Open your OAuth app settings">
        For GitHub: [github.com/settings/developers](https://github.com/settings/developers). For other providers, find the equivalent OAuth app management page.
      </Step>

      <Step title="Edit the callback URL">
        Set **Authorization callback URL** (or the equivalent field) to `http://127.0.0.1:7998/auth/callback/oauth`. The full path matters, it must be `/auth/callback/oauth`.
      </Step>

      <Step title="Save and retry login">
        ```bash theme={null}
        authsome login <provider> --force
        ```
      </Step>
    </Steps>

    <Tip>
      For services that support Dynamic Client Registration, the `dcr_pkce` flow registers a fresh OAuth client with the right redirect URI automatically. Check `authsome inspect <provider>` for `supports_dcr: true`.
    </Tip>
  </Accordion>

  <Accordion title="Port 7998 already in use" icon="plug-circle-exclamation">
    ```text theme={null}
    Error: address already in use: 127.0.0.1:7998
    ```

    Another process is bound to the daemon port. The CLI reuses an existing `authsome` daemon if one is already running; you only see this error when something *else* holds 7998. Find and stop it:

    ```bash theme={null}
    # macOS / Linux
    lsof -nP -iTCP:7998 -sTCP:LISTEN
    kill <PID>
    ```

    If a stale `authsome` daemon won't release the port, `pkill -f authsome` then re-run any CLI command. See [Daemon issues](/troubleshooting/daemon-issues).
  </Accordion>

  <Accordion title="Browser does not open" icon="browser">
    The terminal prints the authorization URL but no browser launches.

    | Cause                                                   | Fix                                                                                   |
    | ------------------------------------------------------- | ------------------------------------------------------------------------------------- |
    | You're SSHed into a remote machine                      | Use `--flow device_code` instead. See [Headless setup](/guides/headless-device-code). |
    | `webbrowser` Python module can't find a default browser | Set `BROWSER` env var: `export BROWSER=$(which firefox)`.                             |
    | Headless Linux without `DISPLAY`                        | Same as SSH, use the device code flow.                                                |

    You can also copy the URL printed in the terminal and open it manually on any device. As long as the redirect lands on `http://127.0.0.1:7998/auth/callback/oauth` on the same machine where authsome is waiting, the flow completes.
  </Accordion>

  <Accordion title="Browser opens but never returns to authsome" icon="clock">
    The browser shows the provider's authorization page, you click **Authorize**, and nothing. The terminal is still waiting.

    | Cause                                                                                    | Fix                                                         |
    | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
    | The browser landed on `http://127.0.0.1:7998/auth/callback/oauth` but authsome timed out | Re-run `authsome login --force`.                            |
    | A corporate proxy is intercepting `127.0.0.1` traffic                                    | Add `127.0.0.1` and `localhost` to your `NO_PROXY` env var. |
    | You authorized in a different browser profile that can't reach localhost                 | Use the same browser profile as your authsome shell.        |
  </Accordion>

  <Accordion title="state mismatch error" icon="shield-halved">
    ```text theme={null}
    Error: OAuth state parameter does not match
    ```

    Authsome generates a random `state` parameter and rejects callbacks that don't echo it back. Causes:

    * A stale tab from a previous login is hitting the callback. Close it and retry.
    * A man-in-the-middle is replaying old callback URLs. Investigate before retrying.
  </Accordion>

  <Accordion title="client_id or client_secret rejected" icon="id-card">
    The provider's token endpoint returns `invalid_client`.

    ```text theme={null}
    Error: token exchange failed: invalid_client
    ```

    The stored client credentials don't match what the provider expects.

    ```bash theme={null}
    authsome revoke <provider>     # clear stored client + tokens
    authsome login <provider>      # re-enter client_id and client_secret via browser bridge
    ```

    If you've recently rotated the OAuth app's client secret, this is the expected flow.
  </Accordion>

  <Accordion title="Scopes not granted" icon="filter">
    The login completes but the agent gets `403 Insufficient scope` on real API calls.

    ```bash theme={null}
    authsome get <provider> --field scopes
    ```

    If the granted scopes don't include what your agent needs:

    ```bash theme={null}
    authsome login <provider> --scopes "<scope1>,<scope2>" --force
    ```

    The provider re-prompts for consent on the additional scopes.
  </Accordion>
</AccordionGroup>

## What's next

<Columns cols={2}>
  <Card title="Token refresh" icon="rotate" href="/troubleshooting/token-refresh">
    What to do when a refresh fails.
  </Card>

  <Card title="Headless device code" icon="server" href="/guides/headless-device-code">
    The right flow when you can't run a browser locally.
  </Card>
</Columns>
