|
1 |
| -import { useCallback, useMemo } from "react"; |
| 1 | +import { useCallback, useMemo, useEffect } from "react"; |
2 | 2 | import { Button } from "@/components/ui/button";
|
3 | 3 | import { DebugInspectorOAuthClientProvider } from "../lib/auth";
|
4 | 4 | import { AlertCircle } from "lucide-react";
|
5 |
| -import { AuthDebuggerState } from "../lib/auth-types"; |
| 5 | +import { AuthDebuggerState, EMPTY_DEBUGGER_STATE } from "../lib/auth-types"; |
6 | 6 | import { OAuthFlowProgress } from "./OAuthFlowProgress";
|
7 | 7 | import { OAuthStateMachine } from "../lib/oauth-state-machine";
|
| 8 | +import { SESSION_KEYS } from "../lib/constants"; |
8 | 9 |
|
9 | 10 | export interface AuthDebuggerProps {
|
10 | 11 | serverUrl: string;
|
@@ -59,6 +60,27 @@ const AuthDebugger = ({
|
59 | 60 | authState,
|
60 | 61 | updateAuthState,
|
61 | 62 | }: AuthDebuggerProps) => {
|
| 63 | + // Check for existing tokens on mount |
| 64 | + useEffect(() => { |
| 65 | + if (serverUrl && !authState.oauthTokens) { |
| 66 | + const checkTokens = async () => { |
| 67 | + try { |
| 68 | + const provider = new DebugInspectorOAuthClientProvider(serverUrl); |
| 69 | + const existingTokens = await provider.tokens(); |
| 70 | + if (existingTokens) { |
| 71 | + updateAuthState({ |
| 72 | + oauthTokens: existingTokens, |
| 73 | + oauthStep: "complete", |
| 74 | + }); |
| 75 | + } |
| 76 | + } catch (error) { |
| 77 | + console.error("Failed to load existing OAuth tokens:", error); |
| 78 | + } |
| 79 | + }; |
| 80 | + checkTokens(); |
| 81 | + } |
| 82 | + }, [serverUrl, updateAuthState, authState.oauthTokens]); |
| 83 | + |
62 | 84 | const startOAuthFlow = useCallback(() => {
|
63 | 85 | if (!serverUrl) {
|
64 | 86 | updateAuthState({
|
@@ -141,6 +163,11 @@ const AuthDebugger = ({
|
141 | 163 | currentState.oauthStep === "authorization_code" &&
|
142 | 164 | currentState.authorizationUrl
|
143 | 165 | ) {
|
| 166 | + // Store the current auth state before redirecting |
| 167 | + sessionStorage.setItem( |
| 168 | + SESSION_KEYS.AUTH_DEBUGGER_STATE, |
| 169 | + JSON.stringify(currentState), |
| 170 | + ); |
144 | 171 | // Open the authorization URL automatically
|
145 | 172 | window.location.href = currentState.authorizationUrl;
|
146 | 173 | break;
|
@@ -178,13 +205,7 @@ const AuthDebugger = ({
|
178 | 205 | );
|
179 | 206 | serverAuthProvider.clear();
|
180 | 207 | updateAuthState({
|
181 |
| - oauthTokens: null, |
182 |
| - oauthStep: "metadata_discovery", |
183 |
| - latestError: null, |
184 |
| - oauthClientInfo: null, |
185 |
| - authorizationCode: "", |
186 |
| - validationError: null, |
187 |
| - oauthMetadata: null, |
| 208 | + ...EMPTY_DEBUGGER_STATE, |
188 | 209 | statusMessage: {
|
189 | 210 | type: "success",
|
190 | 211 | message: "OAuth tokens cleared successfully",
|
@@ -224,52 +245,48 @@ const AuthDebugger = ({
|
224 | 245 | <StatusMessage message={authState.statusMessage} />
|
225 | 246 | )}
|
226 | 247 |
|
227 |
| - {authState.loading ? ( |
228 |
| - <p>Loading authentication status...</p> |
229 |
| - ) : ( |
230 |
| - <div className="space-y-4"> |
231 |
| - {authState.oauthTokens && ( |
232 |
| - <div className="space-y-2"> |
233 |
| - <p className="text-sm font-medium">Access Token:</p> |
234 |
| - <div className="bg-muted p-2 rounded-md text-xs overflow-x-auto"> |
235 |
| - {authState.oauthTokens.access_token.substring(0, 25)}... |
236 |
| - </div> |
| 248 | + <div className="space-y-4"> |
| 249 | + {authState.oauthTokens && ( |
| 250 | + <div className="space-y-2"> |
| 251 | + <p className="text-sm font-medium">Access Token:</p> |
| 252 | + <div className="bg-muted p-2 rounded-md text-xs overflow-x-auto"> |
| 253 | + {authState.oauthTokens.access_token.substring(0, 25)}... |
237 | 254 | </div>
|
238 |
| - )} |
239 |
| - |
240 |
| - <div className="flex gap-4"> |
241 |
| - <Button |
242 |
| - variant="outline" |
243 |
| - onClick={startOAuthFlow} |
244 |
| - disabled={authState.isInitiatingAuth} |
245 |
| - > |
246 |
| - {authState.oauthTokens |
247 |
| - ? "Guided Token Refresh" |
248 |
| - : "Guided OAuth Flow"} |
249 |
| - </Button> |
| 255 | + </div> |
| 256 | + )} |
250 | 257 |
|
251 |
| - <Button |
252 |
| - onClick={handleQuickOAuth} |
253 |
| - disabled={authState.isInitiatingAuth} |
254 |
| - > |
255 |
| - {authState.isInitiatingAuth |
256 |
| - ? "Initiating..." |
257 |
| - : authState.oauthTokens |
258 |
| - ? "Quick Refresh" |
259 |
| - : "Quick OAuth Flow"} |
260 |
| - </Button> |
| 258 | + <div className="flex gap-4"> |
| 259 | + <Button |
| 260 | + variant="outline" |
| 261 | + onClick={startOAuthFlow} |
| 262 | + disabled={authState.isInitiatingAuth} |
| 263 | + > |
| 264 | + {authState.oauthTokens |
| 265 | + ? "Guided Token Refresh" |
| 266 | + : "Guided OAuth Flow"} |
| 267 | + </Button> |
261 | 268 |
|
262 |
| - <Button variant="outline" onClick={handleClearOAuth}> |
263 |
| - Clear OAuth State |
264 |
| - </Button> |
265 |
| - </div> |
| 269 | + <Button |
| 270 | + onClick={handleQuickOAuth} |
| 271 | + disabled={authState.isInitiatingAuth} |
| 272 | + > |
| 273 | + {authState.isInitiatingAuth |
| 274 | + ? "Initiating..." |
| 275 | + : authState.oauthTokens |
| 276 | + ? "Quick Refresh" |
| 277 | + : "Quick OAuth Flow"} |
| 278 | + </Button> |
266 | 279 |
|
267 |
| - <p className="text-xs text-muted-foreground"> |
268 |
| - Choose "Guided" for step-by-step instructions or "Quick" for |
269 |
| - the standard automatic flow. |
270 |
| - </p> |
| 280 | + <Button variant="outline" onClick={handleClearOAuth}> |
| 281 | + Clear OAuth State |
| 282 | + </Button> |
271 | 283 | </div>
|
272 |
| - )} |
| 284 | + |
| 285 | + <p className="text-xs text-muted-foreground"> |
| 286 | + Choose "Guided" for step-by-step instructions or "Quick" for |
| 287 | + the standard automatic flow. |
| 288 | + </p> |
| 289 | + </div> |
273 | 290 | </div>
|
274 | 291 |
|
275 | 292 | <OAuthFlowProgress
|
|
0 commit comments