Skip to content

Commit

Permalink
Implement inactivity timeout for logging user out
Browse files Browse the repository at this point in the history
  • Loading branch information
jhadvig committed Jul 28, 2020
1 parent 68f03f0 commit 26a9247
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 5 deletions.
15 changes: 14 additions & 1 deletion cmd/bridge/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ func main() {
fUserAuthOIDCClientSecretFile := fs.String("user-auth-oidc-client-secret-file", "", "File containing the OIDC OAuth2 Client Secret.")
fUserAuthLogoutRedirect := fs.String("user-auth-logout-redirect", "", "Optional redirect URL on logout needed for some single sign-on identity providers.")

fInactivityTimeout := fs.Int("inactivity-timeout", 0, "Number of seconds, after which user will be logged out if inactive. Ignored if less than 300 seconds (5 minutes).")

fK8sMode := fs.String("k8s-mode", "in-cluster", "in-cluster | off-cluster")
fK8sModeOffClusterEndpoint := fs.String("k8s-mode-off-cluster-endpoint", "", "URL of the Kubernetes API server.")
fK8sModeOffClusterSkipVerifyTLS := fs.Bool("k8s-mode-off-cluster-skip-verify-tls", false, "DEV ONLY. When true, skip verification of certs presented by k8s API server.")
Expand Down Expand Up @@ -204,6 +206,16 @@ func main() {
}
}

if *fInactivityTimeout < 300 {
log.Warning("Flag inactivity-timeout is set to less then 300 seconds and will be ignored!")
} else {
if *fK8sAuth != "oidc" && *fK8sAuth != "openshift" {
fmt.Fprintln(os.Stderr, "In order activate the user inactivity timout, flag --user-auth must be one of: oidc, openshift")
os.Exit(1)
}
log.Infof("Setting user inactivity timout to %d seconds", *fInactivityTimeout)
}

srv := &server.Server{
PublicDir: *fPublicDir,
BaseURL: baseURL,
Expand All @@ -218,6 +230,7 @@ func main() {
PrometheusPublicURL: prometheusPublicURL,
ThanosPublicURL: thanosPublicURL,
LoadTestFactor: *fLoadTestFactor,
InactivityTimeout: *fInactivityTimeout,
}

// if !in-cluster (dev) we should not pass these values to the frontend
Expand Down Expand Up @@ -510,7 +523,7 @@ func main() {
case "disabled":
log.Warningf("running with AUTHENTICATION DISABLED!")
default:
bridge.FlagFatalf("user-auth", "must be one of: oidc, disabled")
bridge.FlagFatalf("user-auth", "must be one of: oidc, openshift, disabled")
}

var resourceListerToken string
Expand Down
30 changes: 30 additions & 0 deletions frontend/public/components/masthead-toolbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,19 @@ class MastheadToolbarContents_ extends React.Component {
this._onHelpDropdownToggle = this._onHelpDropdownToggle.bind(this);
this._onAboutModal = this._onAboutModal.bind(this);
this._closeAboutModal = this._closeAboutModal.bind(this);
this._onInactivityTimeout = this._onInactivityTimeout.bind(this);
this.userInctivityTimeout = null;
}

componentDidMount() {
if (window.SERVER_FLAGS.statuspageID) {
this._getStatuspageData(window.SERVER_FLAGS.statuspageID);
}
// Ignore inactivity-timeout if set to less then 300 seconds
if (window.SERVER_FLAGS.inactivityTimeout >= 300) {
window.addEventListener('click', _.throttle(this._onInactivityTimeout, 500));
window.addEventListener('keydown', _.throttle(this._onInactivityTimeout, 500));
}
this._updateUser();
}

Expand All @@ -98,6 +105,29 @@ class MastheadToolbarContents_ extends React.Component {
}
}

componentWillUnmount() {
window.removeEventListener('click', this._onInactivityTimeout);
window.removeEventListener('keydown', this._onInactivityTimeout);
clearTimeout(this.userInctivityTimeout);
}

