From 80d18ee90d71127e7cdaf2e8bfe98618d9501246 Mon Sep 17 00:00:00 2001 From: Greg <2653109+glinton@users.noreply.github.com> Date: Thu, 13 Feb 2020 11:37:41 -0700 Subject: [PATCH] feat: add flag to redirect login page to specified OAuth IdP (#5380) Co-Authored-By: Bucky Schwarz <hoorayimhelping@users.noreply.github.com> --- CHANGELOG.md | 1 + server/mux.go | 6 ++++-- server/routes.go | 11 ++++++----- server/routes_test.go | 2 +- server/server.go | 3 +++ ui/src/auth/Login.js | 4 ++++ 6 files changed, 19 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61bca4b34..76ae06086 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ 1. [#5367](https://github.com/influxdata/chronograf/pull/5367): Template variables can now select their source database 1. [#5362](https://github.com/influxdata/chronograf/pull/5362): Add migrate command to chronoctl 1. [#5308](https://github.com/influxdata/chronograf/pull/5308): The hosts page can be disabled by setting the new environment variable `HOST_PAGE_DISABLED` to `true`, or by passing in `--host-page-disabled` or `-H` flags +1. [#5380](https://github.com/influxdata/chronograf/pull/5380): Add ability to redirect OAuth login page to OAuth IdP via flag `--redir-auth-login` or environmtent variable `REDIR_AUTH_LOGIN` 1. [#5383](https://github.com/influxdata/chronograf/pull/5383): Add support for 64-bit arm processors ### Other diff --git a/server/mux.go b/server/mux.go index b9579ae09..343b5e63c 100644 --- a/server/mux.go +++ b/server/mux.go @@ -29,6 +29,7 @@ type MuxOpts struct { Develop bool // Develop loads assets from filesystem instead of bindata Basepath string // URL path prefix under which all chronograf routes will be mounted UseAuth bool // UseAuth turns on Github OAuth and JWT + RedirAuth string // RedirAuth specifies which auth to redirect login. Auth oauth2.Authenticator // Auth is used to authenticate and authorize ProviderFuncs []func(func(oauth2.Provider, oauth2.Mux)) StatusFeedURL string // JSON Feed URL for the client Status page News Feed @@ -392,8 +393,9 @@ func AuthAPI(opts MuxOpts, router chronograf.Router) (http.Handler, AuthRoutes) router.Handler("GET", logoutPath, m.Logout()) router.Handler("GET", callbackPath, m.Callback()) routes = append(routes, AuthRoute{ - Name: p.Name(), - Label: strings.Title(p.Name()), + Name: p.Name(), + Label: strings.Title(p.Name()), + RedirectLogin: p.Name() == opts.RedirAuth, // AuthRoutes are content served to the page. When Basepath is set, it // says that all content served to the page will be prefixed with the // basepath. Since these routes are consumed by JS, it will need the diff --git a/server/routes.go b/server/routes.go index 085bfcdb5..1fa70385c 100644 --- a/server/routes.go +++ b/server/routes.go @@ -10,11 +10,12 @@ import ( // AuthRoute are the routes for each type of OAuth2 provider type AuthRoute struct { - Name string `json:"name"` // Name uniquely identifies the provider - Label string `json:"label"` // Label is a user-facing string to present in the UI - Login string `json:"login"` // Login is the route to the login redirect path - Logout string `json:"logout"` // Logout is the route to the logout redirect path - Callback string `json:"callback"` // Callback is the route the provider calls to exchange the code/state + Name string `json:"name"` // Name uniquely identifies the provider + Label string `json:"label"` // Label is a user-facing string to present in the UI + Login string `json:"login"` // Login is the route to the login redirect path + Logout string `json:"logout"` // Logout is the route to the logout redirect path + Callback string `json:"callback"` // Callback is the route the provider calls to exchange the code/state + RedirectLogin bool `json:"redirectLogin"` // RedirectLogin tells the ui to redirect to this auth's login. } // AuthRoutes contains all OAuth2 provider routes. diff --git a/server/routes_test.go b/server/routes_test.go index e82c62f0c..64e14ad09 100644 --- a/server/routes_test.go +++ b/server/routes_test.go @@ -73,7 +73,7 @@ func TestAllRoutesWithAuth(t *testing.T) { if err := json.Unmarshal(body, &routes); err != nil { t.Error("TestAllRoutesWithAuth not able to unmarshal JSON response") } - want := `{"protoboards":"/chronograf/v1/protoboards","orgConfig":{"self":"/chronograf/v1/org_config","logViewer":"/chronograf/v1/org_config/logviewer"},"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/organizations/default/users","allUsers":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","environment":"/chronograf/v1/env","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":[{"name":"github","label":"GitHub","login":"/oauth/github/login","logout":"/oauth/github/logout","callback":"/oauth/github/callback"}],"logout":"/oauth/logout","external":{"statusFeed":""},"flux":{"ast":"/chronograf/v1/flux/ast","self":"/chronograf/v1/flux","suggestions":"/chronograf/v1/flux/suggestions"},"validateTextTemplates":"chronograf/v1/validate_text_templates"} + want := `{"protoboards":"/chronograf/v1/protoboards","orgConfig":{"self":"/chronograf/v1/org_config","logViewer":"/chronograf/v1/org_config/logviewer"},"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/organizations/default/users","allUsers":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","environment":"/chronograf/v1/env","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":[{"name":"github","redirectLogin":false,"label":"GitHub","login":"/oauth/github/login","logout":"/oauth/github/logout","callback":"/oauth/github/callback"}],"logout":"/oauth/logout","external":{"statusFeed":""},"flux":{"ast":"/chronograf/v1/flux/ast","self":"/chronograf/v1/flux","suggestions":"/chronograf/v1/flux/suggestions"},"validateTextTemplates":"chronograf/v1/validate_text_templates"} ` eq, err := jsonEqual(want, string(body)) if err != nil { diff --git a/server/server.go b/server/server.go index 519d10079..e4fad4bc1 100644 --- a/server/server.go +++ b/server/server.go @@ -101,6 +101,8 @@ type Server struct { Auth0Organizations []string `long:"auth0-organizations" description:"Auth0 organizations permitted to access Chronograf (comma separated)" env:"AUTH0_ORGS" env-delim:","` Auth0SuperAdminOrg string `long:"auth0-superadmin-org" description:"Auth0 organization from which users are automatically granted SuperAdmin status" env:"AUTH0_SUPERADMIN_ORG"` + RedirAuth string `long:"redir-auth-login" description:"Automatically redirect login to specified OAuth provider." env:"REDIR_AUTH_LOGIN"` + StatusFeedURL string `long:"status-feed-url" description:"URL of a JSON Feed to display as a News Feed on the client Status page." default:"https://influxdata.com/feed/json" env:"STATUS_FEED_URL"` CustomLinks map[string]string `long:"custom-link" description:"Custom link to be added to the client User menu. Multiple links can be added by using multiple of the same flag with different 'name:url' values, or as an environment variable with comma-separated 'name:url' values. E.g. via flags: '--custom-link=InfluxData:https://www.influxdata.com --custom-link=Chronograf:https://github.com/influxdata/chronograf'. E.g. via environment variable: 'export CUSTOM_LINKS=InfluxData:https://www.influxdata.com,Chronograf:https://github.com/influxdata/chronograf'" env:"CUSTOM_LINKS" env-delim:","` TelegrafSystemInterval time.Duration `long:"telegraf-system-interval" default:"1m" description:"Duration used in the GROUP BY time interval for the hosts list" env:"TELEGRAF_SYSTEM_INTERVAL"` @@ -403,6 +405,7 @@ func (s *Server) Serve(ctx context.Context) { Auth: auth, Logger: logger, UseAuth: s.useAuth(), + RedirAuth: s.RedirAuth, ProviderFuncs: providerFuncs, Basepath: s.Basepath, StatusFeedURL: s.StatusFeedURL, diff --git a/ui/src/auth/Login.js b/ui/src/auth/Login.js index b1f99891f..8824458a3 100644 --- a/ui/src/auth/Login.js +++ b/ui/src/auth/Login.js @@ -9,6 +9,10 @@ import SplashPage from 'shared/components/SplashPage' const VERSION = process.env.npm_package_version const Login = ({authData: {auth}}) => { + if (Array.isArray(auth.links) && auth.links.length === 1 && auth.links[0].redirectLogin) { + window.location.href = auth.links[0].login + } + if (auth.isAuthLoading) { return <PageSpinner /> }