292 lines
9.0 KiB
Plaintext
292 lines
9.0 KiB
Plaintext
note
|
|
description: "Object representing a JWT claim set"
|
|
date: "$Date$"
|
|
revision: "$Revision$"
|
|
EIS: "name=JWT claims", "src=https://tools.ietf.org/html/rfc7519#section-4", "protocol=uri"
|
|
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_issued_at_now_utc
|
|
do
|
|
set_issued_at (create {DATE_TIME}.make_now_utc)
|
|
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
|