familiar is issuer-agnostic (resource server only), so Gitea can back oauth mode with config alone: RS256 JWTs, JWKS at /login/oauth/keys, and OIDC discovery. Add a deployment.md section covering the env config, the aud=client-ID audience pitfall, and the no-DCR caveat; add a Gitea block to .env.example; and note in claude-web.md that Gitea can't back the claude.ai web connector (which requires DCR).
2.8 KiB
Connect Claude web (claude.ai)
Auth: OAuth 2.1 only. Prereq: familiar in oauth mode behind HTTPS, plus an external identity provider.
The claude.ai custom-connector flow speaks OAuth 2.1 with Dynamic Client Registration (DCR) and does not accept a static bearer token. familiar itself is only a resource server — it validates JWTs and advertises where to authenticate, but it is not an authorization server and does no DCR. So Claude web needs an external IdP that supports DCR (e.g. Authentik or Keycloak) sitting in front.
Gitea won't work here. Gitea is a fine OAuth issuer for familiar in general (see deployment.md → Using Gitea as the OAuth issuer), but it has no Dynamic Client Registration, which this connector requires. Use it only with clients that take a pre-registered client ID/secret, or put a DCR-capable IdP in front.
Simpler alternative: if you don't want to run an IdP, use the Claude Desktop app with a bearer token instead — see Connect Claude Desktop. Bearer is easier for every client except the claude.ai web connector.
1. Set up the IdP (external)
On your IdP, create an application/provider for familiar that:
- issues JWT access tokens signed with a key published at a JWKS endpoint,
- sets the token audience to familiar's public URL (the resource),
- supports Dynamic Client Registration so claude.ai can register itself.
Note the issuer URL and (optionally) the JWKS URL.
2. Configure familiar in oauth mode
FAMILIAR_AUTH_MODE=oauth
FAMILIAR_OAUTH_ISSUER=https://idp.yourdomain.tld/application/o/familiar/
FAMILIAR_OAUTH_RESOURCE=https://familiar.yourdomain.tld
# FAMILIAR_OAUTH_AUDIENCE defaults to the resource URL; override if your IdP differs.
# FAMILIAR_OAUTH_JWKS_URI is discovered from the issuer's OIDC metadata if unset.
No FAMILIAR_HTTP_TOKEN is needed in oauth mode. familiar serves the discovery document at https://familiar.yourdomain.tld/.well-known/oauth-protected-resource/mcp, and unauthenticated MCP calls return 401 with a WWW-Authenticate: Bearer header pointing at your issuer.
3. Add the connector
In claude.ai: Settings → Connectors → Add custom connector, URL https://familiar.yourdomain.tld/mcp. Claude discovers your IdP from the metadata, registers via DCR, and runs the OAuth login. Approve familiar's scopes and you're connected.
Troubleshooting
- "couldn't connect" immediately — familiar isn't in
oauthmode, orFAMILIAR_OAUTH_RESOURCE/ISSUERare unset; the metadata endpoint must return 200. - Login loops / invalid token — audience mismatch: your IdP's token
audmust equalFAMILIAR_OAUTH_RESOURCE(or yourFAMILIAR_OAUTH_AUDIENCE). - DCR fails — the IdP doesn't have Dynamic Client Registration enabled; claude.ai requires it.