diff --git a/Makefile b/Makefile index b2e76d7..a67f4fc 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ EXTENSION = pgjwt -DATA = pgjwt--0.1.0.sql +DATA = pgjwt--0.1.1.sql pgjwt--0.1.0--0.1.1.sql # postgres build stuff PG_CONFIG = pg_config diff --git a/pgjwt--0.1.0.sql b/pgjwt--0.1.0--0.1.1.sql similarity index 96% rename from pgjwt--0.1.0.sql rename to pgjwt--0.1.0--0.1.1.sql index 128a137..d726438 100644 --- a/pgjwt--0.1.0.sql +++ b/pgjwt--0.1.0--0.1.1.sql @@ -3,7 +3,7 @@ CREATE OR REPLACE FUNCTION url_encode(data bytea) RETURNS text LANGUAGE sql AS $$ SELECT translate(encode(data, 'base64'), E'+/=\n', '-_'); -$$; +$$ IMMUTABLE; CREATE OR REPLACE FUNCTION url_decode(data text) RETURNS bytea LANGUAGE sql AS $$ @@ -15,7 +15,7 @@ WITH t AS (SELECT translate(data, '-_', '+/') AS trans), THEN repeat('=', (4 - rem.remainder)) ELSE '' END, 'base64') FROM t, rem; -$$; +$$ IMMUTABLE; CREATE OR REPLACE FUNCTION algorithm_sign(signables text, secret text, algorithm text) @@ -28,7 +28,7 @@ WITH WHEN algorithm = 'HS512' THEN 'sha512' ELSE '' END AS id) -- hmac throws error SELECT @extschema@.url_encode(@extschema@.hmac(signables, secret, alg.id)) FROM alg; -$$; +$$ IMMUTABLE; CREATE OR REPLACE FUNCTION sign(payload json, secret text, algorithm text DEFAULT 'HS256') @@ -46,7 +46,7 @@ WITH SELECT signables.data || '.' || @extschema@.algorithm_sign(signables.data, secret, algorithm) FROM signables; -$$; +$$ IMMUTABLE; CREATE OR REPLACE FUNCTION verify(token text, secret text, algorithm text DEFAULT 'HS256') @@ -56,4 +56,4 @@ RETURNS table(header json, payload json, valid boolean) LANGUAGE sql AS $$ convert_from(@extschema@.url_decode(r[2]), 'utf8')::json AS payload, r[3] = @extschema@.algorithm_sign(r[1] || '.' || r[2], secret, algorithm) AS valid FROM regexp_split_to_array(token, '\.') r; -$$; +$$ IMMUTABLE; diff --git a/pgjwt--0.1.1.sql b/pgjwt--0.1.1.sql new file mode 100644 index 0000000..d726438 --- /dev/null +++ b/pgjwt--0.1.1.sql @@ -0,0 +1,59 @@ +\echo Use "CREATE EXTENSION pgjwt" to load this file. \quit + + +CREATE OR REPLACE FUNCTION url_encode(data bytea) RETURNS text LANGUAGE sql AS $$ + SELECT translate(encode(data, 'base64'), E'+/=\n', '-_'); +$$ IMMUTABLE; + + +CREATE OR REPLACE FUNCTION url_decode(data text) RETURNS bytea LANGUAGE sql AS $$ +WITH t AS (SELECT translate(data, '-_', '+/') AS trans), + rem AS (SELECT length(t.trans) % 4 AS remainder FROM t) -- compute padding size + SELECT decode( + t.trans || + CASE WHEN rem.remainder > 0 + THEN repeat('=', (4 - rem.remainder)) + ELSE '' END, + 'base64') FROM t, rem; +$$ IMMUTABLE; + + +CREATE OR REPLACE FUNCTION algorithm_sign(signables text, secret text, algorithm text) +RETURNS text LANGUAGE sql AS $$ +WITH + alg AS ( + SELECT CASE + WHEN algorithm = 'HS256' THEN 'sha256' + WHEN algorithm = 'HS384' THEN 'sha384' + WHEN algorithm = 'HS512' THEN 'sha512' + ELSE '' END AS id) -- hmac throws error +SELECT @extschema@.url_encode(@extschema@.hmac(signables, secret, alg.id)) FROM alg; +$$ IMMUTABLE; + + +CREATE OR REPLACE FUNCTION sign(payload json, secret text, algorithm text DEFAULT 'HS256') +RETURNS text LANGUAGE sql AS $$ +WITH + header AS ( + SELECT @extschema@.url_encode(convert_to('{"alg":"' || algorithm || '","typ":"JWT"}', 'utf8')) AS data + ), + payload AS ( + SELECT @extschema@.url_encode(convert_to(payload::text, 'utf8')) AS data + ), + signables AS ( + SELECT header.data || '.' || payload.data AS data FROM header, payload + ) +SELECT + signables.data || '.' || + @extschema@.algorithm_sign(signables.data, secret, algorithm) FROM signables; +$$ IMMUTABLE; + + +CREATE OR REPLACE FUNCTION verify(token text, secret text, algorithm text DEFAULT 'HS256') +RETURNS table(header json, payload json, valid boolean) LANGUAGE sql AS $$ + SELECT + convert_from(@extschema@.url_decode(r[1]), 'utf8')::json AS header, + convert_from(@extschema@.url_decode(r[2]), 'utf8')::json AS payload, + r[3] = @extschema@.algorithm_sign(r[1] || '.' || r[2], secret, algorithm) AS valid + FROM regexp_split_to_array(token, '\.') r; +$$ IMMUTABLE; diff --git a/pgjwt.control b/pgjwt.control index 85bd1b3..52ce820 100644 --- a/pgjwt.control +++ b/pgjwt.control @@ -1,5 +1,5 @@ # pgjwt extension comment = 'JSON Web Token API for Postgresql' -default_version = '0.1.0' +default_version = '0.1.1' relocatable = false requires = pgcrypto