Merge branch '17829-remove-omniauth' refs #17829
authorPeter Amstutz <peter.amstutz@curii.com>
Mon, 28 Jun 2021 16:17:39 +0000 (12:17 -0400)
committerPeter Amstutz <peter.amstutz@curii.com>
Mon, 28 Jun 2021 16:17:39 +0000 (12:17 -0400)
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz@curii.com>

30 files changed:
apps/workbench/test/integration/logins_test.rb
doc/_config.yml
doc/api/tokens_sso.html.textile.liquid [deleted file]
lib/config/config.default.yml
lib/config/deprecated.go
lib/config/export.go
lib/config/generated_config.go
lib/controller/handler_test.go
lib/controller/localdb/login.go
lib/controller/localdb/login_oidc_test.go
lib/controller/rpc/conn_test.go
sdk/go/arvados/config.go
sdk/python/tests/run_test_server.py
services/api/Gemfile
services/api/Gemfile.lock
services/api/app/assets/stylesheets/application.css
services/api/app/controllers/application_controller.rb
services/api/app/controllers/user_sessions_controller.rb
services/api/app/views/layouts/application.html.erb
services/api/app/views/static/intro.html.erb
services/api/app/views/static/login_failure.html.erb
services/api/app/views/user_sessions/failure.html.erb
services/api/config/arvados_config.rb
services/api/config/environment.rb
services/api/config/initializers/omniauth_init.rb [deleted file]
services/api/lib/josh_id.rb [deleted file]
services/api/test/functional/user_sessions_controller_test.rb
services/api/test/integration/login_workflow_test.rb
services/api/test/integration/user_sessions_test.rb
services/api/test/test_helper.rb

index f079fbb8f1ce39eb4d88e33f232c3f8796dce89c..3c6ab7c7436e1ddb06621a01136ba85673ec78f2 100644 (file)
@@ -17,10 +17,7 @@ class LoginsTest < ActionDispatch::IntegrationTest
 
   test "trying to use expired token redirects to login page" do
     visit page_with_token('expired_trustedclient')
-    buttons = all("a.btn", text: /Log in/)
+    buttons = all("button.btn", text: /Log in/)
     assert_equal(1, buttons.size, "Failed to find one login button")
