Tencent/WeKnora · error
principal context is required to authorize OAuth MCP service
Error message
principal context is required to authorize OAuth MCP service %s
What it means
Returned by StartAuthorization when the principal is missing or invalid after normalization. OAuth tokens are stored per-principal (tenant + principal identify the token row), so an anonymous/system context without a valid principal cannot start an authorization flow.
Source
Thrown at internal/mcp/oauth_manager.go:94
}
// StartAuthorization performs discovery + (one-time) dynamic client
// registration, then returns the authorization URL and an opaque attempt ID.
// redirectURI is the backend callback URL registered with the auth server;
// frontendRedirect is where the callback bounces the browser when finished.
func (m *OAuthManager) StartAuthorization(
ctx context.Context,
service *types.MCPService,
tenantID uint64,
principal types.Principal,
redirectURI, frontendRedirect string,
) (authorizationURL, attemptID string, err error) {
if !service.AuthConfig.IsOAuth() {
return "", "", fmt.Errorf("MCP service %s does not use OAuth", service.ID)
}
principal = principal.Normalize()
if !principal.Valid() {
return "", "", fmt.Errorf("principal context is required to authorize OAuth MCP service %s", service.ID)
}
h, err := m.newHandler(ctx, service, tenantID, principal, redirectURI)
if err != nil {
return "", "", err
}
// Register a client dynamically if we don't have one yet for this service.
existing, _ := m.repo.GetClient(ctx, tenantID, service.ID)
if existing == nil {
if err := h.RegisterClient(ctx, clientRegistrationName); err != nil {
return "", "", fmt.Errorf("dynamic client registration failed: %w", err)
}
clientID := h.GetClientID()
if clientID == "" {
return "", "", fmt.Errorf("dynamic client registration returned an empty client_id")
}
if err := m.repo.SaveClient(ctx, &types.MCPOAuthClient{View on GitHub (pinned to 988cbb0330)
Solutions
- Pass the authenticated user's principal from the request context into StartAuthorization
- Ensure auth middleware injects a valid principal before handlers call the OAuth manager
- For machine flows, construct a principal with a valid service identity rather than a zero value
- Check that Normalize()+Valid() requirements (non-zero tenant/user IDs) are met
Example fix
// before
_, _, err := mgr.StartAuthorizationForService(ctx, svc, tenantID, types.Principal{}, redirect, "")
// after
principal, ok := types.PrincipalFromContext(ctx)
if !ok || !principal.Normalize().Valid() {
return fmt.Errorf("unauthenticated request: cannot start OAuth flow")
}
_, _, err := mgr.StartAuthorizationForService(ctx, svc, tenantID, principal, redirect, "") Defensive patterns
Strategy: validation
Validate before calling
principal, ok := types.PrincipalFromContext(ctx)
if !ok || !principal.Normalize().Valid() {
return fmt.Errorf("authenticated principal required")
} Type guard
func hasValidPrincipal(ctx context.Context) bool {
p, ok := types.PrincipalFromContext(ctx)
return ok && p.Normalize().Valid()
} Try / catch
if !hasValidPrincipal(ctx) { return http.ErrNoAuth /* redirect to login */ }
principal, _ := types.PrincipalFromContext(ctx)
if _, _, err := mgr.StartAuthorizationForService(ctx, svc, tenantID, principal, redirect, ""); err != nil {
if strings.Contains(err.Error(), "principal context is required") { return redirectLogin }
return err
} Prevention
- Require auth middleware on every route that starts OAuth flows
- Never construct zero-value principals for user-facing flows
- Unit-test handlers with and without principal context
- Fail fast at the handler boundary, before calling the OAuth manager
When it happens
Trigger: Calling AuthorizeURL/StartAuthorizationForService with a zero-value types.Principal, or one that fails principal.Valid() after Normalize() (no user/org identity in context).
Common situations: Background job or webhook handler calls the manager without propagating the user's auth context; middleware dropped the principal from the request context; testing with a bare Principal{} struct.
Related errors
- principal context is required to connect to an OAuth MCP ser
- principal context is required to connect to OAuth MCP servic
- MCP service URL is required for OAuth
- MCP service %s does not use OAuth
- OAuth token response did not contain an access_token
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/9fcce0b21fbd676d.
Report an issue: GitHub.