Merge branch 'master' into es17.05
This commit is contained in:
19
.travis.yml
19
.travis.yml
@@ -0,0 +1,19 @@
|
|||||||
|
language: eiffel
|
||||||
|
before_script:
|
||||||
|
- export current_dir=$PWD ; echo current_dir=$current_dir ; cd ..
|
||||||
|
- export ISE_VERSION=17.05; export ISE_BUILD=100416
|
||||||
|
- curl -sSL http://downloads.sourceforge.net/eiffelstudio/Eiffel_${ISE_VERSION}_gpl_${ISE_BUILD}-linux-x86-64.tar.bz2 | tar -x --bzip2
|
||||||
|
- export ISE_EIFFEL=$PWD/Eiffel_${ISE_VERSION} ; export ISE_PLATFORM=linux-x86-64
|
||||||
|
- export PATH=$PATH:$ISE_EIFFEL/studio/spec/$ISE_PLATFORM/bin:$PATH:$ISE_EIFFEL/tools/spec/$ISE_PLATFORM/bin
|
||||||
|
- echo `ec -version`
|
||||||
|
- cd $current_dir
|
||||||
|
- echo Check projects compilation status...
|
||||||
|
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
- v1
|
||||||
|
|
||||||
|
script: compile_all -ecb -melt -list_failures -log_verbose -clean -options dotnet=false
|
||||||
|
group: stable
|
||||||
|
os: linux
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ It provides simple routine to perform http requests, and get response.
|
|||||||
- Eiffel Net library
|
- Eiffel Net library
|
||||||
- and optionally Eiffel NetSSL library to support `https://...`
|
- and optionally Eiffel NetSSL library to support `https://...`
|
||||||
|
|
||||||
|
* Note: set ciphers settings is supported only with libcurl implementation for now, net implementation
|
||||||
|
set all the ciphers as part of the OpenSSL initialization.
|
||||||
|
|
||||||
This means on Windows, do not forget to copy the libcurl.dll (and related) either in the same directory of the executable, or ensure the .dll are in the PATH environment.
|
This means on Windows, do not forget to copy the libcurl.dll (and related) either in the same directory of the executable, or ensure the .dll are in the PATH environment.
|
||||||
|
|
||||||
It is possible to exclude the libcurl implementation xor the Eiffel Net implementation:
|
It is possible to exclude the libcurl implementation xor the Eiffel Net implementation:
|
||||||
|
|||||||
@@ -16,8 +16,19 @@ feature -- Access
|
|||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
|
get (a_url: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||||
|
do
|
||||||
|
Result := new_session (a_url).get ("", ctx)
|
||||||
|
end
|
||||||
|
|
||||||
|
custom (a_method: READABLE_STRING_8; a_url: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||||
|
-- Response for `a_method' request based on `a_url' and optional `ctx'.
|
||||||
|
do
|
||||||
|
Result := new_session (a_url).custom (a_method, "", ctx)
|
||||||
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -31,7 +31,11 @@ feature {NONE} -- Initialization
|
|||||||
-- This can be used to reset/reinitialize Current with new url
|
-- This can be used to reset/reinitialize Current with new url
|
||||||
-- in the case of redirection.
|
-- in the case of redirection.
|
||||||
do
|
do
|
||||||
url := a_url
|
if a_url.starts_with ("http://") or a_url.starts_with ("http://") then
|
||||||
|
url := a_url
|
||||||
|
else
|
||||||
|
url := session.url (a_url, Void)
|
||||||
|
end
|
||||||
headers := session.headers.twin
|
headers := session.headers.twin
|
||||||
if ctx /= Void then
|
if ctx /= Void then
|
||||||
context := ctx
|
context := ctx
|
||||||
|
|||||||
@@ -272,6 +272,15 @@ feature -- Authentication
|
|||||||
-- Associated optional credentials value.
|
-- Associated optional credentials value.
|
||||||
-- Computed as `username':`password'.
|
-- Computed as `username':`password'.
|
||||||
|
|
||||||
|
ciphers_settings: detachable READABLE_STRING_8
|
||||||
|
-- SSL cipher preference lists
|
||||||
|
-- examples: DEFAULT, ALL, TLSv1
|
||||||
|
-- check https://www.openssl.org/docs/man1.1.0/apps/ciphers.html
|
||||||
|
--Warning At the moment only used for LIB_CURL_HTTP_CLIENT
|
||||||
|
--Warning Net implementation set all the ciphers using the OpenSSL at
|
||||||
|
--Warning initialization time.
|
||||||
|
|
||||||
|
|
||||||
feature -- Status setting
|
feature -- Status setting
|
||||||
|
|
||||||
set_is_debug (b: BOOLEAN)
|
set_is_debug (b: BOOLEAN)
|
||||||
@@ -401,6 +410,14 @@ feature -- Element change
|
|||||||
chunk_size := a_size
|
chunk_size := a_size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
set_ciphers_settings (a_ciphers_settings: READABLE_STRING_8)
|
||||||
|
-- Set 'ciphers_settings' with 'a_ciphers_settings'.
|
||||||
|
do
|
||||||
|
create {STRING_8} ciphers_settings.make_from_string (a_ciphers_settings)
|
||||||
|
ensure
|
||||||
|
cipher_settings_set: attached ciphers_settings as c_settings and then c_settings.same_string (a_ciphers_settings)
|
||||||
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
|||||||
@@ -372,6 +372,11 @@ feature -- Execution
|
|||||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_ssl_verifypeer, 0)
|
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_ssl_verifypeer, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--| Cipher List
|
||||||
|
if attached session.ciphers_settings as c_list then
|
||||||
|
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_ssl_cipher_list, c_list )
|
||||||
|
end
|
||||||
|
|
||||||
--| Request method
|
--| Request method
|
||||||
if request_method.is_case_insensitive_equal ("GET") then
|
if request_method.is_case_insensitive_equal ("GET") then
|
||||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpget, 1)
|
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpget, 1)
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ feature -- Access
|
|||||||
-- Get URL data
|
-- Get URL data
|
||||||
l_is_https := url.starts_with_general ("https://")
|
l_is_https := url.starts_with_general ("https://")
|
||||||
create l_uri.make_from_string (url)
|
create l_uri.make_from_string (url)
|
||||||
|
check valid_url: l_uri.is_valid end
|
||||||
l_port := l_uri.port
|
l_port := l_uri.port
|
||||||
if l_port = 0 then
|
if l_port = 0 then
|
||||||
if l_is_https then
|
if l_is_https then
|
||||||
|
|||||||
@@ -55,12 +55,19 @@ feature -- Secure connection Helpers
|
|||||||
end
|
end
|
||||||
|
|
||||||
set_secure_protocol_to_ssl_2_or_3
|
set_secure_protocol_to_ssl_2_or_3
|
||||||
-- Set `ssl_protocol' with `Ssl_23'.
|
-- Set `ssl_protocol' with `Ssl_23'.
|
||||||
do
|
-- Protocol not supported anymore.
|
||||||
set_secure_protocol ({SSL_PROTOCOL}.Ssl_23)
|
obsolete
|
||||||
end
|
"Use set_secure_protocol_to_tls_1_2 [2017-06-23]."
|
||||||
|
local
|
||||||
|
err: DEVELOPER_EXCEPTION
|
||||||
|
do
|
||||||
|
create err
|
||||||
|
err.set_description ("SSL_2 or SSL_3 are not supported anymore, upgrate to TLS set_secure_protocol_to_tls_1_2")
|
||||||
|
err.raise
|
||||||
|
end
|
||||||
|
|
||||||
set_secure_protocol_to_tls_1_0
|
set_secure_protocol_to_tls_1_0
|
||||||
-- Set `ssl_protocol' with `Tls_1_0'.
|
-- Set `ssl_protocol' with `Tls_1_0'.
|
||||||
do
|
do
|
||||||
set_secure_protocol ({SSL_PROTOCOL}.Tls_1_0)
|
set_secure_protocol ({SSL_PROTOCOL}.Tls_1_0)
|
||||||
@@ -176,7 +183,14 @@ feature -- Output
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others"
|
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
source: "[
|
||||||
|
Eiffel Software
|
||||||
|
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||||
|
Telephone 805-685-1006, Fax 805-685-6869
|
||||||
|
Website http://www.eiffel.com
|
||||||
|
Customer support http://support.eiffel.com
|
||||||
|
]"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
36
library/security/jwt/src/errors/jwt_mismatched_alg_error.e
Normal file
36
library/security/jwt/src/errors/jwt_mismatched_alg_error.e
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {JWT_MISMATCHED_ALG_ERROR}."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
JWT_MISMATCHED_ALG_ERROR
|
||||||
|
|
||||||
|
inherit
|
||||||
|
JWT_ERROR
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_alg, a_header_alg: READABLE_STRING_8)
|
||||||
|
do
|
||||||
|
alg := a_alg
|
||||||
|
header_alg := a_header_alg
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
alg: READABLE_STRING_8
|
||||||
|
|
||||||
|
header_alg: READABLE_STRING_8
|
||||||
|
|
||||||
|
id: STRING = "ALG_MISMATCH"
|
||||||
|
|
||||||
|
message: READABLE_STRING_8
|
||||||
|
do
|
||||||
|
Result := "Header alg [" + header_alg + "] does not match given alg [" + alg + "]!"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -59,6 +59,8 @@ feature -- Status report
|
|||||||
do
|
do
|
||||||
if attached claimset.issuer as iss then
|
if attached claimset.issuer as iss then
|
||||||
Result := a_issuer = Void or else a_issuer.same_string (iss)
|
Result := a_issuer = Void or else a_issuer.same_string (iss)
|
||||||
|
else
|
||||||
|
Result := a_issuer = Void
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -66,6 +68,8 @@ feature -- Status report
|
|||||||
do
|
do
|
||||||
if attached claimset.audience as aud then
|
if attached claimset.audience as aud then
|
||||||
Result := a_audience = Void or else a_audience.same_string (aud)
|
Result := a_audience = Void or else a_audience.same_string (aud)
|
||||||
|
else
|
||||||
|
Result := a_audience = Void
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -118,6 +122,11 @@ feature {JWT_UTILITIES} -- Error reporting
|
|||||||
l_errors.extend (err)
|
l_errors.extend (err)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
report_mismatched_alg_error (alg, a_header_alg: READABLE_STRING_8)
|
||||||
|
do
|
||||||
|
report_error (create {JWT_MISMATCHED_ALG_ERROR}.make (alg, a_header_alg))
|
||||||
|
end
|
||||||
|
|
||||||
report_unsupported_alg_error (alg: READABLE_STRING_8)
|
report_unsupported_alg_error (alg: READABLE_STRING_8)
|
||||||
do
|
do
|
||||||
report_error (create {JWT_UNSUPPORTED_ALG_ERROR}.make (alg))
|
report_error (create {JWT_UNSUPPORTED_ALG_ERROR}.make (alg))
|
||||||
|
|||||||
@@ -266,11 +266,10 @@ feature {NONE} -- Implementation
|
|||||||
|
|
||||||
base64_hmacsha256 (s: READABLE_STRING_8; a_secret: READABLE_STRING_8): STRING_8
|
base64_hmacsha256 (s: READABLE_STRING_8; a_secret: READABLE_STRING_8): STRING_8
|
||||||
local
|
local
|
||||||
hs256: HMAC_SHA256
|
ut: JWT_UTILITIES
|
||||||
do
|
do
|
||||||
create hs256.make_ascii_key (a_secret)
|
create ut
|
||||||
hs256.update_from_string (s)
|
Result := ut.base64_hmacsha256 (s, a_secret)
|
||||||
Result := hs256.base64_digest --lowercase_hexadecimal_string_digest
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
note
|
note
|
||||||
description: "Summary description for {JWT_LOADER}."
|
description: "Loader and verifier to JWT token."
|
||||||
author: ""
|
|
||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
EIS: "name=Known Critical vulnerabilities in JWT libs", "protocol=URI", "src=https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/"
|
||||||
|
|
||||||
class
|
class
|
||||||
JWT_LOADER
|
JWT_LOADER
|
||||||
@@ -12,9 +12,13 @@ inherit
|
|||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
token (a_token_input: READABLE_STRING_8; a_secret: READABLE_STRING_8; ctx: detachable JWT_CONTEXT): detachable JWT
|
token (a_token_input: READABLE_STRING_8; a_alg: detachable READABLE_STRING_8; a_verification_key: READABLE_STRING_8; ctx: detachable JWT_CONTEXT): detachable JWT
|
||||||
-- Decoded token from `a_token_input` given the secret `a_secret`, and optional context `ctx`
|
-- Decoded token from `a_token_input` given the verification key `a_verification_key` and optional (but recommended) signature algorithm `a_alg`, and optional context `ctx`
|
||||||
-- used to specify eventual issuer and various parameters.
|
-- used to specify eventual issuer and various parameters.
|
||||||
|
-- WARNING: passing Void for `a_alg` is not safe, as the server should know which alg he used for tokens,
|
||||||
|
-- leaving the possibility to use the header alg is dangerous as client may use "none" and then bypass verification!
|
||||||
|
require
|
||||||
|
a_valid_alg: a_alg /= Void implies is_supporting_signature_algorithm (a_alg)
|
||||||
local
|
local
|
||||||
jws: JWS
|
jws: JWS
|
||||||
i,j,n: INTEGER
|
i,j,n: INTEGER
|
||||||
@@ -29,20 +33,27 @@ feature -- Access
|
|||||||
l_enc_payload := a_token_input.substring (i + 1, j - 1)
|
l_enc_payload := a_token_input.substring (i + 1, j - 1)
|
||||||
l_signature := a_token_input.substring (j + 1, n)
|
l_signature := a_token_input.substring (j + 1, n)
|
||||||
create jws.make_with_json_payload (base64url_decode (l_enc_payload))
|
create jws.make_with_json_payload (base64url_decode (l_enc_payload))
|
||||||
|
|
||||||
alg := signature_algorithm_from_encoded_header (l_enc_header)
|
alg := signature_algorithm_from_encoded_header (l_enc_header)
|
||||||
jws.set_algorithm (alg)
|
if a_alg /= Void then
|
||||||
if alg = Void then
|
if alg /= Void and then not alg.is_case_insensitive_equal_general (a_alg) then
|
||||||
-- Use default
|
jws.report_mismatched_alg_error (a_alg, alg)
|
||||||
alg := alg_hs256
|
else
|
||||||
|
alg := a_alg
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if alg = Void then
|
||||||
|
-- Use default
|
||||||
|
alg := alg_hs256
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
jws.set_algorithm (alg)
|
||||||
check alg_set: alg /= Void end
|
check alg_set: alg /= Void end
|
||||||
if ctx = Void or else not ctx.validation_ignored then
|
if ctx = Void or else not ctx.validation_ignored then
|
||||||
if not is_supporting_signature_algorithm (alg) then
|
if not is_supporting_signature_algorithm (alg) then
|
||||||
jws.report_unsupported_alg_error (alg)
|
jws.report_unsupported_alg_error (alg)
|
||||||
alg := alg_hs256
|
alg := alg_hs256
|
||||||
end
|
end
|
||||||
if not l_signature.same_string (signature (l_enc_header, l_enc_payload, a_secret, alg)) then
|
if not l_signature.same_string (signature (l_enc_header, l_enc_payload, a_verification_key, alg)) then
|
||||||
jws.report_unverified_token_error
|
jws.report_unverified_token_error
|
||||||
end
|
end
|
||||||
if
|
if
|
||||||
|
|||||||
@@ -61,7 +61,33 @@ feature -- Encoding
|
|||||||
do
|
do
|
||||||
create hs256.make_ascii_key (a_secret)
|
create hs256.make_ascii_key (a_secret)
|
||||||
hs256.update_from_string (s)
|
hs256.update_from_string (s)
|
||||||
Result := hs256.base64_digest --lowercase_hexadecimal_string_digest
|
-- if Version >= EiffelStudio 17.11 then
|
||||||
|
-- Result := hs256.base64_digest --lowercase_hexadecimal_string_digest
|
||||||
|
-- else
|
||||||
|
Result := base64_bytes_encoded_string (hs256.digest)
|
||||||
|
-- end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
base64_bytes_encoded_string (a_bytes: SPECIAL [NATURAL_8]): STRING_8
|
||||||
|
-- Base64 string from `a_bytes`.
|
||||||
|
--| Note: to be removed when 17.11 is not latest release anymore.
|
||||||
|
local
|
||||||
|
s: STRING
|
||||||
|
i,n: INTEGER
|
||||||
|
do
|
||||||
|
from
|
||||||
|
i := 1
|
||||||
|
n := a_bytes.count
|
||||||
|
create s.make (n)
|
||||||
|
until
|
||||||
|
i > n
|
||||||
|
loop
|
||||||
|
s.append_code (a_bytes[i - 1])
|
||||||
|
i := i + 1
|
||||||
|
end
|
||||||
|
Result := (create {BASE64}).encoded_string (s)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Decoding
|
feature -- Decoding
|
||||||
|
|||||||
@@ -54,7 +54,14 @@ feature -- Test
|
|||||||
|
|
||||||
create jwt_loader
|
create jwt_loader
|
||||||
|
|
||||||
if attached jwt_loader.token (tok, "secret", Void) as l_tok then
|
-- Use header alg!
|
||||||
|
if attached jwt_loader.token (tok, Void, "secret", Void) as l_tok then
|
||||||
|
assert ("no error", not l_tok.has_error)
|
||||||
|
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Use given alg!
|
||||||
|
if attached jwt_loader.token (tok, jwt.algorithm, "secret", Void) as l_tok then
|
||||||
assert ("no error", not l_tok.has_error)
|
assert ("no error", not l_tok.has_error)
|
||||||
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||||
end
|
end
|
||||||
@@ -96,21 +103,21 @@ feature -- Test
|
|||||||
create jwt_loader
|
create jwt_loader
|
||||||
|
|
||||||
-- Test with validation + exp
|
-- Test with validation + exp
|
||||||
if attached jwt_loader.token (tok, "secret", Void) as l_tok then
|
if attached jwt_loader.token (tok, jwt.algorithm, "secret", Void) as l_tok then
|
||||||
assert ("no error", not l_tok.has_error)
|
assert ("no error", not l_tok.has_error)
|
||||||
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||||
end
|
end
|
||||||
|
|
||||||
create ctx
|
create ctx
|
||||||
ctx.set_time (now)
|
ctx.set_time (now)
|
||||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||||
assert ("no error", not l_tok.has_error)
|
assert ("no error", not l_tok.has_error)
|
||||||
end
|
end
|
||||||
|
|
||||||
dt := duplicated_time (now)
|
dt := duplicated_time (now)
|
||||||
dt.hour_add (5)
|
dt.hour_add (5)
|
||||||
ctx.set_time (dt)
|
ctx.set_time (dt)
|
||||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||||
assert ("exp error", l_tok.has_error)
|
assert ("exp error", l_tok.has_error)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -122,7 +129,7 @@ feature -- Test
|
|||||||
tok := jwt.encoded_string ("secret")
|
tok := jwt.encoded_string ("secret")
|
||||||
|
|
||||||
ctx.set_time (now)
|
ctx.set_time (now)
|
||||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||||
assert ("has nbf error", l_tok.has_error)
|
assert ("has nbf error", l_tok.has_error)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -130,7 +137,7 @@ feature -- Test
|
|||||||
dt.second_add (15)
|
dt.second_add (15)
|
||||||
ctx.set_time (dt)
|
ctx.set_time (dt)
|
||||||
|
|
||||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||||
assert ("has nbf error", l_tok.has_error)
|
assert ("has nbf error", l_tok.has_error)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -138,31 +145,51 @@ feature -- Test
|
|||||||
dt.minute_add (45)
|
dt.minute_add (45)
|
||||||
ctx.set_time (dt)
|
ctx.set_time (dt)
|
||||||
|
|
||||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||||
assert ("no error", not l_tok.has_error)
|
assert ("no error", not l_tok.has_error)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Test Issuer
|
-- Test Issuer
|
||||||
ctx.set_issuer ("urn:foobar")
|
ctx.set_issuer ("urn:foobar")
|
||||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||||
assert ("has iss error", l_tok.has_error)
|
assert ("has iss error", l_tok.has_error)
|
||||||
end
|
end
|
||||||
ctx.set_issuer ("urn:foo")
|
ctx.set_issuer ("urn:foo")
|
||||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||||
assert ("no error", not l_tok.has_error)
|
assert ("no error", not l_tok.has_error)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Test Audience
|
-- Test Audience
|
||||||
ctx.set_audience ("urn:foobar")
|
ctx.set_audience ("urn:foobar")
|
||||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||||
assert ("has aud error", l_tok.has_error)
|
assert ("has aud error", l_tok.has_error)
|
||||||
end
|
end
|
||||||
ctx.set_audience ("urn:foo")
|
ctx.set_audience ("urn:foo")
|
||||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||||
assert ("no error", not l_tok.has_error)
|
assert ("no error", not l_tok.has_error)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test_mismatched_alg_jwt
|
||||||
|
local
|
||||||
|
jwt: JWS
|
||||||
|
payload: STRING
|
||||||
|
tok: STRING
|
||||||
|
do
|
||||||
|
payload := "[
|
||||||
|
{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}
|
||||||
|
]"
|
||||||
|
|
||||||
|
create jwt.make_with_json_payload (payload)
|
||||||
|
jwt.set_algorithm ("none")
|
||||||
|
tok := jwt.encoded_string ("secret")
|
||||||
|
|
||||||
|
if attached (create {JWT_LOADER}).token (tok, "HS256", "secret", Void) as l_tok then
|
||||||
|
assert ("no error", not jwt.has_error)
|
||||||
|
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
test_unsecured_jwt
|
test_unsecured_jwt
|
||||||
local
|
local
|
||||||
jwt: JWS
|
jwt: JWS
|
||||||
@@ -177,7 +204,11 @@ feature -- Test
|
|||||||
jwt.set_algorithm ("none")
|
jwt.set_algorithm ("none")
|
||||||
tok := jwt.encoded_string ("secret")
|
tok := jwt.encoded_string ("secret")
|
||||||
|
|
||||||
if attached (create {JWT_LOADER}).token (tok, "secret", Void) as l_tok then
|
if attached (create {JWT_LOADER}).token (tok, "none", "secret", Void) as l_tok then
|
||||||
|
assert ("no error", not jwt.has_error)
|
||||||
|
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||||
|
end
|
||||||
|
if attached (create {JWT_LOADER}).token (tok, Void, "secret", Void) as l_tok then
|
||||||
assert ("no error", not jwt.has_error)
|
assert ("no error", not jwt.has_error)
|
||||||
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -76,13 +76,13 @@ feature -- Initialization
|
|||||||
a_http_authorization /= Void implies http_authorization /= Void
|
a_http_authorization /= Void implies http_authorization /= Void
|
||||||
end
|
end
|
||||||
|
|
||||||
make_basic_auth (u: READABLE_STRING_32; p: READABLE_STRING_32)
|
make_basic_auth (u: READABLE_STRING_GENERAL; p: READABLE_STRING_GENERAL)
|
||||||
-- Create a Basic authentication.
|
-- Create a Basic authentication.
|
||||||
do
|
do
|
||||||
make_custom_auth (u, p, Basic_auth_type)
|
make_custom_auth (u, p, Basic_auth_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
make_custom_auth (u: READABLE_STRING_32; p: READABLE_STRING_32; a_type: READABLE_STRING_8)
|
make_custom_auth (u: READABLE_STRING_GENERAL; p: READABLE_STRING_GENERAL; a_type: READABLE_STRING_8)
|
||||||
-- Create a custom `a_type' authentication.
|
-- Create a custom `a_type' authentication.
|
||||||
require
|
require
|
||||||
a_type_accepted: a_type.is_case_insensitive_equal (Basic_auth_type)
|
a_type_accepted: a_type.is_case_insensitive_equal (Basic_auth_type)
|
||||||
@@ -90,15 +90,20 @@ feature -- Initialization
|
|||||||
local
|
local
|
||||||
t: STRING_8
|
t: STRING_8
|
||||||
utf: UTF_CONVERTER
|
utf: UTF_CONVERTER
|
||||||
|
s: STRING_32
|
||||||
do
|
do
|
||||||
login := u
|
create login.make_from_string_general (u)
|
||||||
password := p
|
create password.make_from_string_general (p)
|
||||||
create t.make_from_string (a_type)
|
create t.make_from_string (a_type)
|
||||||
t.left_adjust; t.right_adjust
|
t.left_adjust; t.right_adjust
|
||||||
type := t
|
type := t
|
||||||
if t.is_case_insensitive_equal (Basic_auth_type) then
|
if t.is_case_insensitive_equal (Basic_auth_type) then
|
||||||
type := Basic_auth_type
|
type := Basic_auth_type
|
||||||
create http_authorization.make_from_string ("Basic " + (create {BASE64}).encoded_string (utf.string_32_to_utf_8_string_8 (u + {STRING_32} ":" + p)))
|
create s.make_from_string_general (u)
|
||||||
|
s.extend (':')
|
||||||
|
s.append_string_general (p)
|
||||||
|
create http_authorization.make_from_string ("Basic " + (create {BASE64}).encoded_string (utf.string_32_to_utf_8_string_8 (s)))
|
||||||
|
|
||||||
elseif t.is_case_insensitive_equal (Digest_auth_type) then
|
elseif t.is_case_insensitive_equal (Digest_auth_type) then
|
||||||
type := Digest_auth_type
|
type := Digest_auth_type
|
||||||
to_implement ("HTTP Authorization %""+ t +"%", not yet implemented")
|
to_implement ("HTTP Authorization %""+ t +"%", not yet implemented")
|
||||||
@@ -115,9 +120,9 @@ feature -- Access
|
|||||||
|
|
||||||
type: READABLE_STRING_8
|
type: READABLE_STRING_8
|
||||||
|
|
||||||
login: detachable READABLE_STRING_32
|
login: detachable IMMUTABLE_STRING_32
|
||||||
|
|
||||||
password: detachable READABLE_STRING_32
|
password: detachable IMMUTABLE_STRING_32
|
||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ feature -- Element change
|
|||||||
end
|
end
|
||||||
|
|
||||||
set_socket_timeout (a_nb_seconds: like socket_timeout)
|
set_socket_timeout (a_nb_seconds: like socket_timeout)
|
||||||
-- Set `socket_timeout' with `a_nb_seconds'
|
-- Set `socket_timeout' with `a_nb_seconds'.
|
||||||
do
|
do
|
||||||
socket_timeout := a_nb_seconds
|
socket_timeout := a_nb_seconds
|
||||||
ensure
|
ensure
|
||||||
@@ -175,7 +175,7 @@ feature -- Element change
|
|||||||
end
|
end
|
||||||
|
|
||||||
set_socket_recv_timeout (a_nb_seconds: like socket_recv_timeout)
|
set_socket_recv_timeout (a_nb_seconds: like socket_recv_timeout)
|
||||||
-- Set `socket_recv_timeout' with `a_nb_seconds'
|
-- Set `socket_recv_timeout' with `a_nb_seconds'.
|
||||||
do
|
do
|
||||||
socket_recv_timeout := a_nb_seconds
|
socket_recv_timeout := a_nb_seconds
|
||||||
ensure
|
ensure
|
||||||
@@ -183,7 +183,7 @@ feature -- Element change
|
|||||||
end
|
end
|
||||||
|
|
||||||
set_keep_alive_timeout (a_seconds: like keep_alive_timeout)
|
set_keep_alive_timeout (a_seconds: like keep_alive_timeout)
|
||||||
-- Set `keep_alive_timeout' with `a_seconds'
|
-- Set `keep_alive_timeout' with `a_seconds'.
|
||||||
do
|
do
|
||||||
keep_alive_timeout := a_seconds
|
keep_alive_timeout := a_seconds
|
||||||
ensure
|
ensure
|
||||||
@@ -191,7 +191,7 @@ feature -- Element change
|
|||||||
end
|
end
|
||||||
|
|
||||||
set_max_keep_alive_requests (nb: like max_keep_alive_requests)
|
set_max_keep_alive_requests (nb: like max_keep_alive_requests)
|
||||||
-- Set `max_keep_alive_requests' with `nb'
|
-- Set `max_keep_alive_requests' with `nb'.
|
||||||
do
|
do
|
||||||
max_keep_alive_requests := nb
|
max_keep_alive_requests := nb
|
||||||
ensure
|
ensure
|
||||||
@@ -254,7 +254,7 @@ feature -- Element change
|
|||||||
end
|
end
|
||||||
|
|
||||||
mark_secure
|
mark_secure
|
||||||
-- Set is_secure in True
|
-- Set is_secure in True.
|
||||||
do
|
do
|
||||||
set_is_secure (True)
|
set_is_secure (True)
|
||||||
ensure
|
ensure
|
||||||
@@ -287,7 +287,7 @@ feature -- Element change
|
|||||||
end
|
end
|
||||||
|
|
||||||
set_secure_protocol (a_version: NATURAL)
|
set_secure_protocol (a_version: NATURAL)
|
||||||
-- Set `secure_protocol' with `a_version'
|
-- Set `secure_protocol' with `a_version'.
|
||||||
do
|
do
|
||||||
secure_protocol := a_version
|
secure_protocol := a_version
|
||||||
ensure
|
ensure
|
||||||
@@ -295,7 +295,7 @@ feature -- Element change
|
|||||||
end
|
end
|
||||||
|
|
||||||
set_secure_protocol_from_string (a_ssl_version: READABLE_STRING_GENERAL)
|
set_secure_protocol_from_string (a_ssl_version: READABLE_STRING_GENERAL)
|
||||||
-- Set `secure_protocol' with `a_ssl_version'
|
-- Set `secure_protocol' with `a_ssl_version'.
|
||||||
do
|
do
|
||||||
if a_ssl_version.is_case_insensitive_equal ("ssl_2_3") then
|
if a_ssl_version.is_case_insensitive_equal ("ssl_2_3") then
|
||||||
set_secure_protocol_to_ssl_2_or_3
|
set_secure_protocol_to_ssl_2_or_3
|
||||||
@@ -316,6 +316,8 @@ feature -- SSL Helpers
|
|||||||
|
|
||||||
set_secure_protocol_to_ssl_2_or_3
|
set_secure_protocol_to_ssl_2_or_3
|
||||||
-- Set `secure_protocol' with `Ssl_23'.
|
-- Set `secure_protocol' with `Ssl_23'.
|
||||||
|
obsolete
|
||||||
|
"Use set_secure_protocol_to_tls_1_2 [2017-06-23]."
|
||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -36,9 +36,16 @@ feature -- Access
|
|||||||
feature -- SSL Helpers
|
feature -- SSL Helpers
|
||||||
|
|
||||||
set_secure_protocol_to_ssl_2_or_3
|
set_secure_protocol_to_ssl_2_or_3
|
||||||
-- Set `secure_protocol' with `Ssl_23'.
|
-- Set `ssl_protocol' with `Ssl_23'.
|
||||||
|
-- Protocol not supported anymore.
|
||||||
|
obsolete
|
||||||
|
"Use set_secure_protocol_to_tls_1_2 [2017-06-23]."
|
||||||
|
local
|
||||||
|
err: DEVELOPER_EXCEPTION
|
||||||
do
|
do
|
||||||
set_secure_protocol ({SSL_PROTOCOL}.Ssl_23)
|
create err
|
||||||
|
err.set_description ("SSL_2 or SSL_3 are not supported anymore, upgrate to TLS set_secure_protocol_to_tls_1_2")
|
||||||
|
err.raise
|
||||||
end
|
end
|
||||||
|
|
||||||
set_secure_protocol_to_tls_1_0
|
set_secure_protocol_to_tls_1_0
|
||||||
@@ -67,7 +74,7 @@ feature -- SSL Helpers
|
|||||||
|
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
</option>
|
</option>
|
||||||
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone.ecf" readonly="false" use_application_options="true"/>
|
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone.ecf" readonly="false" use_application_options="true"/>
|
||||||
<cluster name="src" location="src\" recursive="true"/>
|
<cluster name="src" location="src\" recursive="true"/>
|
||||||
<override name="override" location="override\" recursive="true"/>
|
|
||||||
</target>
|
</target>
|
||||||
<target name="hello_cgi" extends="hello_dev">
|
<target name="hello_cgi" extends="hello_dev">
|
||||||
<library name="default_cgi" location="..\..\library\server\wsf\default\cgi.ecf"/>
|
<library name="default_cgi" location="..\..\library\server\wsf\default\cgi.ecf"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user