@@ -12,7 +12,7 @@ import ThemeSwitch from "./ThemeSwitch";
1212import { RegisterUserDtoFromJSON } from "../api" ;
1313
1414export function Login ( ) {
15- const { loginBasic, loading, error } = useAuth ( ) ;
15+ const { loginBasic, loginWithTokens , loading, error } = useAuth ( ) ;
1616 const navigate = useNavigate ( ) ;
1717 const [ server , setServer ] = useState ( window . location . origin ) ;
1818 const [ username , setUsername ] = useState ( "" ) ;
@@ -42,6 +42,50 @@ export function Login() {
4242 return s ;
4343 } , [ ] ) ;
4444
45+ // Parse SSO redirect style: {server}/access_token=...&refresh_token=...
46+ 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.
49+ try {
50+ const loc = window . location ;
51+ const path = loc . pathname . startsWith ( "/" )
52+ ? loc . pathname . slice ( 1 )
53+ : loc . pathname ;
54+ 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 ;
71+ ( async ( ) => {
72+ 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" ) ;
79+ navigate ( "/library" , { replace : true } ) ;
80+ } catch {
81+ // ignore - error shown via context
82+ }
83+ } ) ( ) ;
84+ } catch {
85+ // ignore parsing errors
86+ }
87+ } , [ loginWithTokens , navigate ] ) ;
88+
4589 const onSubmit = async ( e : FormEvent ) => {
4690 e . preventDefault ( ) ;
4791 try {
0 commit comments