Updated JWT library, add supports for claim exp, iat, nbf, iss, aud .
This commit is contained in:
287
library/security/jwt/src/jwt_claimset.e
Normal file
287
library/security/jwt/src/jwt_claimset.e
Normal file
@@ -0,0 +1,287 @@
|
||||
note
|
||||
description: "Summary description for {JWT_CLAIMSET}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
JWT_CLAIMSET
|
||||
|
||||
inherit
|
||||
ANY
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
convert
|
||||
string: {READABLE_STRING_8, STRING_8}
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
create json.make_empty
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
import_json (j: READABLE_STRING_8)
|
||||
local
|
||||
jp: JSON_PARSER
|
||||
do
|
||||
create jp.make_with_string (j)
|
||||
jp.parse_content
|
||||
if jp.is_valid and then attached jp.parsed_json_object as jo then
|
||||
across
|
||||
jo as ic
|
||||
loop
|
||||
json.put (ic.item, ic.key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
claim alias "[]" (a_name: READABLE_STRING_GENERAL): detachable ANY
|
||||
do
|
||||
if attached json.item (a_name) as jv then
|
||||
if attached {JSON_STRING} jv as js then
|
||||
Result := js.unescaped_string_32
|
||||
elseif attached {JSON_BOOLEAN} jv as jb then
|
||||
Result := jb.item
|
||||
elseif attached {JSON_NUMBER} jv as jnum then
|
||||
if jnum.is_integer then
|
||||
Result := jnum.integer_64_item
|
||||
elseif jnum.is_natural then
|
||||
Result := jnum.natural_64_item
|
||||
elseif jnum.is_real then
|
||||
Result := jnum.real_64_item
|
||||
else
|
||||
Result := jnum.item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
string_32_claim (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
do
|
||||
if attached json.item (a_name) as jv then
|
||||
if attached {JSON_STRING} jv as js then
|
||||
Result := js.unescaped_string_32
|
||||
elseif attached {JSON_BOOLEAN} jv as jb then
|
||||
Result := jb.item.out
|
||||
elseif attached {JSON_NUMBER} jv as jnum then
|
||||
Result := jnum.item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
string_8_claim (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
|
||||
do
|
||||
if attached json.item (a_name) as jv then
|
||||
if attached {JSON_STRING} jv as js then
|
||||
Result := js.unescaped_string_8
|
||||
elseif attached {JSON_BOOLEAN} jv as jb then
|
||||
Result := jb.item.out
|
||||
elseif attached {JSON_NUMBER} jv as jnum then
|
||||
Result := jnum.item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
issuer: detachable READABLE_STRING_8 assign set_issuer
|
||||
do
|
||||
Result := string_8_claim ("iss")
|
||||
end
|
||||
|
||||
subjet: detachable READABLE_STRING_32 assign set_subject
|
||||
do
|
||||
Result := string_32_claim ("sub")
|
||||
end
|
||||
|
||||
audience: detachable READABLE_STRING_8 assign set_audience
|
||||
do
|
||||
Result := string_8_claim ("aud")
|
||||
end
|
||||
|
||||
expiration_time: detachable DATE_TIME assign set_expiration_time
|
||||
do
|
||||
if attached {INTEGER_64} claim ("exp") as i64 then
|
||||
Result := numeric_date_value_to_datetime (i64)
|
||||
end
|
||||
end
|
||||
|
||||
not_before_time: detachable DATE_TIME assign set_not_before_time
|
||||
do
|
||||
if attached {INTEGER_64} claim ("nbf") as i64 then
|
||||
Result := numeric_date_value_to_datetime (i64)
|
||||
end
|
||||
end
|
||||
|
||||
issued_at: detachable DATE_TIME assign set_issued_at
|
||||
do
|
||||
if attached {INTEGER_64} claim ("iat") as i then
|
||||
Result := numeric_date_value_to_datetime (i)
|
||||
end
|
||||
end
|
||||
|
||||
jwd_id: detachable READABLE_STRING_8 assign set_jwt_id
|
||||
do
|
||||
Result := string_8_claim ("jti")
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
json: JSON_OBJECT
|
||||
|
||||
string: STRING
|
||||
do
|
||||
Result := json.representation
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_claim (a_name: READABLE_STRING_GENERAL; a_val: detachable ANY)
|
||||
do
|
||||
if a_val = Void then
|
||||
json.remove (a_name)
|
||||
elseif attached {READABLE_STRING_GENERAL} a_val as str then
|
||||
json.put_string (str, a_name)
|
||||
elseif attached {BOOLEAN} a_val as b then
|
||||
json.put_boolean (b, a_name)
|
||||
elseif attached {DATE_TIME} a_val as dt then
|
||||
json.put_integer (datetime_to_numeric_date_value (dt), a_name)
|
||||
elseif attached {DATE} a_val as d then
|
||||
json.put_integer (datetime_to_numeric_date_value (create {DATE_TIME}.make_by_date (d)), a_name)
|
||||
elseif attached {NUMERIC} a_val as num then
|
||||
if attached {INTEGER_64} num as i64 then
|
||||
json.put_integer (i64, a_name)
|
||||
elseif attached {INTEGER_32} num as i32 then
|
||||
json.put_integer (i32.to_integer_64, a_name)
|
||||
elseif attached {NATURAL_64} num as n64 then
|
||||
json.put_natural (n64, a_name)
|
||||
elseif attached {INTEGER_32} num as n32 then
|
||||
json.put_natural (n32.to_natural_64, a_name)
|
||||
elseif attached {REAL_64} num as r64 then
|
||||
json.put_real (r64, a_name)
|
||||
elseif attached {REAL_32} num as r32 then
|
||||
json.put_real (r32, a_name)
|
||||
else
|
||||
json.put_string (a_val.out, a_name)
|
||||
end
|
||||
else
|
||||
json.put_string (a_val.out, a_name)
|
||||
end
|
||||
end
|
||||
|
||||
set_issuer (iss: detachable READABLE_STRING_8)
|
||||
-- The "iss" (issuer) claim identifies the principal that issued the
|
||||
-- JWT. The processing of this claim is generally application specific.
|
||||
-- The "iss" value is a case-sensitive string containing a StringOrURI
|
||||
-- value. Use of this claim is OPTIONAL.
|
||||
do
|
||||
set_claim ("iss", iss)
|
||||
end
|
||||
|
||||
set_subject (sub: detachable READABLE_STRING_32)
|
||||
-- The "sub" (subject) claim identifies the principal that is the
|
||||
-- subject of the JWT. The claims in a JWT are normally statements
|
||||
-- about the subject. The subject value MUST either be scoped to be
|
||||
-- locally unique in the context of the issuer or be globally unique.
|
||||
-- The processing of this claim is generally application specific. The
|
||||
-- "sub" value is a case-sensitive string containing a StringOrURI
|
||||
-- value. Use of this claim is OPTIONAL.
|
||||
do
|
||||
set_claim ("sub", sub)
|
||||
end
|
||||
|
||||
set_audience (aud: detachable READABLE_STRING_8)
|
||||
-- The "aud" (audience) claim identifies the recipients that the JWT is
|
||||
-- intended for. Each principal intended to process the JWT MUST
|
||||
-- identify itself with a value in the audience claim. If the principal
|
||||
-- processing the claim does not identify itself with a value in the
|
||||
-- "aud" claim when this claim is present, then the JWT MUST be
|
||||
-- rejected. In the general case, the "aud" value is an array of case-
|
||||
-- sensitive strings, each containing a StringOrURI value. In the
|
||||
-- special case when the JWT has one audience, the "aud" value MAY be a
|
||||
-- single case-sensitive string containing a StringOrURI value. The
|
||||
-- interpretation of audience values is generally application specific.
|
||||
-- Use of this claim is OPTIONAL.
|
||||
do
|
||||
set_claim ("aud", aud)
|
||||
end
|
||||
|
||||
set_expiration_time (exp: detachable DATE_TIME)
|
||||
-- The "exp" (expiration time) claim identifies the expiration time on
|
||||
-- or after which the JWT MUST NOT be accepted for processing. The
|
||||
-- processing of the "exp" claim requires that the current date/time
|
||||
-- MUST be before the expiration date/time listed in the "exp" claim.
|
||||
-- Implementers MAY provide for some small leeway, usually no more than
|
||||
-- a few minutes, to account for clock skew. Its value MUST be a number
|
||||
-- containing a NumericDate value. Use of this claim is OPTIONAL.
|
||||
do
|
||||
if exp = Void then
|
||||
set_claim ("exp", Void)
|
||||
else
|
||||
set_claim ("exp", datetime_to_numeric_date_value (exp))
|
||||
end
|
||||
end
|
||||
|
||||
set_not_before_time (nbf: detachable DATE_TIME)
|
||||
-- The "nbf" (not before) claim identifies the time before which the JWT
|
||||
-- MUST NOT be accepted for processing. The processing of the "nbf"
|
||||
-- claim requires that the current date/time MUST be after or equal to
|
||||
-- the not-before date/time listed in the "nbf" claim. Implementers MAY
|
||||
-- provide for some small leeway, usually no more than a few minutes, to
|
||||
-- account for clock skew. Its value MUST be a number containing a
|
||||
-- NumericDate value. Use of this claim is OPTIONAL.
|
||||
do
|
||||
if nbf = Void then
|
||||
set_claim ("nbf", Void)
|
||||
else
|
||||
set_claim ("nbf", datetime_to_numeric_date_value (nbf))
|
||||
end
|
||||
end
|
||||
|
||||
set_issued_at (iat: detachable DATE_TIME)
|
||||
-- The "iat" (issued at) claim identifies the time at which the JWT was
|
||||
-- issued. This claim can be used to determine the age of the JWT. Its
|
||||
-- value MUST be a number containing a NumericDate value. Use of this
|
||||
-- claim is OPTIONAL.
|
||||
do
|
||||
if iat = Void then
|
||||
set_claim ("iat", Void)
|
||||
else
|
||||
set_claim ("iat", datetime_to_numeric_date_value (iat))
|
||||
end
|
||||
end
|
||||
|
||||
set_jwt_id (jti: detachable READABLE_STRING_8)
|
||||
-- The "jti" (JWT ID) claim provides a unique identifier for the JWT.
|
||||
-- The identifier value MUST be assigned in a manner that ensures that
|
||||
-- there is a negligible probability that the same value will be
|
||||
-- accidentally assigned to a different data object; if the application
|
||||
-- uses multiple issuers, collisions MUST be prevented among values
|
||||
-- produced by different issuers as well. The "jti" claim can be used
|
||||
-- to prevent the JWT from being replayed. The "jti" value is a case-
|
||||
-- sensitive string. Use of this claim is OPTIONAL.
|
||||
do
|
||||
set_claim ("jti", jti)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
numeric_date_value_to_datetime (v: INTEGER_64): DATE_TIME
|
||||
do
|
||||
create Result.make_from_epoch (v.to_integer_32)
|
||||
end
|
||||
|
||||
datetime_to_numeric_date_value (dt: DATE_TIME): INTEGER_64
|
||||
do
|
||||
Result := dt.definite_duration (create {DATE_TIME}.make_from_epoch (0)).seconds_count
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user