@@ -44,45 +44,38 @@ export function Login() {
4444
4545 // Parse SSO redirect style: {server}/access_token=...&refresh_token=...
4646 useEffect ( ( ) => {
47- // Detect tokens embedded after origin (no question mark) e.g. https://srv/access_token=XXX&refresh_token=YYY
48- // Or possibly inside hash.
4947 try {
5048 const loc = window . location ;
51- const path = loc . pathname . startsWith ( "/" )
52- ? loc . pathname . slice ( 1 )
53- : loc . pathname ;
49+ const search = loc . search . startsWith ( "?" ) ? loc . search . substring ( 1 ) : loc . search ;
50+ const path = loc . pathname . startsWith ( "/" ) ? loc . pathname . slice ( 1 ) : loc . pathname ;
5451 const hash = loc . hash . startsWith ( "#" ) ? loc . hash . slice ( 1 ) : loc . hash ;
55- const candidate = path . includes ( "access_token=" ) ? path : hash ;
56- if ( ! candidate ) return ;
57- if ( ! / a c c e s s _ t o k e n = / . test ( candidate ) ) return ;
58- // Interpret as key=value pairs separated by & possibly with leading segment (e.g., access_token=...&refresh_token=...)
59- const pairs = candidate . split ( "&" ) . filter ( Boolean ) ;
60- const data : Record < string , string > = { } ;
61- for ( const p of pairs ) {
62- const eq = p . indexOf ( "=" ) ;
63- if ( eq === - 1 ) continue ;
64- const k = decodeURIComponent ( p . slice ( 0 , eq ) ) ;
65- const v = decodeURIComponent ( p . slice ( eq + 1 ) ) ;
66- data [ k ] = v ;
67- }
68- if ( ! data . access_token ) return ;
69- // Determine server base: remove the trailing candidate part from URL if it's at pathname
70- const base = window . location . origin ;
52+
53+ // Priority order: query string (?access_token=...), then path style, then hash fragment.
54+ let candidate = "" ;
55+ if ( / a c c e s s _ t o k e n = / . test ( search ) ) candidate = search ;
56+ else if ( / a c c e s s _ t o k e n = / . test ( path ) ) candidate = path ;
57+ else if ( / a c c e s s _ t o k e n = / . test ( hash ) ) candidate = hash ;
58+ if ( ! candidate ) return ; // no tokens present
59+
60+ const params = new URLSearchParams ( candidate . replace ( / ^ [ ^ ? ] * \? / , "" ) ) ;
61+ const access = params . get ( "access_token" ) || "" ;
62+ const refresh = params . get ( "refresh_token" ) || undefined ;
63+ if ( ! access ) return ;
64+
65+ const base = window . location . origin ; // assume same origin the user entered for SSO
7166 ( async ( ) => {
7267 try {
73- await loginWithTokens ( base , {
74- access_token : data . access_token ,
75- refresh_token : data . refresh_token ,
76- } ) ;
77- // Clean URL (remove tokens) then navigate
78- window . history . replaceState ( { } , document . title , base + "/login" ) ;
68+ await loginWithTokens ( base , { access_token : access , refresh_token : refresh } ) ;
69+ // Scrub sensitive tokens from URL: go to /login (or /library directly after navigation) without query/hash.
70+ const cleanUrl = base + "/login" ;
71+ window . history . replaceState ( { } , document . title , cleanUrl ) ;
7972 navigate ( "/library" , { replace : true } ) ;
8073 } catch {
81- // ignore - error shown via context
74+ // ignore - context will show error
8275 }
8376 } ) ( ) ;
8477 } catch {
85- // ignore parsing errors
78+ // swallow parsing errors silently
8679 }
8780 } , [ loginWithTokens , navigate ] ) ;
8881
0 commit comments