local helpers = require "spec.helpers"
local md5 = require "resty.md5"
local str = require "resty.string"
local cjson_safe = require "cjson.safe"

local REDIS_HOST = helpers.redis_host
local REDIS_PORT = helpers.redis_port
local REDIS_PASSWORD = ""
local REDIS_DATABASE = 1

local function set_redis(red,key,val)
    local ok, err = red:set(key,val)
    if not ok then
        error("failed to set `"..key.."` api keys: " .. err)
    end
end


local function init_dependency()
    local redis = require "resty.redis"
    local red = redis:new()
    red:set_timeout(2000)
    local ok, err = red:connect(REDIS_HOST, REDIS_PORT)
    if not ok then
        error("failed to connect to Redis: " .. err)
    end

    if REDIS_PASSWORD and REDIS_PASSWORD ~= "" then
        local ok, err = red:auth(REDIS_PASSWORD)
        if not ok then
            error("failed to connect to Redis: " .. err)
        end
    end

    local ok, err = red:select(REDIS_DATABASE)
    if not ok then
        error("failed to change Redis database: " .. err)
    end

    local ok, err = red:set("dbaas:account:api_keys:abc",
                            "{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\", \"cidrs\":[\"0.0.0.0/0\"]}")
    if not ok then
        error("failed to set `abc` api keys: " .. err)
    end
    local ok, err = red:set("dbaas:account:api_keys:abc1",
                            "{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\", \"cidrs\":[\"0.0.0.0/32\"]}")
    if not ok then
        error("failed to set `abc1` api keys: " .. err)
    end
    local ok, err = red:set("dbaas:account:api_keys:abc2",
                            "{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\", \"cidrs\":[\"127.0.0.0/8\", \"192.0.0.0/8\"]}")
    if not ok then
        error("failed to set `abc2` api keys: " .. err)
    end
    local ok, err = red:set("dbaas:account:api_keys:abc3",
                            "{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\", \"cidrs\":[]}")
    if not ok then
        error("failed to set `abc3` api keys: " .. err)
    end
    local ok, err = red:set("dbaas:account:api_keys:abc4",
                            "{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\"}")
    if not ok then
        error("failed to set `abc4` api keys: " .. err)
    end

    set_redis(red,"dbaas:account:api_keys:not_expire_set",
    cjson_safe.encode({private_key="895e6c10bad41ad3adc353baa50138cd",expired_ts=0}))

    set_redis(red,"dbaas:account:api_keys:expired_case",
    string.format("{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\",\"expired_ts\":%d}",(ngx.now()-2)*1000))

    set_redis(red,"dbaas:account:api_keys:not_expired_case",
    string.format("{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\",\"expired_ts\":%d}",(ngx.now()+10)*1000))


    helpers.setenv("SECRET_AES_256_KEY", "12345678901234561234567890123456")
    helpers.setenv("SECRET_AES_256_IV", "1234567890123456")

    red:close()
end

local function extract_www_authenticate(res)
    local auth_str = string.match(res.headers["WWW-Authenticate"],
                                  "%s*[Dd]igest%s*(.*)$")
    if not auth_str then
        error("get bad WWW-Authenticate header")
    end

    local auth = {}
    for k, v in string.gmatch(auth_str, "(%w+)%s*=%s*\"?([%%%w./=:_?&-]+)\"?") do
        auth[k] = v
    end
    return auth
end

local m = md5:new()
local function md5_digest(s)
    m:reset()
    m:update(s)
    local digest = m:final()
    return str.to_hex(digest)
end

local function gen_response(username, passwd, realm, method, uri, nonce, nc,
                            cnonce, qop)
    local A1 = string.format("%s:%s:%s", username, realm, passwd)
    local HA1 = md5_digest(A1)
    local A2 = string.format("%s:%s", method, uri)
    local HA2 = md5_digest(A2)
    local response = md5_digest(string.format("%s:%s:%s:%s:%s:%s", HA1, nonce,
                                              nc, cnonce, qop, HA2))
    return response
end

-- Digest username="apjcejac", realm="tidb.cloud", nonce="4tfOBX/XnfNQ7XAuJ8WTuCEhR2t1SpwW", uri="/status/200", cnonce="YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=", nc=00000001, qop=auth, response="53c2f533bc405ee75dff2c67431b518e", algorithm=MD5

