import { nanoid } from "nanoid";
//#region src/mcp/do-oauth-client-provider.ts
const STATE_EXPIRATION_MS = 600 * 1e3;
var DurableObjectOAuthClientProvider = class {
constructor(storage, clientName, baseRedirectUrl) {
this.storage = storage;
this.clientName = clientName;
this.baseRedirectUrl = baseRedirectUrl;
if (!storage) throw new Error("DurableObjectOAuthClientProvider requires a valid DurableObjectStorage instance");
}
get clientMetadata() {
return {
client_name: this.clientName,
client_uri: this.clientUri,
grant_types: ["authorization_code", "refresh_token"],
redirect_uris: [this.redirectUrl],
response_types: ["code"],
token_endpoint_auth_method: "none"
};
}
get clientUri() {
return new URL(this.redirectUrl).origin;
}
get redirectUrl() {
return this.baseRedirectUrl;
}
get clientId() {
if (!this._clientId_) throw new Error("Trying to access clientId before it was set");
return this._clientId_;
}
set clientId(clientId_) {
this._clientId_ = clientId_;
}
get serverId() {
if (!this._serverId_) throw new Error("Trying to access serverId before it was set");
return this._serverId_;
}
set serverId(serverId_) {
this._serverId_ = serverId_;
}
keyPrefix(clientId) {
return `/${this.clientName}/${this.serverId}/${clientId}`;
}
clientInfoKey(clientId) {
return `${this.keyPrefix(clientId)}/client_info/`;
}
async clientInformation() {
if (!this._clientId_) return;
return await this.storage.get(this.clientInfoKey(this.clientId)) ?? void 0;
}
async saveClientInformation(clientInformation) {
await this.storage.put(this.clientInfoKey(clientInformation.client_id), clientInformation);
this.clientId = clientInformation.client_id;
}
tokenKey(clientId) {
return `${this.keyPrefix(clientId)}/token`;
}
async tokens() {
if (!this._clientId_) return;
return await this.storage.get(this.tokenKey(this.clientId)) ?? void 0;
}
async saveTokens(tokens) {
await this.storage.put(this.tokenKey(this.clientId), tokens);
}
get authUrl() {
return this._authUrl_;
}
stateKey(nonce) {
return `/${this.clientName}/${this.serverId}/state/${nonce}`;
}
async state() {
const nonce = nanoid();
const state = `${nonce}.${this.serverId}`;
const storedState = {
nonce,
serverId: this.serverId,
createdAt: Date.now()
};
await this.storage.put(this.stateKey(nonce), storedState);
return state;
}
async checkState(state) {
const parts = state.split(".");
if (parts.length !== 2) return {
valid: false,
error: "Invalid state format"
};
const [nonce, serverId] = parts;
const key = this.stateKey(nonce);
const storedState = await this.storage.get(key);
if (!storedState) return {
valid: false,
error: "State not found or already used"
};
if (storedState.serverId !== serverId) {
await this.storage.delete(key);
return {
valid: false,
error: "State serverId mismatch"
};
}
if (Date.now() - storedState.createdAt > STATE_EXPIRATION_MS) {
await this.storage.delete(key);
return {
valid: false,
error: "State expired"
};
}
return {
valid: true,
serverId
};
}
async consumeState(state) {
const parts = state.split(".");
if (parts.length !== 2) {
console.warn(`[OAuth] consumeState called with invalid state format: ${state.substring(0, 20)}...`);
return;
}
const [nonce] = parts;
await this.storage.delete(this.stateKey(nonce));
}
async redirectToAuthorization(authUrl) {
this._authUrl_ = authUrl.toString();
}
async invalidateCredentials(scope) {
if (!this._clientId_) return;
const deleteKeys = [];
if (scope === "all" || scope === "client") deleteKeys.push(this.clientInfoKey(this.clientId));
if (scope === "all" || scope === "tokens") deleteKeys.push(this.tokenKey(this.clientId));
if (scope === "all" || scope === "verifier") deleteKeys.push(this.codeVerifierKey(this.clientId));
if (deleteKeys.length > 0) await this.storage.delete(deleteKeys);
}
codeVerifierKey(clientId) {
return `${this.keyPrefix(clientId)}/code_verifier`;
}
async saveCodeVerifier(verifier) {
const key = this.codeVerifierKey(this.clientId);
if (await this.storage.get(key)) return;
await this.storage.put(key, verifier);
}
async codeVerifier() {
const codeVerifier = await this.storage.get(this.codeVerifierKey(this.clientId));
if (!codeVerifier) throw new Error("No code verifier found");
return codeVerifier;
}
async deleteCodeVerifier() {
await this.storage.delete(this.codeVerifierKey(this.clientId));
}
};
//#endregion
export { DurableObjectOAuthClientProvider as t };
//# sourceMappingURL=do-oauth-client-provider-B1fVIshX.js.map