util/jwt.lua
author Matthew Wild <mwild1@gmail.com>
Mon, 20 Feb 2023 18:10:15 +0000
branch0.12
changeset 12898 0598d822614f
parent 11565 d2f33b8fdc96
child 12700 27a72982e331
permissions -rw-r--r--
mod_websocket: Fire pre-session-close event (fixes #1800) This event was added in a7c183bb4e64 and is required to make mod_smacks know that a session was intentionally closed and shouldn't be hibernated (see fcea4d9e7502). Because this was missing from mod_websocket's session.close(), mod_smacks would always attempt to hibernate websocket sessions even if they closed cleanly. That mod_websocket has its own copy of session.close() is something to fix another day (probably not in the stable branch). So for now this commit makes the minimal change to get things working again. Thanks to Damian and the Jitsi team for reporting.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10664
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     1
local s_gsub = string.gsub;
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     2
local json = require "util.json";
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     3
local hashes = require "util.hashes";
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     4
local base64_encode = require "util.encodings".base64.encode;
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     5
local base64_decode = require "util.encodings".base64.decode;
11565
d2f33b8fdc96 util.jwt: Use constant-time comparison with expected signature
Matthew Wild <mwild1@gmail.com>
parents: 10664
diff changeset
     6
local secure_equals = require "util.hashes".equals;
10664
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     7
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     8
local b64url_rep = { ["+"] = "-", ["/"] = "_", ["="] = "", ["-"] = "+", ["_"] = "/" };
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     9
local function b64url(data)
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    10
	return (s_gsub(base64_encode(data), "[+/=]", b64url_rep));
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    11
end
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    12
local function unb64url(data)
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    13
	return base64_decode(s_gsub(data, "[-_]", b64url_rep).."==");
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    14
end
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    15
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    16
local static_header = b64url('{"alg":"HS256","typ":"JWT"}') .. '.';
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    17
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    18
local function sign(key, payload)
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    19
	local encoded_payload = json.encode(payload);
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    20
	local signed = static_header .. b64url(encoded_payload);
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    21
	local signature = hashes.hmac_sha256(key, signed);
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    22
	return signed .. "." .. b64url(signature);
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    23
end
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    24
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    25
local jwt_pattern = "^(([A-Za-z0-9-_]+)%.([A-Za-z0-9-_]+))%.([A-Za-z0-9-_]+)$"
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    26
local function verify(key, blob)
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    27
	local signed, bheader, bpayload, signature = string.match(blob, jwt_pattern);
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    28
	if not signed then
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    29
		return nil, "invalid-encoding";
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    30
	end
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    31
	local header = json.decode(unb64url(bheader));
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    32
	if not header or type(header) ~= "table" then
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    33
		return nil, "invalid-header";
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    34
	elseif header.alg ~= "HS256" then
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    35
		return nil, "unsupported-algorithm";
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    36
	end
11565
d2f33b8fdc96 util.jwt: Use constant-time comparison with expected signature
Matthew Wild <mwild1@gmail.com>
parents: 10664
diff changeset
    37
	if not secure_equals(b64url(hashes.hmac_sha256(key, signed)), signature) then
10664
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    38
		return false, "signature-mismatch";
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    39
	end
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    40
	local payload, err = json.decode(unb64url(bpayload));
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    41
	if err ~= nil then
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    42
		return nil, "json-decode-error";
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    43
	end
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    44
	return true, payload;
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    45
end
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    46
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    47
return {
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    48
	sign = sign;
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    49
	verify = verify;
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    50
};
c4ded3be7cc0 util.jwt: Basic JSON Web Token library supporting HS256 tokens
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    51