fix(auth): Skip issuer validation for management API tokens

Fixes NC PHP app (Astrolabe) OAuth integration by making token validation
more lenient for management API access.

Problem:
- Astrolabe calls Nextcloud OIDC token endpoint via internal URL (http://localhost)
- Tokens are issued with iss: http://localhost (internal)
- MCP server expects iss: http://localhost:8080 (external)
- Token validation failed with "Invalid issuer"

Solution:
- Add skip_issuer_check parameter to _verify_jwt_signature()
- verify_token_for_management_api() now skips both audience and issuer checks
- Security maintained: signature still verified, authorization checked by API

Also includes related fixes from previous session:
- Update test selectors for Vue 3 UI ("Enable Semantic Search")
- Fix OIDC discovery URL transformation in OAuthController.php
- Add overwrite.cli.url to setup hook for proper external URLs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2025-12-24 17:25:48 -06:00
parent 5e2ef5f35b
commit 804480836e
6 changed files with 249 additions and 78 deletions
+13 -2
View File
@@ -335,9 +335,10 @@ class OAuthController extends Controller {
]);
} else {
// Fall back to Nextcloud's OIDC app
// Use internal localhost URL for HTTP request (always accessible from inside container)
// The OIDC discovery response will contain proper external URLs based on overwrite.cli.url
// Use internal localhost URL for HTTP request (accessible from inside container)
// We'll transform the returned URLs to external format after discovery
$discoveryUrl = 'http://localhost/.well-known/openid-configuration';
$internalBaseUrl = 'http://localhost';
$this->logger->info('Using Nextcloud OIDC app as IdP (internal request)', [
'discovery_url' => $discoveryUrl,
@@ -368,6 +369,16 @@ class OAuthController extends Controller {
}
$authEndpoint = $discovery['authorization_endpoint'];
// Transform internal URL to external URL if using Nextcloud OIDC app
// The discovery was done via internal http://localhost but browsers need
// the external URL (e.g., http://localhost:8080)
if (isset($internalBaseUrl)) {
$externalBaseUrl = $this->urlGenerator->getAbsoluteURL('/');
$externalBaseUrl = rtrim($externalBaseUrl, '/');
$authEndpoint = str_replace($internalBaseUrl, $externalBaseUrl, $authEndpoint);
}
$this->logger->info('buildAuthorizationUrl: OIDC discovery succeeded', [
'auth_endpoint' => $authEndpoint,
'token_endpoint' => $discovery['token_endpoint'] ?? 'not_set',