_onInactivityTimeout() {
const { flags, user } = this.props;

if (flagPending(flags[FLAGS.OPENSHIFT]) || !user) {
return;
}

clearTimeout(this.userInctivityTimeout);
this.userInctivityTimeout = setTimeout(() => {
if (flags[FLAGS.OPENSHIFT]) {
authSvc.logoutOpenShift(user?.metadata?.name === 'kube:admin');
} else {
authSvc.logout();
}
}, window.SERVER_FLAGS.inactivityTimeout * 1000);
}

_getStatuspageData(statuspageID) {
fetch(`https://${statuspageID}.statuspage.io/api/v2/summary.json`, {
headers: { Accept: 'application/json' },
Expand Down
1 change: 1 addition & 0 deletions frontend/public/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ declare interface Window {
grafanaPublicURL: string;
prometheusPublicURL: string;
thanosPublicURL: string;
inactivityTimeout: number;
statuspageID: string;
GOARCH: string;
GOOS: string;
Expand Down
3 changes: 3 additions & 0 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ type jsGlobals struct {
PrometheusPublicURL string `json:"prometheusPublicURL"`
ThanosPublicURL string `json:"thanosPublicURL"`
LoadTestFactor int `json:"loadTestFactor"`
InactivityTimeout int `json:"inactivityTimeout"`
GOARCH string `json:"GOARCH"`
GOOS string `json:"GOOS"`
GraphQLBaseURL string `json:"graphqlBaseURL"`
Expand All @@ -102,6 +103,7 @@ type Server struct {
StatuspageID string
LoadTestFactor int
DexClient api.DexClient
InactivityTimeout int
// A client with the correct TLS setup for communicating with the API server.
K8sClient *http.Client
ThanosProxyConfig *proxy.Config
Expand Down Expand Up @@ -430,6 +432,7 @@ func (s *Server) indexHandler(w http.ResponseWriter, r *http.Request) {
Branding: s.Branding,
CustomProductName: s.CustomProductName,
StatuspageID: s.StatuspageID,
InactivityTimeout: s.InactivityTimeout,
DocumentationBaseURL: s.DocumentationBaseURL.String(),
AlertManagerPublicURL: s.AlertManagerPublicURL.String(),
GrafanaPublicURL: s.GrafanaPublicURL.String(),
Expand Down
4 changes: 4 additions & 0 deletions pkg/serverconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ func addAuth(fs *flag.FlagSet, auth *Auth) {
if auth.LogoutRedirect != "" {
fs.Set("user-auth-logout-redirect", auth.LogoutRedirect)
}

if auth.InactivityTimeoutSeconds != 0 {
fs.Set("inactivity-timeout", strconv.Itoa(auth.InactivityTimeoutSeconds))
}
}

func addProviders(fs *flag.FlagSet, providers *Providers) {
Expand Down
9 changes: 5 additions & 4 deletions pkg/serverconfig/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ type ClusterInfo struct {

// Auth holds configuration for authenticating with OpenShift. The auth method is assumed to be "openshift".
type Auth struct {
ClientID string `yaml:"clientID,omitempty"`
ClientSecretFile string `yaml:"clientSecretFile,omitempty"`
OAuthEndpointCAFile string `yaml:"oauthEndpointCAFile,omitempty"`
LogoutRedirect string `yaml:"logoutRedirect,omitempty"`
ClientID string `yaml:"clientID,omitempty"`
ClientSecretFile string `yaml:"clientSecretFile,omitempty"`
OAuthEndpointCAFile string `yaml:"oauthEndpointCAFile,omitempty"`
LogoutRedirect string `yaml:"logoutRedirect,omitempty"`
InactivityTimeoutSeconds int `yaml:"inactivityTimeoutSeconds,omitempty"`
}

// Customization holds configuration such as what logo to use.
Expand Down

0 comments on commit 26a9247

Please sign in to comment.