For a long time Basic Auth was the defacto standard in authentication when it comes to HTTP and the web. But those times are fast fading into oblivion as standards like OAuth and JWT have established themselves very well.

ILEastic has supported Basic Auth and JWT authentication for some time now. Recently the JWT plugin has gotten a contribution which has now been adapted to the rest of the ILEastic code base. The adaption resulted in an incompatible API to the last version but added support for RSA asymmetric algorithm.

The new JWT service program version supports the following algorithms for verification:

  • HS256
  • HS384
  • HS512
  • RS256
  • RS384
  • RS512

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
**FREE

ctl-opt dftactgrp(*no) actgrp(*caller) main(main) bnddir('ILEASTIC');


/include 'ileastic.rpgle'
/include 'jwt.rpginc'
/include 'jwtplugin.rpginc'


dcl-proc main;
dcl-ds config likeds(IL_CONFIG);
dcl-ds jwtOptions likeds(jwt_options_t) inz;

config.port = 35801;
config.host = '*ANY';

jwtOptions.key = 'my_really_secret_key_which_must_be_at_least_32_chars_long';
il_jwt_addVerifyOptions(jwtOptions);
il_addPlugin(config : %paddr('il_jwt_filter') : IL_PREREQUEST);

il_addRoute(config : %paddr(sayHello) : IL_GET : '/hello');

il_listen (config);
end-proc;


dcl-proc sayHello;
dcl-pi *n;
request likeds(IL_REQUEST);
response likeds(IL_RESPONSE);
end-pi;

dcl-s name varchar(100);

name = il_getQueryParameter(request : 'name' : 'World');

response.contentType = 'text/plain';
il_responseWrite(response : 'Hello ' + name);
end-proc;

Load Sign Key from Stream File

In the example above the key for verifying the JWT token signature is directly set in the code. Normally you wouldn’t do this. The key would be loaded from some external source like a file so that it could be changed without the need to change and recompile the whole program. The JWT plugin directly supports loading the key from a stream file like this:

1
jwtOptions.key = il_jwt_loadKeyFromStreamFile('/path/to/signkey/file');

The content of the file will be read in binary mode. There will be no character conversion. If it is a sign key for the HS algorithm or a RSA public key (PEM format) the content should be in an ASCII compatible character set like 1208 (UTF-8) or 1252 (Latin1).

JWT Algorithm “none”

Besides the listed supported algorithms for JWT tokens it is also worthy to mention that the JWT algorithm “none” will always be rejected as it is considered insecure.

Specific JWT Algorithm

To make things even more secure you can optionally specify a JWT algorithm in the options. JWT tokens with a different algorithm will be rejected.

1
jwtOptions.alg = JWT_RS256;

Multi-Tenant Support

Previously only a single key could be configured for JWT verification. Now multiple keys can be added to the JWT plugin configuration by adding an id on registration.

1
2
3
4
5
jwtOptions.key = il_jwt_loadKeyFromStreamFile('/var/local/etc/rpgenxtgen.pub');
il_jwt_addVerifyOptions(jwtOptions : 'https://rpgnextgen.com');

jwtOptions.key = il_jwt_loadKeyFromStreamFile('/var/local/etc/sitemule.pub');
il_jwt_addVerifyOptions(jwtOptions : 'https://sitemule.com');

But how will ILEastic decide which key to use for JWT verification? ILEastic supports the lookup of the key by the “kid” attribute in the JWT header and by the issuer claim (iss) in the payload. The value of the id must match with the value of the attribute from the JWT token.

The method of verify options lookup can be set with the following code:

1
il_jwt_setVerifyOptionsLookupMethod(JWT_VERIFY_OPTIONS_LOOKUP_ISSUER);

JWT payload:

1
2
3
4
{
"sub" : "mihael@rpgnextgen.com",
"iss" : "https://rpgnextgen.com",
}

The above payload of a JWT token would match the first configuration because the issuer claim matches the id (second parameter) on the il_jwt_addVerifyOptions call.

Wrap Up

Besides some changes in the length of some template variables the JWT plugin has gotten some major update. Thanks for the contributions.

Happy web serving!

Mihael