codemonth.dk

One project every month - making stuff better ...

Completing JWT_NINjA for full JWT support

In the single blog post I wrote on the JWT_NINJA package back in June last year, I ended the post by saying that I needed to implement both a verify and a parse function for the package.

Well, it took me a year, but I finally had a reason to go and implement it. As I am getting into Oracle ORDS and trying to get some experience in building REST services, I want to be able to use JWT as the token generator for the application that I am building.

So a quick refresh on how to generate a token using the package:


select jwt_ninja.jwt_generate(p_signature_key => 'my secret password', p_reg_claim_issuer => 'My Application', p_reg_claim_subject => '147654') as token from dual;

TOKEN 
-------------------------------------------------------------------------------------------------------------------------------------
eyAiYWxnIjogIkhTMjU2IiwgInR5cCI6ICJKV1QiIH0.eyAiaWF0IjogMTQ5MTcxNzIxODAwMCwgImlzcyI6ICJNeSBBcHBsaWNhdGlvbiIs
ICJzdWIiOiAiMTQ3NjU0In0.Uy6KeKeO1/52+URTbhk1+spOIO3OYamLhViPJ1ZmjUU 

So now that we have a token, we would store that on the client side, and every request from the client would include this token for us to validate. So to validate the token there is now a procedure jwt_ninja.jwt_verify_and_decode that will do just that. The third argument (p_do_parse) indicates if you only want the token to be verified or if you want to parse the fields inside the payload. The default is to only verify the validity of the signature and the message and not do the parse. If it is set to true, the values of the different JWT claims will be set and found in the output parameters of the procedure.


declare
  mysecret varchar2(4000) := 'my secret password';
  mytoken varchar2(4000) := jwt_ninja.jwt_generate(p_signature_key => 'my secret password', p_reg_claim_issuer => 'My Application', p_reg_claim_subject => '147654');
  doparse boolean := false;
  myresult boolean;
  l_reg_claim_issuer      varchar2(4000) := null;
  l_reg_claim_subject     varchar2(4000) := null;
  l_reg_claim_audience    varchar2(4000) := null;
  l_reg_claim_expiration  date := null;
  l_reg_claim_notbefore   date := null;
  l_reg_claim_issuedat    date := null;
  l_reg_claim_jwtid       varchar2(4000) := null;
begin
  jwt_ninja.jwt_verify_and_decode(mytoken, mysecret, doparse, myresult, l_reg_claim_issuer, l_reg_claim_subject, l_reg_claim_audience, l_reg_claim_expiration, l_reg_claim_notbefore, l_reg_claim_issuedat, l_reg_claim_jwtid);
  if myresult then
    dbms_output.put_line('Verified');
    dbms_output.put_line('Iss: ' || l_reg_claim_issuer);
    dbms_output.put_line('Sub: ' || l_reg_claim_subject);
  else
    dbms_output.put_line('Not verified');
  end if;
end;
/

So know I can "close" this codemonth for now, since I can start to use it in my other project.

JWT - JSON Web Tokens

After having worked on a couple of SAML issues, trying to debug some encryption errors, I was getting really tired of really big SAML messages.

So I started looking around for alternatives, and found the JWT website. A lot more straight forward and plenty secure for what most people are looking to do with security tokens.

To quote from the website:

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA.

  • Compact: Because of its smaller size, JWTs can be sent through an URL, POST parameter, or inside an HTTP header. Additionally, the smaller size means transmission is fast.
  • Self-contained: The payload contains all the required information about the user, avoiding the need to query the database more than once.