Move OAuth definitions into shared, add more
This commit is contained in:
parent
41e0d26f23
commit
afae4212e6
4 changed files with 108 additions and 81 deletions
|
|
@ -6,7 +6,6 @@ import {
|
|||
registerClient,
|
||||
} from "./auth.js";
|
||||
|
||||
|
||||
// Mock fetch globally
|
||||
const mockFetch = jest.fn();
|
||||
global.fetch = mockFetch;
|
||||
|
|
|
|||
|
|
@ -1,84 +1,7 @@
|
|||
import pkceChallenge from "pkce-challenge";
|
||||
import { z } from "zod";
|
||||
import { LATEST_PROTOCOL_VERSION } from "../types.js";
|
||||
|
||||
export const OAuthMetadataSchema = z
|
||||
.object({
|
||||
issuer: z.string(),
|
||||
authorization_endpoint: z.string(),
|
||||
token_endpoint: z.string(),
|
||||
registration_endpoint: z.string().optional(),
|
||||
scopes_supported: z.array(z.string()).optional(),
|
||||
response_types_supported: z.array(z.string()),
|
||||
response_modes_supported: z.array(z.string()).optional(),
|
||||
grant_types_supported: z.array(z.string()).optional(),
|
||||
token_endpoint_auth_methods_supported: z.array(z.string()).optional(),
|
||||
token_endpoint_auth_signing_alg_values_supported: z
|
||||
.array(z.string())
|
||||
.optional(),
|
||||
service_documentation: z.string().optional(),
|
||||
revocation_endpoint: z.string().optional(),
|
||||
revocation_endpoint_auth_methods_supported: z.array(z.string()).optional(),
|
||||
revocation_endpoint_auth_signing_alg_values_supported: z
|
||||
.array(z.string())
|
||||
.optional(),
|
||||
introspection_endpoint: z.string().optional(),
|
||||
introspection_endpoint_auth_methods_supported: z
|
||||
.array(z.string())
|
||||
.optional(),
|
||||
introspection_endpoint_auth_signing_alg_values_supported: z
|
||||
.array(z.string())
|
||||
.optional(),
|
||||
code_challenge_methods_supported: z.array(z.string()).optional(),
|
||||
})
|
||||
.passthrough();
|
||||
|
||||
export const OAuthTokensSchema = z
|
||||
.object({
|
||||
access_token: z.string(),
|
||||
token_type: z.string(),
|
||||
expires_in: z.number().optional(),
|
||||
scope: z.string().optional(),
|
||||
refresh_token: z.string().optional(),
|
||||
})
|
||||
.strip();
|
||||
|
||||
/**
|
||||
* Client metadata schema according to RFC 7591 OAuth 2.0 Dynamic Client Registration
|
||||
*/
|
||||
export const OAuthClientMetadataSchema = z.object({
|
||||
redirect_uris: z.array(z.string()),
|
||||
token_endpoint_auth_method: z.string().optional(),
|
||||
grant_types: z.array(z.string()).optional(),
|
||||
response_types: z.array(z.string()).optional(),
|
||||
client_name: z.string().optional(),
|
||||
client_uri: z.string().optional(),
|
||||
logo_uri: z.string().optional(),
|
||||
scope: z.string().optional(),
|
||||
contacts: z.array(z.string()).optional(),
|
||||
tos_uri: z.string().optional(),
|
||||
policy_uri: z.string().optional(),
|
||||
jwks_uri: z.string().optional(),
|
||||
jwks: z.any().optional(),
|
||||
software_id: z.string().optional(),
|
||||
software_version: z.string().optional(),
|
||||
}).passthrough();
|
||||
|
||||
/**
|
||||
* Client information response schema according to RFC 7591
|
||||
*/
|
||||
export const OAuthClientInformationSchema = z.object({
|
||||
client_id: z.string(),
|
||||
client_secret: z.string().optional(),
|
||||
client_id_issued_at: z.number().optional(),
|
||||
client_secret_expires_at: z.number().optional(),
|
||||
}).passthrough();
|
||||
|
||||
export type OAuthMetadata = z.infer<typeof OAuthMetadataSchema>;
|
||||
export type OAuthTokens = z.infer<typeof OAuthTokensSchema>;
|
||||
|
||||
export type OAuthClientMetadata = z.infer<typeof OAuthClientMetadataSchema>;
|
||||
export type OAuthClientInformation = z.infer<typeof OAuthClientInformationSchema>;
|
||||
import type { OAuthClientMetadata, OAuthClientInformation, OAuthTokens, OAuthMetadata } from "../shared/auth.js";
|
||||
import { OAuthClientInformationSchema, OAuthMetadataSchema, OAuthTokensSchema } from "../shared/auth.js";
|
||||
|
||||
/**
|
||||
* Implements an end-to-end OAuth client to be used with one MCP server.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ import { createServer, type IncomingMessage, type Server } from "http";
|
|||
import { AddressInfo } from "net";
|
||||
import { JSONRPCMessage } from "../types.js";
|
||||
import { SSEClientTransport } from "./sse.js";
|
||||
import { OAuthClientProvider, OAuthTokens, UnauthorizedError } from "./auth.js";
|
||||
import { OAuthClientProvider, UnauthorizedError } from "./auth.js";
|
||||
import { OAuthTokens } from "../shared/auth.js";
|
||||
|
||||
describe("SSEClientTransport", () => {
|
||||
let server: Server;
|
||||
|
|
|
|||
104
src/shared/auth.ts
Normal file
104
src/shared/auth.ts
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
* RFC 8414 OAuth 2.0 Authorization Server Metadata
|
||||
*/
|
||||
export const OAuthMetadataSchema = z
|
||||
.object({
|
||||
issuer: z.string(),
|
||||
authorization_endpoint: z.string(),
|
||||
token_endpoint: z.string(),
|
||||
registration_endpoint: z.string().optional(),
|
||||
scopes_supported: z.array(z.string()).optional(),
|
||||
response_types_supported: z.array(z.string()),
|
||||
response_modes_supported: z.array(z.string()).optional(),
|
||||
grant_types_supported: z.array(z.string()).optional(),
|
||||
token_endpoint_auth_methods_supported: z.array(z.string()).optional(),
|
||||
token_endpoint_auth_signing_alg_values_supported: z
|
||||
.array(z.string())
|
||||
.optional(),
|
||||
service_documentation: z.string().optional(),
|
||||
revocation_endpoint: z.string().optional(),
|
||||
revocation_endpoint_auth_methods_supported: z.array(z.string()).optional(),
|
||||
revocation_endpoint_auth_signing_alg_values_supported: z
|
||||
.array(z.string())
|
||||
.optional(),
|
||||
introspection_endpoint: z.string().optional(),
|
||||
introspection_endpoint_auth_methods_supported: z
|
||||
.array(z.string())
|
||||
.optional(),
|
||||
introspection_endpoint_auth_signing_alg_values_supported: z
|
||||
.array(z.string())
|
||||
.optional(),
|
||||
code_challenge_methods_supported: z.array(z.string()).optional(),
|
||||
})
|
||||
.passthrough();
|
||||
|
||||
/**
|
||||
* OAuth 2.1 token response
|
||||
*/
|
||||
export const OAuthTokensSchema = z
|
||||
.object({
|
||||
access_token: z.string(),
|
||||
token_type: z.string(),
|
||||
expires_in: z.number().optional(),
|
||||
scope: z.string().optional(),
|
||||
refresh_token: z.string().optional(),
|
||||
})
|
||||
.strip();
|
||||
|
||||
/**
|
||||
* OAuth 2.1 error response
|
||||
*/
|
||||
export const OAuthErrorSchema = z
|
||||
.object({
|
||||
error: z.string(),
|
||||
error_description: z.string().optional(),
|
||||
error_uri: z.string().optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* RFC 7591 OAuth 2.0 Dynamic Client Registration metadata
|
||||
*/
|
||||
export const OAuthClientMetadataSchema = z.object({
|
||||
redirect_uris: z.array(z.string()),
|
||||
token_endpoint_auth_method: z.string().optional(),
|
||||
grant_types: z.array(z.string()).optional(),
|
||||
response_types: z.array(z.string()).optional(),
|
||||
client_name: z.string().optional(),
|
||||
client_uri: z.string().optional(),
|
||||
logo_uri: z.string().optional(),
|
||||
scope: z.string().optional(),
|
||||
contacts: z.array(z.string()).optional(),
|
||||
tos_uri: z.string().optional(),
|
||||
policy_uri: z.string().optional(),
|
||||
jwks_uri: z.string().optional(),
|
||||
jwks: z.any().optional(),
|
||||
software_id: z.string().optional(),
|
||||
software_version: z.string().optional(),
|
||||
}).passthrough();
|
||||
|
||||
/**
|
||||
* RFC 7591 OAuth 2.0 Dynamic Client Registration response
|
||||
*/
|
||||
export const OAuthClientInformationSchema = OAuthClientMetadataSchema.extend({
|
||||
client_id: z.string(),
|
||||
client_secret: z.string().optional(),
|
||||
client_id_issued_at: z.number().optional(),
|
||||
client_secret_expires_at: z.number().optional(),
|
||||
}).passthrough();
|
||||
|
||||
/**
|
||||
* RFC 7591 OAuth 2.0 Dynamic Client Registration error response
|
||||
*/
|
||||
export const OAuthClientRegistrationErrorSchema = z.object({
|
||||
error: z.string(),
|
||||
error_description: z.string().optional(),
|
||||
}).strip();
|
||||
|
||||
export type OAuthMetadata = z.infer<typeof OAuthMetadataSchema>;
|
||||
export type OAuthTokens = z.infer<typeof OAuthTokensSchema>;
|
||||
export type OAuthError = z.infer<typeof OAuthErrorSchema>;
|
||||
export type OAuthClientMetadata = z.infer<typeof OAuthClientMetadataSchema>;
|
||||
export type OAuthClientInformation = z.infer<typeof OAuthClientInformationSchema>;
|
||||
export type OAuthClientRegistrationError = z.infer<typeof OAuthClientRegistrationErrorSchema>;
|
||||
Loading…
Reference in a new issue