Skip to content
This repository
Browse code

Merge pull request #12 from vitrue/api-key-auth

API key header auth
  • Loading branch information...
commit 19b222ad76ed0598f2801c636494a1a58560cd31 2 parents 1716102 + 0040df1
Kyle Brett authored
6 lib/dzl/dsl_proxies/protection.rb
@@ -3,4 +3,8 @@ def http_basic(opts)
3 3 raise ArgumentError unless [:username, :password].all? {|k| opts[k].present?}
4 4 @subject.opts[:http_basic] = opts
5 5 end
6   -end
  6 + def api_key(opts)
  7 + raise ArgumentError unless [:header, :valid_keys].all? {|k| opts[k].present?}
  8 + @subject.opts[:api_key] = opts
  9 + end
  10 +end
32 lib/dzl/dsl_subjects/protection.rb
... ... @@ -1,6 +1,7 @@
1 1 require 'dzl/dsl_proxies/protection'
2 2
3 3 class Dzl::RespondWithHTTPBasicChallenge < StandardError; end
  4 +class Dzl::RespondWithInvalidAPIKey < StandardError; end
4 5
5 6 class Dzl::DSLSubjects::Protection < Dzl::DSLSubject
6 7 def initialize
@@ -15,17 +16,34 @@ def allow?(parandidates, request)
15 16 if @opts[:http_basic].present?
16 17 @auth = Rack::Auth::Basic::Request.new(request.env)
17 18 if @auth.provided? && @auth.basic? && @auth.credentials
  19 + # Invalid basic auth credentials
18 20 unless @auth.credentials[0] == @opts[:http_basic][:username] &&
19 21 @auth.credentials[1] == @opts[:http_basic][:password]
20   - Dzl::ValueOrError.new(e: :invalid_http_basic_credentials)
21   - else
22   - Dzl::ValueOrError.new(v: nil)
  22 + return Dzl::ValueOrError.new(e: :invalid_http_basic_credentials)
23 23 end
  24 + # No basic auth credentials provided
24 25 else
25   - Dzl::ValueOrError.new(e: :no_http_basic_credentials)
  26 + return Dzl::ValueOrError.new(e: :no_http_basic_credentials)
26 27 end
27   - else
28   - Dzl::ValueOrError.new(v: nil)
29 28 end
  29 +
  30 + if @opts[:api_key].present?
  31 + api_key_header = @opts[:api_key][:header]
  32 + allowed_keys = @opts[:api_key][:valid_keys]
  33 + request_key = request.headers[api_key_header]
  34 +
  35 + if request_key
  36 + # Invalid API key provided
  37 + unless allowed_keys.include? request_key
  38 + return Dzl::ValueOrError.new(e: :invalid_api_key)
  39 + end
  40 + # No API key provided
  41 + else
  42 + return Dzl::ValueOrError.new(e: :no_api_key)
  43 + end
  44 + end
  45 +
  46 + # Auth passed
  47 + return Dzl::ValueOrError.new(v: nil)
30 48 end
31   -end
  49 +end
7 lib/dzl/dsl_subjects/router.rb
@@ -99,7 +99,12 @@ def find_endpoint(request)
99 99 raise Dzl::RespondWithHTTPBasicChallenge
100 100 end
101 101
  102 + if !errors.empty? &&
  103 + errors.values.any? {|v| v == :no_api_key || v == :invalid_api_key}
  104 + raise Dzl::RespondWithInvalidAPIKey
  105 + end
  106 +
102 107 endpoint || raise(Dzl::NotFound.new(errors))
103 108 end
104 109
105   -end
  110 +end
6 lib/dzl/examples/fun_with_params.rb
@@ -48,6 +48,12 @@ class Dzl::Examples::FunWithParams < Dzl::Examples::Base
48 48 end
49 49 end
50 50
  51 + endpoint '/api' do
  52 + protect do
  53 + api_key header: 'x_api_key', valid_keys: ['valid-key']
  54 + end
  55 + end
  56 +
51 57 endpoint '/arithmetic' do
52 58 optional :int do
53 59 type Fixnum
12 lib/dzl/rack_interface.rb
@@ -15,6 +15,8 @@ def call(env)
15 15 [__router.handle_request(request), nil]
16 16 rescue Dzl::RespondWithHTTPBasicChallenge
17 17 [respond_with_http_basic_challenge, nil]
  18 + rescue Dzl::RespondWithInvalidAPIKey
  19 + [respond_with_invalid_api_key, nil]
18 20 rescue Dzl::Error => e
19 21 [respond_with_dzl_error_handler(e), nil]
20 22 rescue StandardError => e
@@ -51,6 +53,14 @@ def respond_with_http_basic_challenge
51 53 response.finish
52 54 end
53 55
  56 + def respond_with_invalid_api_key
  57 + response = Rack::Response.new
  58 + response.status = 401
  59 + response.headers['Content-Type'] = 'text/html'
  60 + response.write("Not Authorized\n")
  61 + response.finish
  62 + end
  63 +
54 64 def respond_with_standard_error_handler(e)
55 65 response = Rack::Response.new
56 66 response.headers['Content-Type'] = 'application/json'
@@ -108,4 +118,4 @@ def log_request(request, response, seconds, error)
108 118 end
109 119 end
110 120 end
111   -end
  121 +end
17 spec/fun_with_params_spec.rb
@@ -172,6 +172,23 @@ def app; Dzl::Examples::FunWithParams; end
172 172 end
173 173 end
174 174
  175 + describe '/api' do
  176 + it 'should 401 if no api key provided' do
  177 + get '/api'
  178 + last_response.status.should == 401
  179 + end
  180 +
  181 + it 'should 401 if invalid api key provided' do
  182 + get '/api', {}, {"HTTP_X_API_KEY" => 'invalid-key'}
  183 + last_response.status.should == 401
  184 + end
  185 +
  186 + it 'should accept valid api key' do
  187 + get '/api', {}, {"HTTP_X_API_KEY" => 'valid-key'}
  188 + last_response.status.should == 200
  189 + end
  190 + end
  191 +
175 192 describe '/arithmetic' do
176 193 it 'should not allow :int < 5' do
177 194 get('/arithmetic', {int: 4}) do |response|

0 comments on commit 19b222a

Please sign in to comment.
Something went wrong with that request. Please try again.