store state before redirect

This commit is contained in:
Paul Carleton 2025-05-29 11:50:09 +01:00
commit 0dbf75a664
No known key found for this signature in database
4 changed files with 47 additions and 10 deletions

View file

@ -234,21 +234,36 @@ const App = () => {
({ ({
authorizationCode, authorizationCode,
errorMsg, errorMsg,
restoredState,
}: { }: {
authorizationCode?: string; authorizationCode?: string;
errorMsg?: string; errorMsg?: string;
restoredState?: AuthDebuggerState;
}) => { }) => {
setIsAuthDebuggerVisible(true); setIsAuthDebuggerVisible(true);
if (authorizationCode) {
if (restoredState) {
// Restore the previous auth state
updateAuthState({ updateAuthState({
authorizationCode, ...restoredState,
oauthStep: "token_request", // Update with the new authorization code if provided
}); authorizationCode: authorizationCode || restoredState.authorizationCode,
} oauthStep: authorizationCode ? "token_request" : restoredState.oauthStep,
if (errorMsg) { latestError: errorMsg ? new Error(errorMsg) : restoredState.latestError,
updateAuthState({
latestError: new Error(errorMsg),
}); });
} else {
// Fallback to the original behavior if no state was restored
if (authorizationCode) {
updateAuthState({
authorizationCode,
oauthStep: "token_request",
});
}
if (errorMsg) {
updateAuthState({
latestError: new Error(errorMsg),
});
}
} }
}, },
[], [],

View file

@ -5,6 +5,7 @@ import { AlertCircle } from "lucide-react";
import { AuthDebuggerState, EMPTY_DEBUGGER_STATE } from "../lib/auth-types"; import { AuthDebuggerState, EMPTY_DEBUGGER_STATE } from "../lib/auth-types";
import { OAuthFlowProgress } from "./OAuthFlowProgress"; import { OAuthFlowProgress } from "./OAuthFlowProgress";
import { OAuthStateMachine } from "../lib/oauth-state-machine"; import { OAuthStateMachine } from "../lib/oauth-state-machine";
import { SESSION_KEYS } from "../lib/constants";
export interface AuthDebuggerProps { export interface AuthDebuggerProps {
serverUrl: string; serverUrl: string;
@ -141,6 +142,11 @@ const AuthDebugger = ({
currentState.oauthStep === "authorization_code" && currentState.oauthStep === "authorization_code" &&
currentState.authorizationUrl currentState.authorizationUrl
) { ) {
// Store the current auth state before redirecting
sessionStorage.setItem(
SESSION_KEYS.AUTH_DEBUGGER_STATE,
JSON.stringify(currentState)
);
// Open the authorization URL automatically // Open the authorization URL automatically
window.location.href = currentState.authorizationUrl; window.location.href = currentState.authorizationUrl;
break; break;

View file

@ -9,9 +9,11 @@ interface OAuthCallbackProps {
onConnect: ({ onConnect: ({
authorizationCode, authorizationCode,
errorMsg, errorMsg,
restoredState,
}: { }: {
authorizationCode?: string; authorizationCode?: string;
errorMsg?: string; errorMsg?: string;
restoredState?: any;
}) => void; }) => void;
} }
@ -35,6 +37,19 @@ const OAuthDebugCallback = ({ onConnect }: OAuthCallbackProps) => {
const serverUrl = sessionStorage.getItem(SESSION_KEYS.SERVER_URL); const serverUrl = sessionStorage.getItem(SESSION_KEYS.SERVER_URL);
// Try to restore the auth state
const storedState = sessionStorage.getItem(SESSION_KEYS.AUTH_DEBUGGER_STATE);
let restoredState = null;
if (storedState) {
try {
restoredState = JSON.parse(storedState);
// Clean up the stored state
sessionStorage.removeItem(SESSION_KEYS.AUTH_DEBUGGER_STATE);
} catch (e) {
console.error("Failed to parse stored auth state:", e);
}
}
// ServerURL isn't set, this can happen if we've opened the // ServerURL isn't set, this can happen if we've opened the
// authentication request in a new tab, so we don't have the same // authentication request in a new tab, so we don't have the same
// session storage // session storage
@ -50,8 +65,8 @@ const OAuthDebugCallback = ({ onConnect }: OAuthCallbackProps) => {
} }
// Instead of storing in sessionStorage, pass the code directly // Instead of storing in sessionStorage, pass the code directly
// to the auth state manager through onConnect // to the auth state manager through onConnect, along with restored state
onConnect({ authorizationCode: params.code }); onConnect({ authorizationCode: params.code, restoredState });
}; };
handleCallback().finally(() => { handleCallback().finally(() => {

View file

@ -7,6 +7,7 @@ export const SESSION_KEYS = {
TOKENS: "mcp_tokens", TOKENS: "mcp_tokens",
CLIENT_INFORMATION: "mcp_client_information", CLIENT_INFORMATION: "mcp_client_information",
SERVER_METADATA: "mcp_server_metadata", SERVER_METADATA: "mcp_server_metadata",
AUTH_DEBUGGER_STATE: "mcp_auth_debugger_state",
} as const; } as const;
// Generate server-specific session storage keys // Generate server-specific session storage keys