From 743fd3682d4d1611726331df3531f737a8e8399b Mon Sep 17 00:00:00 2001 From: Sdogruyol Date: Sun, 27 Dec 2015 11:53:54 +0200 Subject: [PATCH] Add HTTPBasicAuth middleware --- spec/middleware/http_basic_auth_spec.cr | 25 +++++++++++++++++++ spec/spec_helper.cr | 1 + src/kemal/macros.cr | 6 +++++ src/kemal/middleware/http_basic_auth.cr | 33 +++++++++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 spec/middleware/http_basic_auth_spec.cr create mode 100644 src/kemal/middleware/http_basic_auth.cr diff --git a/spec/middleware/http_basic_auth_spec.cr b/spec/middleware/http_basic_auth_spec.cr new file mode 100644 index 0000000..223d3e1 --- /dev/null +++ b/spec/middleware/http_basic_auth_spec.cr @@ -0,0 +1,25 @@ +require "../spec_helper" + +describe "Kemal::Middleware::HTTPBasicAuth" do + it "goes to next handler with correct credentials" do + auth_handler = Kemal::Middleware::HTTPBasicAuth.new("serdar", "123") + request = HTTP::Request.new( + "GET", + "/", + headers: HTTP::Headers{"Authorization": "Basic c2VyZGFyOjEyMw=="}, + ) + response = auth_handler.call(request) + response.status_code.should eq 404 + end + + it "returns 401 with incorrect credentials" do + auth_handler = Kemal::Middleware::HTTPBasicAuth.new("serdar", "123") + request = HTTP::Request.new( + "GET", + "/", + headers: HTTP::Headers{"Authorization": "NotBasic"}, + ) + response = auth_handler.call(request) + response.status_code.should eq 401 + end +end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index 4774aec..9b98db6 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -1,5 +1,6 @@ require "spec" require "../src/kemal/*" +require "../src/kemal/middleware/*" include Kemal diff --git a/src/kemal/macros.cr b/src/kemal/macros.cr index f968481..a97b5bb 100644 --- a/src/kemal/macros.cr +++ b/src/kemal/macros.cr @@ -20,3 +20,9 @@ macro redirect(url) env.response.headers.add "Location", {{url}} env.response.status_code = 301 end + +# Uses Kemal::Middleware::HTTPBasicAuth to easily add HTTP Basic Auth support. +macro basic_auth(username, password) + auth_handler = Kemal::Middleware::HTTPBasicAuth.new("serdar", "123") + Kemal.config.add_handler auth_handler +end diff --git a/src/kemal/middleware/http_basic_auth.cr b/src/kemal/middleware/http_basic_auth.cr new file mode 100644 index 0000000..8ec53b8 --- /dev/null +++ b/src/kemal/middleware/http_basic_auth.cr @@ -0,0 +1,33 @@ +require "base64" + +module Kemal::Middleware + # This middleware adds HTTP Basic Auth support to your application. + # Returns 401 "Unauthorized" with wrong credentials. + # + # auth_handler = Kemal::Middleware::HTTPBasicAuth.new("username", "password") + # Kemal.config.add_handler auth_handler + # + class HTTPBasicAuth < HTTP::Handler + BASIC = "Basic" + AUTH = "Authorization" + + def initialize(@username, @password) + end + + def call(request) + if request.headers[AUTH]? + if value = request.headers[AUTH] + if value.size > 0 && value.starts_with?(BASIC) + return call_next(request) if authorized?(value) + end + end + end + HTTP::Response.new(401, "Unauthorized") + end + + def authorized?(value) + username, password = Base64.decode_string(value[BASIC.size + 1..-1]).split(":") + @username == username && @password == password + end + end +end