NetTalk Central

Author Topic: JWT Json Web Token  (Read 6042 times)

ntnewbies

  • Full Member
  • ***
  • Posts: 184
    • View Profile
    • Email
JWT Json Web Token
« on: July 20, 2021, 01:51:35 AM »
hi
i need to Create the JWT token (https://jwt.io/) with the following claims:

{
    "iss": "your_api_key",
    "ist": "project",
    "iat": current_timestamp_in_seconds,
    "exp": expire_timestamp_in_seconds,
    "jti": "jwt_nonce"
}


i was told to run a phyton script to get the token

import jwt
import time
import uuid
print jwt.encode({"iss": "my-account-API-key",
    "iat": int(time.time()),
    "exp": int(time.time()) + 180,
    "ist": "project",
    "jti": str(uuid.uuid4())},
    'my-API-secret',
    algorithm='HS256')

how to do this in nettalk??

jason
c11
nt11.51

bshields

  • Sr. Member
  • ****
  • Posts: 392
    • View Profile
    • Inhabit
    • Email
Re: JWT Json Web Token
« Reply #1 on: July 20, 2021, 06:12:54 AM »
Hi Jason,

This is me creating a JWT token for Twilio's Chat API system.


CreateTwilioToken    PROCEDURE  (STRING lAccountSID,STRING lAPIKey,STRING lAPISecret,STRING lServiceSID,STRING lPushSID,STRING lIdentity)
stHeader      StringTheory
stPayload     StringTheory 
stToEncrypt   StringTheory
stSignature   StringTheory

Crypto        Cryptonite

  CODE
  stHeader.SetValue('{{"typ":"JWT","alg":"HS256","cty":"twilio-fpa;v=1"}')

  stPayload.SetValue('{{"jti":"'&CLIP(lAPIKey)&'-'&RANDOM(100000000,999999999)&'",'&|
                       '"iss":"'&CLIP(lAPIKey)&'",'&|
                       '"sub":"'&CLIP(lAccountSID)&'",'&|
                       '"iat":'&TimestampZ()-(GETINI('Server','Timezone',0,GLO:INIFilename)*3600)&','&|
                       '"exp":'&TimestampZ()+3600-(GETINI('Server','Timezone',0,GLO:INIFilename)*3600)&','&|
                       '"grants":{{'&|
                       '"identity":"'&CLIP(lIdentity)&'",'&|
                       '"chat":{{'&|
                         '"service_sid":"'&CLIP(lServiceSID)&'",'&|
                         '"push_credential_sid":"'&CLIP(lPushSID)&'"'&|
                       '}}}')
                       
  stHeader.Base64Encode(1)
  stHeader.Replace('+','-')
  stHeader.Replace('/','_')
  stHeader.Replace('=','')
  stPayload.Base64Encode(1)
  stPayload.Replace('+','-')
  stPayload.Replace('/','_')
  stPayload.Replace('=','')
  stToEncrypt.SetValue(stHeader.GetValue()&'.'&stPayload.GetValue())
 
  Crypto.MakeHMAC(stToEncrypt,CLIP(lAPISecret),cs:CALG_SHA_256,0)
  stToEncrypt.Base64Encode(1)
  stToEncrypt.Replace('+','-')
  stToEncrypt.Replace('/','_')
  stToEncrypt.Replace('=','')
 
 
  RETURN stHeader.GetValue()&'.'&stPayload.GetValue()&'.'&stToEncrypt.GetValue()



I'm in a hurry tonight getting a build out. But, if you want the exact code, ask me on Slack.

Regards
Bill

bshields

  • Sr. Member
  • ****
  • Posts: 392
    • View Profile
    • Inhabit
    • Email
Re: JWT Json Web Token
« Reply #2 on: July 21, 2021, 03:19:36 AM »
Hi Jason,

I thought I should post the solution here incase anyone was interested (after we worked through it on Slack).

TestVonage           PROCEDURE                             ! Declare Procedure
lToken   STRING(1024)
lPayload STRING(1024)
lSecret  STRING(255)
lAPIKey  STRING(255)
  CODE
  lSecret = 'b845bb0a8b2xxxxxxxxxxxxxx30c108da7bd755b'
  lAPIKey = 'xxxxxxx'
  lPayload = '{{"iss": "'&CLIP(lAPIKey)&'","iat": '&TimestampZ()&',"exp": '&TimestampZ()+180&',"ist": "Inhabit","jti": "'&RandomString(16)&'"}'
  lToken = CreateJWTToken(CLIP(lPayload),CLIP(lSecret))
  WriteDebugInfo('Payload: '&CLIP(lPayload))
  WriteDebugInfo('Token: '&CLIP(lToken))



CreateJWTToken       FUNCTION (STRING lPayload,STRING lSecret) ! Declare Procedure
stHeader      StringTheory
stPayload     StringTheory
stToEncrypt   StringTheory
stSignature   StringTheory
Crypto        Cryptonite
  CODE                                                     ! Begin processed code
  stHeader.SetValue('{{"typ":"JWT","alg":"HS256"}')
  stPayload.SetValue(CLIP(lPayload))
  stHeader.Base64Encode(1)
  stHeader.Replace('+','-')
  stHeader.Replace('/','_')
  stHeader.Replace('=','')
  stPayload.Base64Encode(1)
  stPayload.Replace('+','-')
  stPayload.Replace('/','_')
  stPayload.Replace('=','')
  stToEncrypt.SetValue(stHeader.GetValue()&'.'&stPayload.GetValue())
  Crypto.MakeHMAC(stToEncrypt,CLIP(lSecret),cs:CALG_SHA_256,0)
  stToEncrypt.Base64Encode(1)
  stToEncrypt.Replace('+','-')
  stToEncrypt.Replace('/','_')
  stToEncrypt.Replace('=','')
  RETURN stHeader.GetValue()&'.'&stPayload.GetValue()&'.'&stToEncrypt.GetValue()



A quick dirty demo, but it can be verified at https://jwt.io.


Regards
Bill

Bruce

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 11250
    • View Profile
Re: JWT Json Web Token
« Reply #3 on: July 21, 2021, 08:27:22 PM »
Hi Bill,

just FYI, the following lines;

  stPayload.Base64Encode(1)
  stPayload.Replace('+','-')
  stPayload.Replace('/','_')
  stPayload.Replace('=','')

can be replaced by
  stPayload.Base64Encode(st:URLSafe + st:NoPadding')

as per;
https://www.capesoft.com/docs/StringTheory3/StringTheory.htm#stBase64Encode

Also see;
https://www.capesoft.com/docs/NetTalk12/NetTalkUtilityFunctions.htm#NetMakeHMAC

which would remove the dependency on Cryptonite.

Cheers
Bruce


Cheers
Bruce

bshields

  • Sr. Member
  • ****
  • Posts: 392
    • View Profile
    • Inhabit
    • Email
Re: JWT Json Web Token
« Reply #4 on: July 22, 2021, 12:36:42 AM »
Hi Bruce,

Awesome! Thanks. I'll clean up my code.

Regards
Bill

ntnewbies

  • Full Member
  • ***
  • Posts: 184
    • View Profile
    • Email
Re: JWT Json Web Token
« Reply #5 on: July 22, 2021, 07:29:19 PM »
thank you very much bill and bruce.

jason

PaulMacFarlane

  • Newbie
  • *
  • Posts: 34
    • View Profile
    • Email
Re: JWT Json Web Token
« Reply #6 on: November 03, 2024, 06:12:37 PM »
On this section of code:

  stToEncrypt.SetValue(stHeader.GetValue()&'.'&stPayload.GetValue())
  Crypto.MakeHMAC(stToEncrypt,CLIP(lSecret),cs:CALG_SHA_256,0)
  stToEncrypt.Base64Encode(1)
  stToEncrypt.Replace('+','-')
  stToEncrypt.Replace('/','_')
  stToEncrypt.Replace('=','')

I modified per Bruces note to

! NetMakeHMAC function passes a string and returns ST so I created a string for this part
  strPREencrypt = stHeader.GetValue()&'.'&stPayload.GetValue()

  stToEncrypt  = NetMakeHMAC(clip(strPREencrypt ),len(strPREencrypt),CLIP(lSecret),cs:CALG_SHA_256,0)

  stToEncrypt.Base64Encode(1)  <<-GPF
  stToEncrypt.Replace('+','-')
  stToEncrypt.Replace('/','_')
  stToEncrypt.Replace('=','')

And I get a GPF on base64encode.


Bruce

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 11250
    • View Profile
Re: JWT Json Web Token
« Reply #7 on: November 03, 2024, 11:00:26 PM »
you probably got a compile warning on this line;

stToEncrypt  = NetMakeHMAC(clip(strPREencrypt ),len(strPREencrypt),CLIP(lSecret),cs:CALG_SHA_256,0)

This line should be
stToEncrypt.SetValu(NetMakeHMAC(clip(strPREencrypt ),len(strPREencrypt),CLIP(lSecret),cs:CALG_SHA_256,0))

just one more reason not to ignore warnings....

PaulMacFarlane

  • Newbie
  • *
  • Posts: 34
    • View Profile
    • Email
Re: JWT Json Web Token
« Reply #8 on: November 03, 2024, 11:45:03 PM »
I did not get a compile warning. :-\

Thanks for noticing my error.  Somehow I got it stuck in my brain that it returned a ST object.

PaulMacFarlane

  • Newbie
  • *
  • Posts: 34
    • View Profile
    • Email
Re: JWT Json Web Token
« Reply #9 on: November 04, 2024, 04:11:51 PM »
I am successfully generating the JWT, but when I verify it on jwt.io it's telling me my secret is bad....

The header and payload data is decoded fine but I'm doing something wrong on the 'secret' stuff....

Here's the code I'm using:

Code: [Select]
!Create_ClientJWT       FUNCTION (STRING KeyID,STRING ClientID, string UserID, string lSecret) ! Declare Procedure


! Build Header
    Header_element.kid = clip(KeyID)
    Header_element.alg = 'RSA256'

    jwtj.Start()
    jwtj.SetTagCase(jf:CaseAsIs)
    jwtj.Save(header_element,stHeader)

! Payload

    Payload_element.iss =   clip(ClientID)      ! Issuer
    Payload_element.sub =   clip(UserID)        ! Subject of token
    Payload_element.aud =   'https://api.alt.www4.irs.gov/auth/oauth/v2/token'
    Payload_element.iat =   fmt.ClarionToUnixDate(today(),clock())  ! Issued At Time - Epoch time
    Payload_element.exp =   fmt.ClarionToUnixDate(today(),clock()+(15*60*100))  ! expire time = iat + 15 minutes
    stPayload.SetValue('')
    stPayload.MakeGUID4(st:format)
    Payload_element.jti =   stPayload.GetValue()  ! Unique ID I create

    jwtj.Save(Payload_element,stPayload)

!    message(stHeader.GetValue(),'stheader:')
!    message(stPayload.GetValue(),'stPayload:')

    stHeader.Base64Encode(st:URLSafe + st:NoPadding)
    stPayload.Base64Encode(st:URLSafe + st:NoPadding)

! The call in this format gives me an invalid type error..
!  stToEncrypt.SetValue(stHeader.GetValue()&'.'&stPayload.GetValue())
!  stToEncrypt.SetValue(NetMakeHMAC(stToEncrypt.GetValue(),stToEncrypt.Len,CLIP(lSecret),net:CALG_SHA_256))

! So I do this....  stPreEncrypt        string(1024)


    stPreEncrypt = clip(stHeader.GetValue())&'.'& clip(stPayload.GetValue())        ! Values already encoded

    stToEncrypt.SetValue(NetMakeHMAC(stPreEncrypt,len(stPreEncrypt),CLIP(lSecret),net:CALG_SHA_256))

    stToEncrypt.Base64Encode(st:URLSafe + st:NoPadding)

  RETURN stHeader.GetValue()&'.'& stPayload.GetValue() &'.'& stToEncrypt.GetValue()

Any ideas?

PaulMacFarlane

  • Newbie
  • *
  • Posts: 34
    • View Profile
    • Email
Re: JWT Json Web Token
« Reply #10 on: November 05, 2024, 02:44:46 PM »
Okay - I think I figured out the problem.

The alg is not correct.  If I switch to HS256 all works.

The website is expecting RS256.

So I suspect this means I cannot use the HMAC function since that creates HS256....