|
| 1 | +local http = require "socket.http" |
| 2 | +local ltn12 = require "ltn12" |
| 3 | +local cjson = require "cjson.safe" |
| 4 | +local jwt_decoder = require "kong.plugins.jwt.jwt_parser" |
| 5 | +local req_set_header = ngx.req.set_header |
| 6 | +local BasePlugin = require "kong.plugins.base_plugin" |
| 7 | + |
| 8 | +local kong = kong |
| 9 | + |
| 10 | +local TokenAuthHandler = BasePlugin:extend() |
| 11 | + |
| 12 | +TokenAuthHandler.PRIORITY = 1000 |
| 13 | +TokenAuthHandler.VERSION="0.1.0" |
| 14 | + |
| 15 | +local KEY_PREFIX = "whispir_auth_token" |
| 16 | +local EXPIRES_ERR = "token expires" |
| 17 | + |
| 18 | +local function extract_token(request) |
| 19 | + local auth_header = request.get_headers()["authorization"] |
| 20 | + if auth_header then |
| 21 | + local iterator, ierr = ngx.re.gmatch(auth_header, "\\s*[Bb]earer\\s+(.+)") |
| 22 | + if not iterator then |
| 23 | + return nil, ierr |
| 24 | + end |
| 25 | + |
| 26 | + local m, err = iterator() |
| 27 | + if err then |
| 28 | + return nil, err |
| 29 | + end |
| 30 | + |
| 31 | + if m and #m > 0 then |
| 32 | + return m[1] |
| 33 | + end |
| 34 | + end |
| 35 | +end |
| 36 | + |
| 37 | +local function test_redis(conf,setName,setValue) |
| 38 | + local redis = require "resty.redis"; |
| 39 | + local red = redis:new(); |
| 40 | + |
| 41 | + red:set_timeout(redis_connection_timeout);-- Time out |
| 42 | + |
| 43 | + local ok, err = red:connect(conf.redis_addr, conf.redis_port); |
| 44 | + ok, err = red:auth(conf.redis_pwd)-- password |
| 45 | + if not ok then |
| 46 | + --ngx.log(ngx.DEBUG, "error:" .. err); |
| 47 | + return kong.response.exit(500, { message = "Unable to connect to the database:"..tostring(err)}) |
| 48 | + else |
| 49 | + local blackValue, err = red:sismember(setName,setValue); |
| 50 | + if err then |
| 51 | + --ngx.log(ngx.DEBUG, "error:" .. err) |
| 52 | + return kong.response.exit(500, { message = tostring(err) }) |
| 53 | + else |
| 54 | + return blackValue |
| 55 | + end |
| 56 | + end |
| 57 | +end |
| 58 | + |
| 59 | +local function query_and_validate_token(token, conf) |
| 60 | +---[[ |
| 61 | + local request_uri = ngx.var.request_uri |
| 62 | + if false then |
| 63 | + return kong.response.exit(401, { message = tostring(request_uri) }) |
| 64 | + end |
| 65 | +--]] |
| 66 | + |
| 67 | +---[[ |
| 68 | + local jwt, err = jwt_decoder:new(token) |
| 69 | + if err then |
| 70 | + return kong.response.exit(401, { message = tostring(err) }) |
| 71 | + end |
| 72 | + |
| 73 | + local claims = jwt.claims |
| 74 | + local header = jwt.header |
| 75 | + |
| 76 | + local jwt_uid_key = claims[conf.key_uid_name] or header[conf.key_uid_name] |
| 77 | + local jwt_permission_key = claims[conf.key_permission_name] or header[conf.key_permission_name] |
| 78 | + if not jwt_uid_key then |
| 79 | + return false, { status = 401, message = "No mandatory '" .. conf.key_uid_name .. "' in claims" } |
| 80 | + end |
| 81 | + |
| 82 | + if not jwt_permission_key then |
| 83 | + return false, { status = 401, message = "No mandatory '" .. conf.key_permission_name .. "' in claims" } |
| 84 | + end |
| 85 | +--return kong.response.exit(500, { message = jwt_permission_key }) |
| 86 | + |
| 87 | +---[[ |
| 88 | + --test Redis |
| 89 | + |
| 90 | + local blackValue=test_redis(conf,jwt_uid_key,jwt_permission_key) |
| 91 | + |
| 92 | + if (tostring(blackValue)~="1") then |
| 93 | + return kong.response.exit(401, { message = "Wrong request,no permission:"..tostring(blackValue)}) |
| 94 | + end |
| 95 | + --test end |
| 96 | +---[[ |
| 97 | + |
| 98 | + local authorization = tostring(jwt_uid_key); |
| 99 | + local authorizationBase64 = ngx.encode_base64(authorization); |
| 100 | + local authorizationHeader = "Basic " .. authorizationBase64; |
| 101 | + req_set_header("uid", authorization) |
| 102 | + print(authorization) |
| 103 | +--]] |
| 104 | + |
| 105 | +end |
| 106 | + |
| 107 | +function TokenAuthHandler:new() |
| 108 | + TokenAuthHandler.super.new(self, "my-jwt") |
| 109 | +end |
| 110 | + |
| 111 | +function TokenAuthHandler:access(conf) |
| 112 | + TokenAuthHandler.super.access(self) |
| 113 | + |
| 114 | + local token, err = extract_token(ngx.req) |
| 115 | + if err then |
| 116 | + ngx.log(ngx.ERR, "failed to extract token: ", err) |
| 117 | + return kong.response.exit(500, { message = err }) |
| 118 | + end |
| 119 | + ngx.log(ngx.DEBUG, "extracted token: ", token) |
| 120 | + |
| 121 | + local ttype = type(token) |
| 122 | + if ttype ~= "string" then |
| 123 | + if ttype == "nil" then |
| 124 | + return kong.response.exit(401, { message = "Missing token" }) |
| 125 | + end |
| 126 | + if ttype == "table" then |
| 127 | + return kong.response.exit(401, { message = "Multiple tokens" }) |
| 128 | + end |
| 129 | + return kong.response.exit(401, { message = "Unrecognized token" }) |
| 130 | + end |
| 131 | + |
| 132 | + local info |
| 133 | + info, err = query_and_validate_token(token, conf) |
| 134 | + |
| 135 | + if err then |
| 136 | + ngx.log(ngx.ERR, "failed to validate token: ", err) |
| 137 | + if EXPIRES_ERR == err then |
| 138 | + return kong.response.exit(401, { message = EXPIRES_ERR }) |
| 139 | + end |
| 140 | + return kong.response.exit(500, { message = err }) |
| 141 | + end |
| 142 | + |
| 143 | + --if info.expires_at < os.time() then |
| 144 | + --return kong.response.exit(401, { message = EXPIRES_ERR }) |
| 145 | + --end |
| 146 | + --ngx.log(ngx.DEBUG, "token will expire in ", info.expires_at - os.time(), " seconds") |
| 147 | + |
| 148 | +end |
| 149 | + |
| 150 | +return TokenAuthHandler |
0 commit comments