From 080e1dd74ed08535c3c1e6eaba5326f8266db4f5 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 21 Jan 2020 12:58:55 +0300 Subject: [PATCH 1/2] * auth: respond with 403 for API requests when not authenticated --- AGHTechDoc.md | 4 +++- home/auth.go | 9 +++++++-- home/home_test.go | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index 6e99cbaa..8d1de3d7 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1353,7 +1353,9 @@ Response: ## Log-in page -After user completes the steps of installation wizard, he must log in into dashboard using his name and password. After user successfully logs in, he gets the Cookie which allows the server to authenticate him next time without password. After the Cookie is expired, user needs to perform log-in operation again. All requests without a proper Cookie get redirected to Log-In page with prompt for name and password. +After user completes the steps of installation wizard, he must log in into dashboard using his name and password. After user successfully logs in, he gets the Cookie which allows the server to authenticate him next time without password. After the Cookie is expired, user needs to perform log-in operation again. + +Requests to / or /index.html without a proper Cookie get redirected to Log-In page with prompt for name and password. The server responds with 403 to all other requests (including all API methods) without a proper Cookie. YAML configuration: diff --git a/home/auth.go b/home/auth.go index e074e414..aae40f33 100644 --- a/home/auth.go +++ b/home/auth.go @@ -406,8 +406,13 @@ func optionalAuth(handler func(http.ResponseWriter, *http.Request)) func(http.Re } } if !ok { - w.Header().Set("Location", "/login.html") - w.WriteHeader(http.StatusFound) + if r.URL.Path == "/" || r.URL.Path == "/index.html" { + w.Header().Set("Location", "/login.html") + w.WriteHeader(http.StatusFound) + } else { + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte("Forbidden")) + } return } } diff --git a/home/home_test.go b/home/home_test.go index 315797b0..771c74d0 100644 --- a/home/home_test.go +++ b/home/home_test.go @@ -114,6 +114,7 @@ func TestHome(t *testing.T) { assert.True(t, ioutil.WriteFile(fn, []byte(yamlConf), 0644) == nil) fn, _ = filepath.Abs(fn) + config = configuration{} // the global variable is dirty because of the previous tests run args := options{} args.configFilename = fn args.workDir = dir From 447080b422f929025454aaa1bc0ab4a6c8abcbd9 Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Tue, 21 Jan 2020 16:57:51 +0300 Subject: [PATCH 2/2] + client: handle 403 status --- client/src/api/Api.js | 7 +++++++ client/src/helpers/constants.js | 1 + 2 files changed, 8 insertions(+) diff --git a/client/src/api/Api.js b/client/src/api/Api.js index d8fed5ce..3d215144 100644 --- a/client/src/api/Api.js +++ b/client/src/api/Api.js @@ -1,6 +1,7 @@ import axios from 'axios'; import { getPathWithQueryString } from '../helpers/helpers'; +import { R_PATH_LAST_PART } from '../helpers/constants'; class Api { baseUrl = 'control'; @@ -17,6 +18,12 @@ class Api { console.error(error); const errorPath = `${this.baseUrl}/${path}`; if (error.response) { + if (error.response.status === 403) { + const loginPageUrl = window.location.href.replace(R_PATH_LAST_PART, '/login.html'); + window.location.replace(loginPageUrl); + return false; + } + throw new Error(`${errorPath} | ${error.response.data} | ${error.response.status}`); } throw new Error(`${errorPath} | ${error.message ? error.message : error}`); diff --git a/client/src/helpers/constants.js b/client/src/helpers/constants.js index f186bfaa..d015eec6 100644 --- a/client/src/helpers/constants.js +++ b/client/src/helpers/constants.js @@ -4,6 +4,7 @@ export const R_IPV4 = /^(?:(?:^|\.)(?:2(?:5[0-5]|[0-4]\d)|1?\d?\d)){4}$/; export const R_IPV6 = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/; export const R_CIDR = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$/; export const R_MAC = /^((([a-fA-F0-9][a-fA-F0-9]+[-]){5}|([a-fA-F0-9][a-fA-F0-9]+[:]){5})([a-fA-F0-9][a-fA-F0-9])$)|(^([a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9]+[.]){2}([a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9]))$/; +export const R_PATH_LAST_PART = /\/[^/]*$/; export const STATS_NAMES = { avg_processing_time: 'average_processing_time',