Token revocation endpoint

This commit is contained in:
Justin Spahr-Summers 2025-02-18 09:41:35 +00:00
commit 9abcccf2ed
No known key found for this signature in database
2 changed files with 50 additions and 1 deletions

View file

@ -0,0 +1,42 @@
import { OAuthServerProvider } from "../provider.js";
import express, { RequestHandler } from "express";
import cors from "cors";
import { authenticateClient } from "../middleware/clientAuth.js";
import { OAuthTokenRevocationRequestSchema } from "../../../shared/auth.js";
export type RevocationHandlerOptions = {
provider: OAuthServerProvider;
};
export function revocationHandler({ provider }: RevocationHandlerOptions): RequestHandler {
if (!provider.revokeToken) {
throw new Error("Auth provider does not support revoking tokens");
}
// Nested router so we can configure middleware and restrict HTTP method
const router = express.Router();
router.use(express.urlencoded({ extended: false }));
// Configure CORS to allow any origin, to make accessible to web-based MCP clients
router.use(cors());
// Authenticate and extract client details
router.use(authenticateClient({ clientsStore: provider.clientsStore }));
router.post("/", async (req, res) => {
let revocationRequest;
try {
revocationRequest = OAuthTokenRevocationRequestSchema.parse(req.body);
} catch (error) {
res.status(400).json({
error: "invalid_request",
error_description: String(error),
});
return;
}
await provider.revokeToken!(revocationRequest);
});
return router;
}

View file

@ -1,6 +1,6 @@
import { Response } from "express";
import { OAuthRegisteredClientsStore } from "./clients.js";
import { OAuthClientInformationFull, OAuthTokens } from "../../shared/auth.js";
import { OAuthClientInformationFull, OAuthTokenRevocationRequest, OAuthTokens } from "../../shared/auth.js";
export type AuthorizationParams = {
client: OAuthClientInformationFull;
@ -45,4 +45,11 @@ export interface OAuthServerProvider {
* Exchanges a refresh token for an access token.
*/
exchangeRefreshToken(refreshToken: string, scopes?: string[]): Promise<OAuthTokens>;
/**
* Revokes an access or refresh token. If unimplemented, token revocation is not supported (not recommended).
*
* If the given token is invalid or already revoked, this method should do nothing.
*/
revokeToken?(request: OAuthTokenRevocationRequest): Promise<void>;
}