diff --git a/client/web/src/api.ts b/client/web/src/api.ts index b922eb858..f0d46980b 100644 --- a/client/web/src/api.ts +++ b/client/web/src/api.ts @@ -1,4 +1,5 @@ let csrfToken: string +let synoToken: string | undefined // required for synology API requests let unraidCsrfToken: string | undefined // required for unraid POST requests (#8062) // apiFetch wraps the standard JS fetch function with csrf header @@ -15,9 +16,13 @@ export function apiFetch( ): Promise { const urlParams = new URLSearchParams(window.location.search) const nextParams = new URLSearchParams(params) - const token = urlParams.get("SynoToken") - if (token) { - nextParams.set("SynoToken", token) + if (synoToken) { + nextParams.set("SynoToken", synoToken) + } else { + const token = urlParams.get("SynoToken") + if (token) { + nextParams.set("SynoToken", token) + } } const search = nextParams.toString() const url = `api${endpoint}${search ? `?${search}` : ""}` @@ -62,6 +67,10 @@ function updateCsrfToken(r: Response) { } } +export function setSynoToken(token?: string) { + synoToken = token +} + export function setUnraidCsrfToken(token?: string) { unraidCsrfToken = token } diff --git a/client/web/src/hooks/auth.ts b/client/web/src/hooks/auth.ts index 1fa26aec5..238049288 100644 --- a/client/web/src/hooks/auth.ts +++ b/client/web/src/hooks/auth.ts @@ -1,9 +1,15 @@ import { useCallback, useEffect, useState } from "react" -import { apiFetch } from "src/api" +import { apiFetch, setSynoToken } from "src/api" + +export enum AuthType { + synology = "synology", + tailscale = "tailscale", +} export type AuthResponse = { ok: boolean authUrl?: string + authNeeded?: AuthType } // useAuth reports and refreshes Tailscale auth status @@ -18,6 +24,14 @@ export default function useAuth() { return apiFetch(url, "GET") .then((r) => r.json()) .then((d) => { + if ((d as AuthResponse).authNeeded == AuthType.synology) { + fetch("/webman/login.cgi") + .then((r) => r.json()) + .then((data) => { + setSynoToken(data.SynoToken) + }) + } + setLoading(false) setData(d) }) diff --git a/client/web/web.go b/client/web/web.go index 849d1c519..b836c2ca2 100644 --- a/client/web/web.go +++ b/client/web/web.go @@ -269,9 +269,17 @@ func (s *Server) serveLoginAPI(w http.ResponseWriter, r *http.Request) { return } +type authType string + +var ( + synoAuth authType = "synology" // user needs a SynoToken for subsequent API calls + tailscaleAuth authType = "tailscale" // user needs to complete Tailscale check mode +) + type authResponse struct { - OK bool `json:"ok"` // true when user has valid auth session - AuthURL string `json:"authUrl,omitempty"` // filled when user has control auth action to take + OK bool `json:"ok"` // true when user has valid auth session + AuthURL string `json:"authUrl,omitempty"` // filled when user has control auth action to take + AuthNeeded authType `json:"authNeeded,omitempty"` // filled when user needs to complete a specific type of auth } func (s *Server) serveTailscaleAuth(w http.ResponseWriter, r *http.Request) {