/**
* postgres-mcp - OAuth Resource Server
*
* RFC 9728 Protected Resource Metadata implementation.
*/
import type {
ResourceServerConfig,
ProtectedResourceMetadata,
} from "./types.js";
/**
* OAuth 2.0 Resource Server (RFC 9728)
*/
export class OAuthResourceServer {
private readonly config: ResourceServerConfig;
constructor(config: ResourceServerConfig) {
this.config = {
...config,
bearerMethodsSupported: config.bearerMethodsSupported ?? ["header"],
};
}
/**
* Get protected resource metadata (RFC 9728)
*/
getMetadata(): ProtectedResourceMetadata {
const metadata: ProtectedResourceMetadata = {
resource: this.config.resource,
authorization_servers: this.config.authorizationServers,
scopes_supported: this.config.scopesSupported,
resource_documentation: `${this.config.resource}/docs`,
resource_signing_alg_values_supported: ["RS256", "ES256"],
};
if (this.config.bearerMethodsSupported) {
metadata.bearer_methods_supported = this.config.bearerMethodsSupported;
}
return metadata;
}
/**
* Get the well-known endpoint path for protected resource metadata
*/
getWellKnownPath(): string {
return "/.well-known/oauth-protected-resource";
}
/**
* Verify that a scope is supported by this resource
*/
isScopeSupported(scope: string): boolean {
// Check if in explicit list
if (this.config.scopesSupported.includes(scope)) {
return true;
}
// Check for PostgreSQL-specific scope patterns
if (
scope.startsWith("db:") ||
scope.startsWith("schema:") ||
scope.startsWith("table:")
) {
return true;
}
return false;
}
/**
* Get the resource identifier
*/
getResourceId(): string {
return this.config.resource;
}
/**
* Get all supported scopes
*/
getSupportedScopes(): string[] {
return [...this.config.scopesSupported];
}
/**
* Get authorization servers
*/
getAuthorizationServers(): string[] {
return [...this.config.authorizationServers];
}
}
/**
* Create an OAuth resource server instance
*/
export function createOAuthResourceServer(
config: ResourceServerConfig,
): OAuthResourceServer {
return new OAuthResourceServer(config);
}