Fix provider authorization ui error handling (#24250)

This commit is contained in:
Michael Geers 2025-10-09 09:39:08 +02:00 • committed by GitHub
parent 21682e7619
commit f67e8f901a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 48 additions and 24 deletions

View file

@ -219,19 +219,32 @@ export default defineComponent({
const { title, authenticated, loginPath, logoutPath } = provider;
if (!authenticated) {
try {
const response = await baseAPI.get(loginPath);
window.location.href = response.data.loginUri;
const response = await baseAPI.get(loginPath, {
validateStatus: (code) => [200, 400].includes(code),
});
if (response.status === 200) {
window.open(response.data?.loginUri, "_blank");
} else {
alert(`Failed to login: ${response.data?.error}`);
}
} catch (error: any) {
console.error(error);
alert(`Failed to login: ${error.response?.data}`);
alert("Unexpected login error: " + error.message);
}
} else {
if (window.confirm(this.$t("header.authProviders.confirmLogout", { title }))) {
try {
await baseAPI.get(logoutPath);
const response = await baseAPI.get(logoutPath, {
validateStatus: (code) => [200, 400, 500].includes(code),
});
if (response.status === 200) {
alert(this.$t("header.authProviders.loggedOut"));
} else {
alert(`Failed to logout: ${response.data?.error}`);
}
} catch (error: any) {
console.error(error);
alert(`Failed to logout: ${error.response?.data}`);
alert(`Unexpected logout error: ${error.response?.data}`);
}
}
}

View file

@ -658,6 +658,7 @@
"about": "Über",
"authProviders": {
"confirmLogout": "Sicher, dass du {title} trennen möchtest?",
"loggedOut": "Erfolgreich abgemeldet",
"title": "Autorisierungsstatus"
},
"blog": "Blog",

View file

@ -658,6 +658,7 @@
"about": "About",
"authProviders": {
"confirmLogout": "Are you sure you want to disconnect {title}?",
"loggedOut": "Successfully logged out",
"title": "Authorization Status"
},
"blog": "Blog",

View file

@ -13,6 +13,26 @@ import (
"github.com/evcc-io/evcc/util"
)
type errorResponse struct {
Error string `json:"error"`
}
type loginResponse struct {
LoginUri string `json:"loginUri"`
}
// jsonWrite writes a JSON response
func jsonWrite(w http.ResponseWriter, data interface{}) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)
}
// jsonError writes an error response
func jsonError(w http.ResponseWriter, status int, message string) {
w.WriteHeader(status)
jsonWrite(w, errorResponse{Error: message})
}
// Handler manages a dynamic map of routes for handling the redirect during
// OAuth authentication. When a route is registered a token OAuth state is returned.
// On GET request the generic handler identifies route and target handler
@ -70,8 +90,7 @@ func (a *Handler) handleLogin(w http.ResponseWriter, r *http.Request) {
provider, ok := a.providers[id]
if !ok {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintln(w, "invalid id")
jsonError(w, http.StatusBadRequest, "invalid id")
return
}
@ -89,23 +108,11 @@ func (a *Handler) handleLogin(w http.ResponseWriter, r *http.Request) {
uri, err := provider.Login(encryptedState)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "error: %v", err)
jsonError(w, http.StatusBadRequest, err.Error())
return
}
// return authorization URL
res := struct {
LoginUri string `json:"loginUri"`
}{
LoginUri: uri,
}
if err := json.NewEncoder(w).Encode(res); err != nil {
a.log.ERROR.Printf("failed to encode login URI response: %v", err)
}
w.WriteHeader(http.StatusFound)
jsonWrite(w, loginResponse{LoginUri: uri})
}
func (a *Handler) handleLogout(w http.ResponseWriter, r *http.Request) {
@ -117,17 +124,18 @@ func (a *Handler) handleLogout(w http.ResponseWriter, r *http.Request) {
provider, ok := a.providers[id]
if !ok {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintln(w, "invalid id")
jsonError(w, http.StatusBadRequest, "invalid id")
return
}
// Handle logout
if err := provider.Logout(); err != nil {
a.log.ERROR.Printf("logout for provider %s failed: %v", id, err)
jsonError(w, http.StatusInternalServerError, "logout failed")
return
}
http.Redirect(w, r, "/", http.StatusFound)
jsonWrite(w, "OK")
}
func (a *Handler) handleCallback(w http.ResponseWriter, r *http.Request) {

View file

@ -24,6 +24,7 @@ export default defineConfig({
proxy: {
"/api": "http://localhost:7070",
"/i18n": "http://localhost:7070",
"/providerauth": "http://localhost:7070",
"/ws": { target: "ws://localhost:7070", ws: true },
},
},