Moves API token authentication from ApplicationController into ArvadosApiToken Rack...
[arvados.git] / services / api / app / middlewares / arvados_api_token.rb
1 class ArvadosApiToken
2   def initialize(app = nil, options = nil)
3     @app = app if app.respond_to?(:call)
4   end
5
6   def call env
7     # first, clean up just in case
8     Thread.current[:api_client_ip_address] = nil
9     Thread.current[:api_client_authorization] = nil
10     Thread.current[:api_client_uuid] = nil
11     Thread.current[:api_client] = nil
12     Thread.current[:user] = nil
13
14     request = Rack::Request.new(env)
15     params = request.params
16     remote_ip = env["action_dispatch.remote_ip"]
17
18     Thread.current[:request_starttime] = Time.now
19     user = nil
20     api_client = nil
21     api_client_auth = nil
22     supplied_token =
23       params["api_token"] ||
24       params["oauth_token"] ||
25       env["HTTP_AUTHORIZATION"].andand.match(/OAuth2 ([a-z0-9]+)/).andand[1]
26     if supplied_token
27       api_client_auth = ApiClientAuthorization.
28         includes(:api_client, :user).
29         where('api_token=? and (expires_at is null or expires_at > CURRENT_TIMESTAMP)', supplied_token).
30         first
31       if api_client_auth.andand.user
32         user = api_client_auth.user
33         api_client = api_client_auth.api_client
34       else
35         # Token seems valid, but points to a non-existent (deleted?) user.
36         api_client_auth = nil
37       end
38     end
39     Thread.current[:api_client_ip_address] = remote_ip
40     Thread.current[:api_client_authorization] = api_client_auth
41     Thread.current[:api_client_uuid] = api_client.andand.uuid
42     Thread.current[:api_client] = api_client
43     Thread.current[:user] = user
44     if api_client_auth
45       api_client_auth.last_used_at = Time.now
46       api_client_auth.last_used_by_ip_address = remote_ip.to_s
47       api_client_auth.save validate: false
48     end
49
50     @app.call env
51   end
52 end