for _, strategy in helpers.each_strategy() do
    describe("Plugin: custom-basic-auth-and-digest-auth [#" .. strategy .. "]",
             function()
        local proxy_client
        lazy_setup(function()
            init_dependency()

            local bp = helpers.get_db_utils(strategy,
                                            {"routes", "services", "plugins"})

            local service1 = bp.services:insert{
                protocol = "http",
                host = helpers.mock_upstream_host,
                port = helpers.mock_upstream_port
            }

            local route1 = bp.routes:insert{
                protocols = {"http", "https"},
                hosts = {"test1.com"},
                service = service1
            }

            bp.plugins:insert{
                route = {id = route1.id},
                name = "digest-auth",
                config = {
                    nonce_key = "1234567890123456",
                    nonce_iv = "1234567890123456",
                    redis_host = REDIS_HOST,
                    redis_database = REDIS_DATABASE
                }
            }

            bp.plugins:insert{
                route = {id = route1.id},
                name = "custom-basic-auth",
                config = {
                    nonce_key = "1234567890123456",
                    nonce_iv = "1234567890123456",
                    redis_host = REDIS_HOST,
                    redis_database = REDIS_DATABASE
                }
            }

            bp.plugins:insert{route = {id = route1.id}, name = "bearer-token-auth"}

            assert(helpers.start_kong({
                database = strategy,
                nginx_conf = "spec/fixtures/custom_nginx.template",
                plugins = "digest-auth,custom-basic-auth,bearer-token-auth"
            }))
        end)

        lazy_teardown(function()
            helpers.stop_kong()
        end)

        before_each(function()
            proxy_client = helpers.proxy_client()
        end)

        after_each(function()
            if proxy_client then
                proxy_client:close()
            end
        end)

        describe("No Authorization Header", function()
            it("return 401", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)
            end)
            it("return different nonce every time", function()
                local pre = ""
                for i = 1, 10 do
                    local res = assert(proxy_client:send({
                        method = "GET",
                        path = "/status/200",
                        headers = {["Host"] = "test1.com"}
                    }))
                    local auth = extract_www_authenticate(res)
                    assert.falsy(auth["nonce"] == pre)
                    pre = auth["nonce"]
                    ngx.sleep(0.01)
                end
            end)
        end)

        describe("With Digest Authorization Header", function()
            it("if password is correct return 200", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)
                local auth = extract_www_authenticate(res)
                local response = gen_response("abc", "123456", auth.realm,
                                              "GET", "/status/200", auth.nonce,
                                              "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"abc\", realm=\"tidb.cloud\", uri=\"/status/200\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local res200 = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(200, res200)
            end)

            it("test password is correct and path is urlencoded return 200",
               function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200?type=c&q=C%E8%AF%AD%E8%A8%80",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)
                local auth = extract_www_authenticate(res)
                local response = gen_response("abc", "123456", auth.realm,
                                              "GET",
                                              "/status/200?type=c&q=C%E8%AF%AD%E8%A8%80",
                                              auth.nonce, "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"abc\", realm=\"tidb.cloud\", uri=\"/status/200?type=c&q=C%E8%AF%AD%E8%A8%80\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local res200 = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200?type=c&q=C%E8%AF%AD%E8%A8%80",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(200, res200)
            end)

            it("test password is correct and path with space return 200",
               function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200?type=c&q=A+B",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)
                local auth = extract_www_authenticate(res)
                local response = gen_response("abc", "123456", auth.realm,
                                              "GET", "/status/200?type=c&q=A+B",
                                              auth.nonce, "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"abc\", realm=\"tidb.cloud\", uri=\"/status/200?type=c&q=A+B\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local res200 = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200?type=c&q=A+B",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(200, res200)
            end)

            it("if password is wrong return 401", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)
                local auth = extract_www_authenticate(res)
                local response = gen_response("abc", "1234567", auth.realm,
                                              "GET", "/status/200", auth.nonce,
                                              "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"abc\", realm=\"tidb.cloud\", uri=\"/status/200\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local res401 = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(401, res401)
            end)
        end)

        describe("With Wrong Basic Authorization Header", function()
            it("return 401", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
                    }
                }))
                assert.res_status(401, res)
            end)
        end)

        describe("With Correct Basic Authorization Header", function()
            it("return 200", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = "Basic YWJjOjEyMzQ1Ngo="
                    }
                }))
                assert.res_status(200, res)
            end)
        end)

        describe("Test Nonce Expire", function()
            it("can't be reused in 5 seconds", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)
                local auth = extract_www_authenticate(res)
                local response = gen_response("abc", "123456", auth.realm,
                                              "GET", "/status/200", auth.nonce,
                                              "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"abc\", realm=\"tidb.cloud\", uri=\"/status/200\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local res200 = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(200, res200)

                ngx.sleep(2)
                local res200 = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(200, res200)

                ngx.sleep(4)
                local res401 = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(401, res401)
            end)
        end)

        describe("Test CIDR", function()
            it("block return 403", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)
                local auth = extract_www_authenticate(res)
                local response = gen_response("abc1", "123456", auth.realm,
                                              "GET", "/status/200", auth.nonce,
                                              "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"abc1\", realm=\"tidb.cloud\", uri=\"/status/200\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local r = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(403, r)
            end)
            it("pass check", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)
                local auth = extract_www_authenticate(res)
                local response = gen_response("abc2", "123456", auth.realm,
                                              "GET", "/status/200", auth.nonce,
                                              "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"abc2\", realm=\"tidb.cloud\", uri=\"/status/200\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local r = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(200, r)
            end)
            it("empty cidr does not bock", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)
                local auth = extract_www_authenticate(res)
                local response = gen_response("abc3", "123456", auth.realm,
                                              "GET", "/status/200", auth.nonce,
                                              "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"abc3\", realm=\"tidb.cloud\", uri=\"/status/200\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local r = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(200, r)
            end)
            it("no cidr does not bock", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)
                local auth = extract_www_authenticate(res)
                local response = gen_response("abc4", "123456", auth.realm,
                                              "GET", "/status/200", auth.nonce,
                                              "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"abc4\", realm=\"tidb.cloud\", uri=\"/status/200\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local r = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(200, r)
            end)
        end)

        describe("Test Header To Upstream", function()
            it("contains auth type and auth username", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/request",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)
                local auth = extract_www_authenticate(res)
                local response = gen_response("abc", "123456", auth.realm,
                                              "GET", "/request", auth.nonce,
                                              "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"abc\", realm=\"tidb.cloud\", uri=\"/request\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local r = assert(proxy_client:send({
                    method = "GET",
                    path = "/request",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(200, r)
                local t = assert.request(r).has.header("x-auth-type")
                assert.equals("openapi", t)
                local u = assert.request(r).has.header("x-auth-username")
                assert.equals("abc", u)
                local c = assert.request(r).has.header("x-auth-content")
                local auth_content = cjson_safe.decode(c)
                assert.equals("abc", auth_content["public_key"])
            end)
        end)

        describe("Test Header To Upstream Basic Auth", function()
            it("contains auth type and auth username", function()
                local r = assert(proxy_client:send({
                    method = "GET",
                    path = "/request",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = "Basic YWJjOjEyMzQ1Ngo="
                    }
                }))
                assert.res_status(200, r)
                local t = assert.request(r).has.header("x-auth-type")
                assert.equals("openapi", t)
                local u = assert.request(r).has.header("x-auth-username")
                assert.equals("abc", u)
                local c = assert.request(r).has.header("x-auth-content")
                local auth_content = cjson_safe.decode(c)
                assert.equals("abc", auth_content["public_key"])
            end)
        end)

        describe("Test without CORS plugin", function()
            it("OPTIONS returns 401", function()
                local r = assert(proxy_client:send({
                    method = "OPTIONS",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Origin"] = "tidbcloud.com",
                        ["Access-Control-Request-Method"] = "GET"
                    }
                }))
                assert.res_status(401, r)
            end)
        end)

        describe("Test Expired Key", function()
            it("return 200 if expire not set", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)

                local auth = extract_www_authenticate(res)
                local response = gen_response("not_expire_set", "123456", auth.realm,
                                              "GET", "/status/200", auth.nonce,
                                              "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"not_expire_set\", realm=\"tidb.cloud\", uri=\"/status/200\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local res200 = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(200, res200)
            end)
            it("return 200 if key is not expired", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)

                local auth = extract_www_authenticate(res)
                local response = gen_response("not_expired_case", "123456", auth.realm,
                                              "GET", "/status/200", auth.nonce,
                                              "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"not_expired_case\", realm=\"tidb.cloud\", uri=\"/status/200\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local res200 = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(200, res200)
            end)
            it("return 401 if key was expired", function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {["Host"] = "test1.com"}
                }))
                assert.res_status(401, res)

                local auth = extract_www_authenticate(res)
                local response = gen_response("expired_case", "123456", auth.realm,
                                              "GET", "/status/200", auth.nonce,
                                              "00000001",
                                              "YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=",
                                              "auth")
                local header =
                    "Digest username=\"expired_case\", realm=\"tidb.cloud\", uri=\"/status/200\", cnonce=\"YzI2ZTYzNTFiMDk0MzFlMDQxOGNjMDEwMTYyNjRkNmE=\", nc=00000001, qop=auth, algorithm=MD5, " ..
                        "nonce=" .. auth.nonce .. ", response=" .. response

                local res401 = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"] = header
                    }
                }))
                assert.res_status(401, res401)
            end)
        end)

        describe("Bearer Auth Test", function()
            it("return 200 given valid bearer",
               function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"]="Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlJEWTNNVUpGTUVReU9VVTBSa0U"
                    }
                }))
                assert.res_status(200, res)
                res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"]="bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlJEWTNNVUpGTUVReU9VVTBSa0U"
                    }
                }))
                assert.res_status(200, res)
            end)

            it("return 401 given invalid bearer",
               function()
                local res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"]="Bearer",
                    }
                }))
                assert.res_status(401, res)
                
                res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"]="Bearerfewq",
                    }
                }))
                assert.res_status(401, res)

                res = assert(proxy_client:send({
                    method = "GET",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Authorization"]="Beare",
                    }
                }))
                assert.res_status(401, res)

            end)
        end)

    end)
end
