12627: Set current_user from first valid reader_token
authorTom Clegg <tclegg@veritasgenetics.com>
Thu, 23 Nov 2017 18:52:46 +0000 (13:52 -0500)
committerTom Clegg <tclegg@veritasgenetics.com>
Fri, 24 Nov 2017 15:29:00 +0000 (10:29 -0500)
...if primary session token is missing or invalid.

Workbench relies on this for anonymous access.

Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg@veritasgenetics.com>

services/api/app/middlewares/arvados_api_token.rb
services/api/test/integration/reader_tokens_test.rb

index 5eb756b9fa3609519a1fa63f8c3a1a9021ed190c..1d477183f1f37f4907adad745bdbbb3de6da48ac 100644 (file)
@@ -32,21 +32,33 @@ class ArvadosApiToken
     user = nil
     api_client = nil
     api_client_auth = nil
-    supplied_token =
-      params["api_token"] ||
-      params["oauth_token"] ||
-      env["HTTP_AUTHORIZATION"].andand.match(/OAuth2 ([a-zA-Z0-9]+)/).andand[1]
-    if supplied_token
-      api_client_auth = ApiClientAuthorization.
+    if request.get?
+      reader_tokens = params["reader_tokens"]
+      if reader_tokens.is_a? String
+        reader_tokens = SafeJSON.load(reader_tokens)
+      end
+    else
+      reader_tokens = nil
+    end
+
+    # Set current_user etc. based on the primary session token if a
+    # valid one is present. Otherwise, use the first valid token in
+    # reader_tokens.
+    [params["api_token"],
+     params["oauth_token"],
+     env["HTTP_AUTHORIZATION"].andand.match(/OAuth2 ([a-zA-Z0-9]+)/).andand[1],
+     *reader_tokens,
+    ].each do |supplied|
+      next if !supplied
+      try_auth = ApiClientAuthorization.
         includes(:api_client, :user).
-        where('api_token=? and (expires_at is null or expires_at > CURRENT_TIMESTAMP)', supplied_token).
+        where('api_token=? and (expires_at is null or expires_at > CURRENT_TIMESTAMP)', supplied).
         first
-      if api_client_auth.andand.user
+      if try_auth.andand.user
+        api_client_auth = try_auth
         user = api_client_auth.user
         api_client = api_client_auth.api_client
-      else
-        # Token seems valid, but points to a non-existent (deleted?) user.
-        api_client_auth = nil
+        break
       end
     end
     Thread.current[:api_client_ip_address] = remote_ip
index 60b06a9ec8828b5894315a0880b254044a4dadaf..a60be093a31f033f15d4dbb96a22d4f35da0dda2 100644 (file)
@@ -51,9 +51,9 @@ class ReaderTokensTest < ActionDispatch::IntegrationTest
   [nil, :active_noscope].each do |main_auth|
     [:spectator, :spectator_specimens].each do |read_auth|
       [:to_a, :to_json].each do |formatter|
-        test "#{main_auth.inspect} auth with #{formatter} reader token #{read_auth} can't read" do
+        test "#{main_auth.inspect} auth with #{formatter} reader token #{read_auth} can#{"'t" if main_auth} read" do
           get_specimens(main_auth, read_auth)
-          assert_response(if main_auth then 403 else 302 end)
+          assert_response(if main_auth then 403 else 200 end)
         end
 
         test "#{main_auth.inspect} auth with #{formatter} reader token #{read_auth} can't write" do