-    login_link = buttons.first[:href]
-    assert_match(%r{//[^/]+/login}, login_link)
-    assert_no_match(/\bapi_token=/, login_link)
   end
 end
index 55987c062fad7666e4541477b60584788fc7027f..06d15952131f118d1d7b79c2e80a97032ee5d3d5 100644 (file)
@@ -113,7 +113,6 @@ navbar:
       - api/requests.html.textile.liquid
       - api/methods.html.textile.liquid
       - api/resources.html.textile.liquid
-      - api/tokens_sso.html.textile.liquid
     - Permission and authentication:
       - api/methods/api_client_authorizations.html.textile.liquid
       - api/methods/api_clients.html.textile.liquid
diff --git a/doc/api/tokens_sso.html.textile.liquid b/doc/api/tokens_sso.html.textile.liquid
deleted file mode 100644 (file)
index 5d52465..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
----
-layout: default
-navsection: api
-title: API Authorization with SSO (deprecated)
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This page describes the deprecated login flow via the SSO server. SSO server authentication will be removed in a future Arvados release and should not be used for new installations. See "Set up web based login":{{site.baseurl}}/install/setup-login.html for more information.
-{% include 'notebox_end' %}
-
-All requests to the API server must have an API token.  API tokens can be issued by going though the login flow, or created via the API.  At this time, only browser based applications can perform login from email/password.  Command line applications and services must use an API token provided via the @ARVADOS_API_TOKEN@ environment variable or configuration file.
-
-h2. Browser login
-
-Browser based applications can perform log in via the following highlevel flow:
-
-# The web application presents a "login" link to @/login@ on the API server with a @return_to@ parameter provided in the query portion of the URL.  For example @https://{{ site.arvados_api_host }}/login?return_to=XXX@ , where  @return_to=XXX@ is the URL of the login page for the web application.
-# The "login" link takes the browser to the login page (this may involve several redirects)
-# The user logs in.  API server authenticates the user and issues a new API token.
-# The browser is redirected to the login page URL provided in @return_to=XXX@ with the addition of @?api_token=xxxxapitokenxxxx@.
-# The web application gets the login request with the included authorization token.
-
-!{{site.baseurl}}/images/Session_Establishment_with_SSO.svg!
-
-The "browser authentication process is documented in detail on the Arvados wiki.":https://dev.arvados.org/projects/arvados/wiki/Workbench_authentication_process
-
-h2. User activation
-
-"Creation and activation of new users is described here.":{{site.baseurl}}/admin/user-management.html
-
-h2. Creating tokens via the API
-
-The browser login method above issues a new token.  Using that token, it is possible to make API calls to create additional tokens.  To do so, use the @create@ method of the "API client authorizations":{{site.baseurl}}/api/methods/api_client_authorizations.html resource.
-
-h2. Trusted API clients
-
-The "api_clients":{{site.baseurl}}/api/methods/api_clients.html resource determines if web applications that have gone through the browser login flow may create or list API tokens.
-
-After the user has authenticated, but before an authorization token is issued and browser redirect sent (sending the browser back to the @return_to@ login page bearing @api_token@), the server strips the path and query portion from @return_to@ to get @url_prefix@.  The @url_prefix@ is used to find or create an ApiClient object.  The newly issued API client authorization (API token) is associated with this ApiClient object.
-
-API clients may be marked as "trusted" by making an API call to create or update an "api_clients":{{site.baseurl}}/api/methods/api_clients.html resource and set the @is_trusted@ flag to @true@. An authorization token associated with a "trusted" client is permitted to list authorization tokens on "API client authorizations":{{site.baseurl}}/api/methods/api_client_authorizations.html .
-
-A authorization token which is not associated with a trusted client may only use the @current@ method to query its own api_client_authorization object.  The "untrusted" token is forbidden performing any other operations on API client authorizations, such as listing other authorizations or creating new authorizations.
-
-Authorization tokens which are not issued via the browser login flow (created directly via the API) inherit the api client of the token used to create them.  They will always be "trusted" because untrusted API clients cannot create tokens.
-
-h2(#scopes). Scopes
-
-Scopes can restrict a token so it may only access certain resources.  This is in addition to normal permission checks for the user associated with the token.
-
-Each entry in scopes consists of a @request_method@ and @request_path@.  The @request_method@ is a HTTP method (one of @GET@, @POST@, @PATCH@ or @DELETE@) and @request_path@ is the request URI.  A given request is permitted if it matches a scopes exactly, or the scope ends with @/@ and the request string is a prefix of the scope.
-
-As a special case, a scope of @["all"]@ allows all resources.  This is the default if no scope is given.
-
-Using scopes is also described on the "Securing API access with scoped tokens":{{site.baseurl}}/admin/scoped-tokens.html page of the admin documentation.
-
-h3. Scope examples
-
-A scope of @GET /arvados/v1/collections@ permits listing collections.
-
-* Requests with different methods, such as creating a new collection using @POST /arvados/v1/collections@, will be rejected.
-* Requests to access other resources, such as @GET /arvados/v1/groups@, will be rejected.
-* Be aware that requests for specific records, such as @GET /arvados/v1/collections/962eh-4zz18-xi32mpz2621o8km@ will also be rejected.  This is because the scope @GET /arvados/v1/collections@ does not end in @/@
-
-A scope of @GET /arvados/v1/collections/@ (with @/@ suffix) will permit access to individual collections.
-
-* The request @GET /arvados/v1/collections/962eh-4zz18-xi32mpz2621o8km@ will succeed
-* Be aware that requests for listing @GET /arvados/v1/collections@ (no @/@ suffix) will be rejected, because it is not a match with the rule @GET /arvados/v1/collections/@
-* A listing request @GET /arvados/v1/collections/@ will have the trailing @/@ suffix trimmed before the scope check, as a result it will not match the rule @GET /arvados/v1/collections/@.
-
-To allow both listing objects and requesting individual objects, include both in the scope: @["GET /arvados/v1/collections", "GET /arvados/v1/collections/"]@
-
-A narrow scope such as @GET /arvados/v1/collections/962eh-4zz18-xi32mpz2621o8km@ will disallow listing objects as well as disallow requesting any object other than those listed in the scope.
index f0794a7e5320b115f1cac6b2d0f34c87cb3d7394..645da56718d6ae10bda4fb7dd366541d034a20f8 100644 (file)
@@ -52,9 +52,6 @@ Clusters:
       DispatchCloud:
         InternalURLs: {SAMPLE: {}}
         ExternalURL: "-"
-      SSO:
-        InternalURLs: {SAMPLE: {}}
-        ExternalURL: ""
       Keepproxy:
         InternalURLs: {SAMPLE: {}}
         ExternalURL: ""
@@ -555,7 +552,7 @@ Clusters:
         MaxSessions: 100
 
     Login:
-      # One of the following mechanisms (SSO, Google, PAM, LDAP, or
+      # One of the following mechanisms (Google, PAM, LDAP, or
       # LoginCluster) should be enabled; see
       # https://doc.arvados.org/install/setup-login.html
 
@@ -736,16 +733,6 @@ Clusters:
         # originally supplied by the user will be used.
         UsernameAttribute: uid
 
-      SSO:
-        # Authenticate with a separate SSO server. (Deprecated)
-        Enable: false
-
-        # ProviderAppID and ProviderAppSecret are generated during SSO
-        # setup; see
-        # https://doc.arvados.org/v2.0/install/install-sso.html#update-config
-        ProviderAppID: ""
-        ProviderAppSecret: ""
-
       Test:
         # Authenticate users listed here in the config file. This
         # feature is intended to be used in test environments, and
index 5e68bbfcefa7950163791d66a6a533bc65c19097..efc9f0837ea531872d92f551c8030e4f9241def4 100644 (file)
@@ -103,18 +103,6 @@ func (ldr *Loader) applyDeprecatedConfig(cfg *arvados.Config) error {
                        *dst = *n
                }
 
-               // Provider* moved to SSO.Provider*
-               if dst, n := &cluster.Login.SSO.ProviderAppID, dcluster.Login.ProviderAppID; n != nil && *n != *dst {
-                       *dst = *n
-                       if *n != "" {
-                               // In old config, non-empty ID meant enable
-                               cluster.Login.SSO.Enable = true
-                       }
-               }
-               if dst, n := &cluster.Login.SSO.ProviderAppSecret, dcluster.Login.ProviderAppSecret; n != nil && *n != *dst {
-                       *dst = *n
-               }
-
                cfg.Clusters[id] = cluster
        }
        return nil
index 23d0b6bffe5346426632e6ebccf0ee7b5db8a967..32a528b3c73835cef815f056d781941386a92695 100644 (file)
@@ -173,10 +173,6 @@ var whitelist = map[string]bool{
        "Login.PAM.Enable":                                    true,
        "Login.PAM.Service":                                   false,
        "Login.RemoteTokenRefresh":                            true,
-       "Login.SSO":                                           true,
-       "Login.SSO.Enable":                                    true,
-       "Login.SSO.ProviderAppID":                             false,
-       "Login.SSO.ProviderAppSecret":                         false,
        "Login.Test":                                          true,
        "Login.Test.Enable":                                   true,
        "Login.Test.Users":                                    false,
index d5e0f200b84559845450c65c36da1092b84ef5d8..1bdc269c083b00b4e3e6d273c87d5a6c97726412 100644 (file)
@@ -58,9 +58,6 @@ Clusters:
       DispatchCloud:
         InternalURLs: {SAMPLE: {}}
         ExternalURL: "-"
-      SSO:
-        InternalURLs: {SAMPLE: {}}
-        ExternalURL: ""
       Keepproxy:
         InternalURLs: {SAMPLE: {}}
         ExternalURL: ""
@@ -561,7 +558,7 @@ Clusters:
         MaxSessions: 100
 
     Login:
-      # One of the following mechanisms (SSO, Google, PAM, LDAP, or
+      # One of the following mechanisms (Google, PAM, LDAP, or
       # LoginCluster) should be enabled; see
       # https://doc.arvados.org/install/setup-login.html
 
@@ -742,16 +739,6 @@ Clusters:
         # originally supplied by the user will be used.
         UsernameAttribute: uid
 
-      SSO:
-        # Authenticate with a separate SSO server. (Deprecated)
-        Enable: false
-
-        # ProviderAppID and ProviderAppSecret are generated during SSO
-        # setup; see
-        # https://doc.arvados.org/v2.0/install/install-sso.html#update-config
-        ProviderAppID: ""
-        ProviderAppSecret: ""
-
       Test:
         # Authenticate users listed here in the config file. This
         # feature is intended to be used in test environments, and
index 2911a4f031cdac7aef14a80ecff42f349ddd0011..9b71c349a4b5624cf32cdf3eb6bba83d06d737bc 100644 (file)
@@ -164,34 +164,6 @@ func (s *HandlerSuite) TestProxyNotFound(c *check.C) {
        c.Check(jresp["errors"], check.FitsTypeOf, []interface{}{})
 }
 
-func (s *HandlerSuite) TestProxyRedirect(c *check.C) {
-       s.cluster.Login.SSO.Enable = true
-       s.cluster.Login.SSO.ProviderAppID = "test"
-       s.cluster.Login.SSO.ProviderAppSecret = "test"
-       req := httptest.NewRequest("GET", "https://0.0.0.0:1/login?return_to=foo", nil)
-       resp := httptest.NewRecorder()
-       s.handler.ServeHTTP(resp, req)
-       if !c.Check(resp.Code, check.Equals, http.StatusFound) {
-               c.Log(resp.Body.String())
-       }
-       // Old "proxy entire request" code path returns an absolute
-       // URL. New lib/controller/federation code path returns a
-       // relative URL.
-       c.Check(resp.Header().Get("Location"), check.Matches, `(https://0.0.0.0:1)?/auth/joshid\?return_to=%2Cfoo&?`)
-}
-
-func (s *HandlerSuite) TestLogoutSSO(c *check.C) {
-       s.cluster.Login.SSO.Enable = true
-       s.cluster.Login.SSO.ProviderAppID = "test"
-       req := httptest.NewRequest("GET", "https://0.0.0.0:1/logout?return_to=https://example.com/foo", nil)
-       resp := httptest.NewRecorder()
-       s.handler.ServeHTTP(resp, req)
-       if !c.Check(resp.Code, check.Equals, http.StatusFound) {
-               c.Log(resp.Body.String())
-       }
-       c.Check(resp.Header().Get("Location"), check.Equals, "http://localhost:3002/users/sign_out?"+url.Values{"redirect_uri": {"https://example.com/foo"}}.Encode())
-}
-
 func (s *HandlerSuite) TestLogoutGoogle(c *check.C) {
        s.cluster.Login.Google.Enable = true
        s.cluster.Login.Google.ClientID = "test"
index 0d6f2ef027e8500c60fdf644e8f808fecd2f226a..3c7b01baad1361735ebe37b4ef6df7157d1eb750 100644 (file)
@@ -30,15 +30,14 @@ type loginController interface {
 func chooseLoginController(cluster *arvados.Cluster, parent *Conn) loginController {
        wantGoogle := cluster.Login.Google.Enable
        wantOpenIDConnect := cluster.Login.OpenIDConnect.Enable
-       wantSSO := cluster.Login.SSO.Enable
        wantPAM := cluster.Login.PAM.Enable
        wantLDAP := cluster.Login.LDAP.Enable
        wantTest := cluster.Login.Test.Enable
        wantLoginCluster := cluster.Login.LoginCluster != "" && cluster.Login.LoginCluster != cluster.ClusterID
        switch {
-       case 1 != countTrue(wantGoogle, wantOpenIDConnect, wantSSO, wantPAM, wantLDAP, wantTest, wantLoginCluster):
+       case 1 != countTrue(wantGoogle, wantOpenIDConnect, wantPAM, wantLDAP, wantTest, wantLoginCluster):
                return errorLoginController{
-                       error: errors.New("configuration problem: exactly one of Login.Google, Login.OpenIDConnect, Login.SSO, Login.PAM, Login.LDAP, Login.Test, or Login.LoginCluster must be set"),
+                       error: errors.New("configuration problem: exactly one of Login.Google, Login.OpenIDConnect, Login.PAM, Login.LDAP, Login.Test, or Login.LoginCluster must be set"),
                }
        case wantGoogle:
                return &oidcLoginController{
@@ -66,8 +65,6 @@ func chooseLoginController(cluster *arvados.Cluster, parent *Conn) loginControll
                        AcceptAccessToken:      cluster.Login.OpenIDConnect.AcceptAccessToken,
                        AcceptAccessTokenScope: cluster.Login.OpenIDConnect.AcceptAccessTokenScope,
                }
-       case wantSSO:
-               return &ssoLoginController{Parent: parent}
        case wantPAM:
                return &pamLoginController{Cluster: cluster, Parent: parent}
        case wantLDAP:
@@ -93,20 +90,6 @@ func countTrue(vals ...bool) int {
        return n
 }
 
-// Login and Logout are passed through to the parent's railsProxy;
-// UserAuthenticate is rejected.
-type ssoLoginController struct{ Parent *Conn }
-
-func (ctrl *ssoLoginController) Login(ctx context.Context, opts arvados.LoginOptions) (arvados.LoginResponse, error) {
-       return ctrl.Parent.railsProxy.Login(ctx, opts)
-}
-func (ctrl *ssoLoginController) Logout(ctx context.Context, opts arvados.LogoutOptions) (arvados.LogoutResponse, error) {
-       return ctrl.Parent.railsProxy.Logout(ctx, opts)
-}
-func (ctrl *ssoLoginController) UserAuthenticate(ctx context.Context, opts arvados.UserAuthenticateOptions) (arvados.APIClientAuthorization, error) {
-       return arvados.APIClientAuthorization{}, httpserver.ErrorWithStatus(errors.New("username/password authentication is not available"), http.StatusBadRequest)
-}
-
 type errorLoginController struct{ error }
 
 func (ctrl errorLoginController) Login(context.Context, arvados.LoginOptions) (arvados.LoginResponse, error) {
index c9d6133c480319b9129397ea076068d67bb4a3f5..4be7d58f699c455ee67e31a206bcebfc889ed0ad 100644 (file)
@@ -63,7 +63,7 @@ func (s *OIDCLoginSuite) SetUpTest(c *check.C) {
        c.Assert(err, check.IsNil)
        s.cluster, err = cfg.GetCluster("")
        c.Assert(err, check.IsNil)
-       s.cluster.Login.SSO.Enable = false
+       s.cluster.Login.Test.Enable = false
        s.cluster.Login.Google.Enable = true
        s.cluster.Login.Google.ClientID = "test%client$id"
        s.cluster.Login.Google.ClientSecret = "test#client/secret"
index cf4dbc47673e7713e8f9d77c2ebbb449077e4447..eee8db9ac830588754956afc62806b757d72b89a 100644 (file)
@@ -50,9 +50,8 @@ func (s *RPCSuite) TestLogin(c *check.C) {
        opts := arvados.LoginOptions{
                ReturnTo: "https://foo.example.com/bar",
        }
-       resp, err := s.conn.Login(s.ctx, opts)
-       c.Check(err, check.IsNil)
-       c.Check(resp.RedirectLocation, check.Equals, "/auth/joshid?return_to="+url.QueryEscape(","+opts.ReturnTo))
+       _, err := s.conn.Login(s.ctx, opts)
+       c.Check(err.(*arvados.TransactionError).StatusCode, check.Equals, 404)
 }
 
 func (s *RPCSuite) TestLogout(c *check.C) {
@@ -62,7 +61,7 @@ func (s *RPCSuite) TestLogout(c *check.C) {
        }
        resp, err := s.conn.Logout(s.ctx, opts)
        c.Check(err, check.IsNil)
-       c.Check(resp.RedirectLocation, check.Equals, "http://localhost:3002/users/sign_out?redirect_uri="+url.QueryEscape(opts.ReturnTo))
+       c.Check(resp.RedirectLocation, check.Equals, opts.ReturnTo)
 }
 
 func (s *RPCSuite) TestCollectionCreate(c *check.C) {
index 403d501b4153af489e207fbfe4ba53e194655f78..7fdea2c74059224c0718fe60fcd099df7acb3843 100644 (file)
@@ -176,11 +176,6 @@ type Cluster struct {
                        Service            string
                        DefaultEmailDomain string
                }
-               SSO struct {
-                       Enable            bool
-                       ProviderAppID     string
-                       ProviderAppSecret string
-               }
                Test struct {
                        Enable bool
                        Users  map[string]TestUser
@@ -327,7 +322,6 @@ type Services struct {
        Keepproxy      Service
        Keepstore      Service
        RailsAPI       Service
-       SSO            Service
        WebDAVDownload Service
        WebDAV         Service
        WebShell       Service
index 917d6100ae211853d379bcc04bbd4a591f3e625f..c022e6c874d23f099406b626374e7cfe5d0951c0 100644 (file)
@@ -755,9 +755,6 @@ def setup_config():
                 "http://%s:%s"%(localhost, keep_web_dl_port): {},
             },
         },
-        "SSO": {
-            "ExternalURL": "http://localhost:3002",
-        },
     }
 
     config = {
@@ -769,10 +766,14 @@ def setup_config():
                     "RequestTimeout": "30s",
                 },
                 "Login": {
-                    "SSO": {
+                    "Test": {
                         "Enable": True,
-                        "ProviderAppID": "arvados-server",
-                        "ProviderAppSecret": "608dbf356a327e2d0d4932b60161e212c2d8d8f5e25690d7b622f850a990cd33",
+                        "Users": {
+                            "alice": {
+                                "Email": "alice@example.com",
+                                "Password": "xyzzy"
+                            }
+                        }
                     },
                 },
                 "SystemLogs": {
index 7fc7f8757c690fc7aed031b7b40977ec1ef1bc38..39ce5def17e0feddaafc04a91c7a1bfeadd997a6 100644 (file)
@@ -44,10 +44,6 @@ gem 'passenger'
 # Locking to 5.10.3 to workaround issue in 5.11.1 (https://github.com/seattlerb/minitest/issues/730)
 gem 'minitest', '5.10.3'
 
-# Restricted because omniauth >= 1.5.0 requires Ruby >= 2.1.9:
-gem 'omniauth', '~> 1.4.0'
-gem 'omniauth-oauth2', '~> 1.1'
-
 gem 'andand'
 
 gem 'optimist'
index 7a3180d2477df410db8c813df739b9351ddc542f..ddecd4a18a785281252b95155d7bcd4cde1509cc 100644 (file)
@@ -110,7 +110,6 @@ GEM
       multi_json (~> 1.11)
       os (>= 0.9, < 2.0)
       signet (~> 0.7)
-    hashie (3.6.0)
     highline (2.0.1)
     httpclient (2.8.3)
     i18n (0.9.5)
@@ -148,7 +147,6 @@ GEM
     mocha (1.8.0)
       metaclass (~> 0.0.1)
     multi_json (1.15.0)
-    multi_xml (0.6.0)
     multipart-post (2.1.1)
     net-scp (2.0.0)
       net-ssh (>= 2.6.5, < 6.0.0)
@@ -161,19 +159,7 @@ GEM
     nokogiri (1.11.7)
       mini_portile2 (~> 2.5.0)
       racc (~> 1.4)
-    oauth2 (1.4.1)
-      faraday (>= 0.8, < 0.16.0)
-      jwt (>= 1.0, < 3.0)
-      multi_json (~> 1.3)
-      multi_xml (~> 0.5)
-      rack (>= 1.2, < 3)
     oj (3.9.2)
-    omniauth (1.4.3)
-      hashie (>= 1.2, < 4)
-      rack (>= 1.6.2, < 3)
-    omniauth-oauth2 (1.5.0)
-      oauth2 (~> 1.1)
-      omniauth (~> 1.2)
     optimist (3.0.0)
     os (1.1.1)
     passenger (6.0.2)
@@ -297,8 +283,6 @@ DEPENDENCIES
   mocha
   multi_json
   oj
-  omniauth (~> 1.4.0)
-  omniauth-oauth2 (~> 1.1)
   optimist
   passenger
   pg (~> 1.0)
index 721ff801c91c5aba35337fbd7a8efab7729d9f14..18895f6efc275cc019a5788ed9bbb6c3d88cf18c 100644 (file)
@@ -62,7 +62,7 @@ div#header span.beta > span {
     border-bottom: 1px solid #fff;
     font-size: 0.8em;
 }
-img.curoverse-logo {
+img.arvados-logo {
     height: 66px;
 }
 #intropage {
index e1ae76ed29f7e6d58862f7d1bffd464c63644a93..fc33dde4477b45d059db2cbd7a63f919eb67e167 100644 (file)
@@ -397,7 +397,7 @@ class ApplicationController < ActionController::Base
     if not current_user
       respond_to do |format|
         format.json { send_error("Not logged in", status: 401) }
-        format.html { redirect_to '/auth/joshid' }
+        format.html { redirect_to '/login' }
       end
       false
     end
index 8e9a26b7a88f3207c4ab1cb76f2aba990d6cce9c..ae34fa76006aabe6c7866cee09d8249f58254567 100644 (file)
@@ -11,7 +11,7 @@ class UserSessionsController < ApplicationController
 
   respond_to :html
 
-  # omniauth callback method
+  # create a new session
   def create
     if !Rails.configuration.Login.LoginCluster.empty? and Rails.configuration.Login.LoginCluster != Rails.configuration.ClusterID
       raise "Local login disabled when LoginCluster is set"
@@ -27,9 +27,7 @@ class UserSessionsController < ApplicationController
       authinfo = SafeJSON.load(params[:auth_info])
       max_expires_at = authinfo["expires_at"]
     else
-      # omniauth middleware verified the user and is passing auth_info
-      # in request.env.
-      authinfo = request.env['omniauth.auth']['info'].with_indifferent_access
+      return send_error "Legacy code path no longer supported", status: 404
     end
 
     if !authinfo['user_uuid'].blank?
@@ -92,19 +90,17 @@ class UserSessionsController < ApplicationController
     flash[:notice] = params[:message]
   end
 
-  # logout - Clear our rack session BUT essentially redirect to the provider
-  # to clean up the Devise session from there too !
+  # logout - this gets intercepted by controller, so this is probably
+  # mostly dead code at this point.
   def logout
     session[:user_id] = nil
 
     flash[:notice] = 'You have logged off'
     return_to = params[:return_to] || root_url
-    redirect_to "#{Rails.configuration.Services.SSO.ExternalURL}users/sign_out?redirect_uri=#{CGI.escape return_to}"
+    redirect_to return_to
   end
 
-  # login - Just bounce to /auth/joshid. The only purpose of this function is
-  # to save the return_to parameter (if it exists; see the application
-  # controller). /auth/joshid bypasses the application controller.
+  # login.  Redirect to LoginCluster.
   def login
     if params[:remote] !~ /^[0-9a-z]{5}$/ && !params[:remote].nil?
       return send_error 'Invalid remote cluster id', status: 400
@@ -136,13 +132,7 @@ class UserSessionsController < ApplicationController
       p << "return_to=#{CGI.escape(params[:return_to])}" if params[:return_to]
       redirect_to "#{login_cluster}/login?#{p.join('&')}"
     else
-      if params[:return_to]
-        # Encode remote param inside callback's return_to, so that we'll get it on
-        # create() after login.
-        remote_param = params[:remote].nil? ? '' : params[:remote]
-        p << "return_to=#{CGI.escape(remote_param + ',' + params[:return_to])}"
-      end
-      redirect_to "/auth/joshid?#{p.join('&')}"
+      return send_error "Legacy code path no longer supported", status: 404
     end
   end
 
index a99b6f165dd74864c160df8597c06eecc15f5477..b4f60de3469cab52848badac471a9e8f25b6cb50 100644 (file)
@@ -23,8 +23,6 @@ SPDX-License-Identifier: AGPL-3.0 %>
     <% end %>
     &nbsp;&bull;&nbsp;
     <a class="logout" href="/logout">Log out</a>
-    <% else %>
-      <!--<a class="logout" href="/auth/joshid">Log in</a>-->
     <% end %>
 
     <% if current_user and session[:real_uid] and session[:switch_back_to] and User.find(session[:real_uid].to_i).verify_userswitch_cookie(session[:switch_back_to]) %>
@@ -41,7 +39,6 @@ SPDX-License-Identifier: AGPL-3.0 %>
 
 <% if current_user or session['invite_code'] %>
 <div id="footer">
-  <div style="float:right">Questions &rarr; <a href="mailto:arvados@curoverse.com">arvados@curoverse.com</a></div>
   <div style="clear:both"></div>
 </div>
 <% end %>
index bdefaa5c1f19bfae8357950038f328e6aa22da2c..8bab0b2ac64d8b217ffa22d0584a8e7b30e48018 100644 (file)
@@ -8,30 +8,23 @@ $(function(){
 });
 <% end %>
 <div id="intropage">
-  <img class="curoverse-logo" src="<%= asset_path('logo.png') %>" style="display:block; margin:2em auto"/>
+  <img class="arvados-logo" src="<%= asset_path('logo.png') %>" style="display:block; margin:2em auto"/>
   <div style="width:30em; margin:2em auto 0 auto">
     <h1>Welcome</h1>
-    <h4>Curoverse ARVADOS</h4>
+    <h4>ARVADOS</h4>
 
     <% if !current_user and session['invite_code'] %>
 
-    <p>Curoverse Arvados lets you manage and process human genomes and exomes.  You can start using the private beta
-    now with your Google account.</p>
+    <p>Arvados lets you manage and process biomedical data.</p>
     <p style="float:right;margin-top:1em">
-      <button class="login" href="/auth/joshid">Log in and get started</button>
+      <button class="login" href="/login">Log in and get started</button>
     </p>
 
     <% else %>
 
-    <p>Curoverse ARVADOS is transforming how researchers and
-    clinical geneticists use whole genome sequences. </p>
-    <p>If you&rsquo;re interested in learning more, we&rsquo;d love to hear
-    from you &mdash;
-    contact <a href="mailto:arvados@curoverse.com">arvados@curoverse.com</a>.</p>
-
     <% if !current_user %>
     <p style="float:right;margin-top:1em">
-      <a href="/auth/joshid">Log in here.</a>
+      <a href="/login">Log in here.</a>
     </p>
     <% end %>
 
index b3c6e70d907f4e460096ecbb06aaa6ccc7ddcd87..6b81a33e875b135a3fabdb12b458ad23386a78c3 100644 (file)
@@ -10,7 +10,7 @@ $(function(){
 
 
 <div id="intropage">
-  <img class="curoverse-logo" src="<%= asset_path('logo.png') rescue '/logo.png' %>" style="display:block; margin:2em auto"/>
+  <img class="arvados-logo" src="<%= asset_path('logo.png') rescue '/logo.png' %>" style="display:block; margin:2em auto"/>
   <div style="width:30em; margin:2em auto 0 auto">
 
     <h1>Error</h1>
index 81c5be27c642e948698b6073f201dac2e1a3522d..e8c5b0846583c9e8dfdae899cb4cd5123a2e63c8 100644 (file)
@@ -7,4 +7,4 @@ SPDX-License-Identifier: AGPL-3.0 %>
 <%= notice %>
 
 <br/>
-<a href="/auth/joshid">Retry Login</a>
+<a href="/login">Retry Login</a>
index 2c259919aeb69e6852076485c30e71ca0dd6f293..a6f1730e86190fc878c4c1ec3fd236af30e7cea3 100644 (file)
@@ -28,22 +28,6 @@ rescue LoadError
   # configured by application.yml (i.e., here!) instead.
 end
 
-if (File.exist?(File.expand_path '../omniauth.rb', __FILE__) and
-    not defined? WARNED_OMNIAUTH_CONFIG)
-  Rails.logger.warn <<-EOS
-DEPRECATED CONFIGURATION:
- Please move your SSO provider config into config/application.yml
- and delete config/initializers/omniauth.rb.
-EOS
-  # Real values will be copied from globals by omniauth_init.rb. For
-  # now, assign some strings so the generic *.yml config loader
-  # doesn't overwrite them or complain that they're missing.
-  Rails.configuration.Login["SSO"]["ProviderAppID"] = 'xxx'
-  Rails.configuration.Login["SSO"]["ProviderAppSecret"] = 'xxx'
-  Rails.configuration.Services["SSO"]["ExternalURL"] = '//xxx'
-  WARNED_OMNIAUTH_CONFIG = true
-end
-
 # Load the defaults, used by config:migrate and fallback loading
 # legacy application.yml
 defaultYAML, stderr, status = Open3.capture3("arvados-server", "config-dump", "-config=-", "-skip-legacy", stdin_data: "Clusters: {xxxxx: {}}")
@@ -114,14 +98,11 @@ arvcfg.declare_config "Users.EmailSubjectPrefix", String, :email_subject_prefix
 arvcfg.declare_config "Users.UserNotifierEmailFrom", String, :user_notifier_email_from
 arvcfg.declare_config "Users.NewUserNotificationRecipients", Hash, :new_user_notification_recipients, ->(cfg, k, v) { arrayToHash cfg, "Users.NewUserNotificationRecipients", v }
 arvcfg.declare_config "Users.NewInactiveUserNotificationRecipients", Hash, :new_inactive_user_notification_recipients, method(:arrayToHash)
-arvcfg.declare_config "Login.SSO.ProviderAppSecret", String, :sso_app_secret
-arvcfg.declare_config "Login.SSO.ProviderAppID", String, :sso_app_id
 arvcfg.declare_config "Login.LoginCluster", String
 arvcfg.declare_config "Login.TrustedClients", Hash
 arvcfg.declare_config "Login.RemoteTokenRefresh", ActiveSupport::Duration
 arvcfg.declare_config "Login.TokenLifetime", ActiveSupport::Duration
 arvcfg.declare_config "TLS.Insecure", Boolean, :sso_insecure
-arvcfg.declare_config "Services.SSO.ExternalURL", String, :sso_provider_url
 arvcfg.declare_config "AuditLogs.MaxAge", ActiveSupport::Duration, :max_audit_log_age
 arvcfg.declare_config "AuditLogs.MaxDeleteBatch", Integer, :max_audit_log_delete_batch
 arvcfg.declare_config "AuditLogs.UnloggedAttributes", Hash, :unlogged_attributes, ->(cfg, k, v) { arrayToHash cfg, "AuditLogs.UnloggedAttributes", v }
index b82ba27f9ae1bd390bdb71c0fd4f79c9c1fb4b70..cd706940a389752fd6263bb32fc82a057fc3c583 100644 (file)
@@ -4,7 +4,6 @@
 
 # Load the rails application
 require_relative 'application'
-require 'josh_id'
 
 # Initialize the rails application
 Rails.application.initialize!
diff --git a/services/api/config/initializers/omniauth_init.rb b/services/api/config/initializers/omniauth_init.rb
deleted file mode 100644 (file)
index a1b2356..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-# This file is called omniauth_init.rb instead of omniauth.rb because
-# older versions had site configuration in omniauth.rb.
-#
-# It must come after omniauth.rb in (lexical) load order.
-
-if defined? CUSTOM_PROVIDER_URL
-  Rails.logger.warn "Copying omniauth from globals in legacy config file."
-  Rails.configuration.Login["SSO"]["ProviderAppID"] = APP_ID
-  Rails.configuration.Login["SSO"]["ProviderAppSecret"] = APP_SECRET
-  Rails.configuration.Services["SSO"]["ExternalURL"] = CUSTOM_PROVIDER_URL.sub(/\/$/, "") + "/"
-else
-  Rails.application.config.middleware.use OmniAuth::Builder do
-    provider(:josh_id,
-             Rails.configuration.Login["SSO"]["ProviderAppID"],
-             Rails.configuration.Login["SSO"]["ProviderAppSecret"],
-             Rails.configuration.Services["SSO"]["ExternalURL"])
-  end
-  OmniAuth.config.on_failure = StaticController.action(:login_failure)
-end
diff --git a/services/api/lib/josh_id.rb b/services/api/lib/josh_id.rb
deleted file mode 100644 (file)
index f18c0ed..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'omniauth-oauth2'
-module OmniAuth
-  module Strategies
-    class JoshId < OmniAuth::Strategies::OAuth2
-
-      args [:client_id, :client_secret, :custom_provider_url]
-
-      option :custom_provider_url, ''
-
-      uid { raw_info['id'] }
-
-      option :client_options, {}
-
-      info do
-        {
-          :first_name => raw_info['info']['first_name'],
-          :last_name => raw_info['info']['last_name'],
-          :email => raw_info['info']['email'],
-          :identity_url => raw_info['info']['identity_url'],
-          :username => raw_info['info']['username'],
-        }
-      end
-
-      extra do
-        {
-          'raw_info' => raw_info
-        }
-      end
-
-      def authorize_params
-        options.authorize_params[:auth_provider] = request.params['auth_provider']
-        super
-      end
-
-      def client
-        options.client_options[:site] = options[:custom_provider_url]
-        options.client_options[:authorize_url] = "#{options[:custom_provider_url]}/auth/josh_id/authorize"
-        options.client_options[:access_token_url] = "#{options[:custom_provider_url]}/auth/josh_id/access_token"
-        if Rails.configuration.TLS.Insecure
-          options.client_options[:ssl] = {verify_mode: OpenSSL::SSL::VERIFY_NONE}
-        end
-        ::OAuth2::Client.new(options.client_id, options.client_secret, deep_symbolize(options.client_options))
-      end
-
-      def callback_url
-        full_host + script_name + callback_path + "?return_to=" + CGI.escape(request.params['return_to'] || '')
-      end
-
-      def raw_info
-        @raw_info ||= access_token.get("/auth/josh_id/user.json?oauth_token=#{access_token.token}").parsed
-      end
-    end
-  end
-end
index 1f919689325d2fef9f9578b150863a77ab55965b..66aff787bd78ecba8f5d897aa29c9d0a99265575 100644 (file)
@@ -9,9 +9,8 @@ class UserSessionsControllerTest < ActionController::TestCase
   test "redirect to joshid" do
     api_client_page = 'http://client.example.com/home'
     get :login, params: {return_to: api_client_page}
-    assert_response :redirect
-    assert_equal("http://test.host/auth/joshid?return_to=%2Chttp%3A%2F%2Fclient.example.com%2Fhome", @response.redirect_url)
-    assert_nil assigns(:api_client)
+    # Not supported any more
+    assert_response 404
   end
 
   test "send token when user is already logged in" do
@@ -107,9 +106,8 @@ class UserSessionsControllerTest < ActionController::TestCase
     Rails.configuration.Login.LoginCluster = 'zzzzz'
     api_client_page = 'http://client.example.com/home'
     get :login, params: {return_to: api_client_page}
-    assert_response :redirect
-    assert_equal("http://test.host/auth/joshid?return_to=%2Chttp%3A%2F%2Fclient.example.com%2Fhome", @response.redirect_url)
-    assert_nil assigns(:api_client)
+    # Doesn't redirect, just fail.
+    assert_response 404
   end
 
   test "controller cannot create session without SystemRootToken" do
index f0741fcfde9f2fe27297720f5bbc4bb88af9b418..ba3b2ac6e3198bbc0ad1eee986b71a2eb80db444 100644 (file)
@@ -30,7 +30,7 @@ class LoginWorkflowTest < ActionDispatch::IntegrationTest
       params: {specimen: {}},
       headers: {'HTTP_ACCEPT' => 'text/html'})
     assert_response 302
-    assert_match(%r{/auth/joshid$}, @response.headers['Location'],
+    assert_match(%r{http://www.example.com/login$}, @response.headers['Location'],
                  "HTML login prompt did not include expected redirect")
   end
 end
index 6e951499adfc173d7653376500a49e1f5a49a8e3..76659f3207fff6b7470e6d85ca95dcbbc936e10b 100644 (file)
@@ -15,21 +15,17 @@ class UserSessionsApiTest < ActionDispatch::IntegrationTest
 
   def mock_auth_with(email: nil, username: nil, identity_url: nil, remote: nil, expected_response: :redirect)
     mock = {
-      'provider' => 'josh_id',
-      'uid' => 'https://edward.example.com',
-      'info' => {
         'identity_url' => 'https://edward.example.com',
         'name' => 'Edward Example',
         'first_name' => 'Edward',
         'last_name' => 'Example',
-      },
     }
-    mock['info']['email'] = email unless email.nil?
-    mock['info']['username'] = username unless username.nil?
-    mock['info']['identity_url'] = identity_url unless identity_url.nil?
-    post('/auth/josh_id/callback',
-      params: {return_to: client_url(remote: remote)},
-      headers: {'omniauth.auth' => mock})
+    mock['email'] = email unless email.nil?
+    mock['username'] = username unless username.nil?
+    mock['identity_url'] = identity_url unless identity_url.nil?
+    post('/auth/controller/callback',
+      params: {return_to: client_url(remote: remote), :auth_info => SafeJSON.dump(mock)},
+      headers: {'Authorization' => 'Bearer ' + Rails.configuration.SystemRootToken})
 
     errors = {
       :redirect => 'Did not redirect to client with token',
index ee7dac4cd90099bb1d9b9fe17a9a781baaee5f1c..843d4f1b23fccfb8777883c3021ab54187b3cf57 100644 (file)
@@ -25,7 +25,6 @@ unless ENV["NO_COVERAGE_TEST"]
     SimpleCov.start do
       add_filter '/test/'
       add_filter 'initializers/secret_token'
-      add_filter 'initializers/omniauth'
     end
   rescue Exception => e
     $stderr.puts "SimpleCov unavailable (#{e}). Proceeding without."