Roku Developer Program

Developers and content creators—a complete solution for growing an audience directly.
cancel
Showing results for 
Search instead for 
Did you mean: 
DadOfTwo
Level 7

ByteArray FromBase64String not able to handle Valid JWT (RS512) tokens?

Hi all

Found what maybe an issue with the Roku ByteArray fromBase64StringtoAsciiString methods.

When passing in a value JSON Web Token to the ByteArray.fromBase64String method and converting it via ByteArray.toAsciiString the 'payload' value in the JWT is missing characters.

Here's an example of the issue, the tokens are generated from the https://jwt.io site.

sub init()
  'jwToken1 values'
  'header:
  '{
  ' "alg": "HS256",
  ' "typ": "JWT"
  '}
  'payload:
  '{
  ' "someKey": "someValue"
  '}
  'verify signature:
  'default on the https://jwt.io/ site'

  jwToken1 = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lS2V5Ijoic29tZVZhbHVlIn0._UeRDHCMD9aFDsAxucwn3b66Y7YkJ7eBsQh7ajEWXmE"
  tokenPayloadFromJwToken1 = getTokenPayloadAsObject(jwToken1)
  'tokenPayloadFromJwToken1 outputs INVALID JSON: {"someKey":"someValue

  jwToken2 = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lS2V5Ijp0cnVlfQ.kxkYrH4gICavDvfJ2IoGvhUHlt2YLKHWk1DbwFN9qNA"
  tokenPayloadFromJwToken2 = getTokenPayloadAsObject(jwToken2)
  'tokenPayloadFromJwToken2 outputs INVALID JSON: {"someKey":true

  jwToken3 = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lS2V5IjoxMjN9.DL8qyWMeqfMMLCTPN3RA9K08e-AkNW_ybPyywvrIIZ8"
  tokenPayloadFromJwToken3 = getTokenPayloadAsObject(jwToken3)
  'tokenPayloadFromJwToken3 outputs VALID JSON: {"someKey":123}

  jwToken4 = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lS2V5IjoxMjM0fQ.BHOwW2P2Rs6hUMrxyFqMi9EbLVQGgvWfUdbXZHE2QA8"
  tokenPayloadFromJwToken4 = getTokenPayloadAsObject(jwToken4)
  'tokenPayloadFromJwToken4 outputs INVALID JSON: {"someKey":1234
end sub

function getTokenPayloadAsObject(token as String) as String
  tokenParts = token.split(".")
  ' XXX: the token we're receiving back is a JWT (RS512) base64 string consisting of 3 parts:
  '      1 (index 0). header: token type and algoritham'
  '      2 (index 1). payload: various json value pairs'
  '      3 (index 3). verify signature: details on the encoding/ secret format'
  payloadIndex = 1
  tokenPayload = tokenParts[payloadIndex]
  ba = CreateObject("roByteArray")
  ba.fromBase64String(tokenPayload)
  tokenPayloadString = ba.toAsciiString()
  return tokenPayloadString
end function



Thanks
0 Kudos
5 Replies
Roku Employee
Roku Employee

Re: ByteArray FromBase64String not able to handle Valid JWT (RS512) tokens?

it doesn't handle well un-padded base64, apparently. Make sure the length is divisible by 4, pad with '=' as needed:

Brightscript Debugger> s = "eyJzb21lS2V5Ijoic29tZVZhbHVlIn0"
Brightscript Debugger> b = createObject("roByteArray")
Brightscript Debugger> b.fromBase64String(s): ? b.toAsciiString(), len(s)  
{"someKey":"someValue            31
Brightscript Debugger> if len(s) mod 4 <> 0 then s += string(4 - len(s) mod 4, "=")  '"

Brightscript Debugger> b.fromBase64String(s): ? b.toAsciiString(), len(s), s
{"someKey":"someValue"}          32             eyJzb21lS2V5Ijoic29tZVZhbHVlIn0=
0 Kudos
DadOfTwo
Level 7

Re: ByteArray FromBase64String not able to handle Valid JWT (RS512) tokens?

Nice explanation and temporary fix, thanks. 

Are there plans to fix this without needing to pad the token with equals? Also the ba.toAsciiString() method is still chopping off the trailing brace '}'... so need to manually check for that missing from the tokenPayloadString before passing it to the Native Roku ParseJson method.
0 Kudos
DadOfTwo
Level 7

Re: ByteArray FromBase64String not able to handle Valid JWT (RS512) tokens?

Also found a token that the fix does not work on:

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px 'Andale Mono'; color: #29f914; background-color: #000000} span.s1 {font-variant-ligatures: no-common-ligatures}

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJ1c2VyIjoiMDAxN0UwMDAwMGNtQjBsUUFFIiwiaXNzdWVkIjoxNTA5OTg1MTk1LCJleHAiOjE1MDk5OTIzOTUsInVzZXJzdGF0dXMiOiJBY3RpdmVHcmFjZSIsInZpZXdlcklkIjoiRXh0LTAzNDc1MTQzIiwiY291bnRyeSI6ImRlIiwidXNlclR5cGUiOjAsImNhbnJlZGVlbWdjIjoiRW5hYmxlZCIsIm1weCI6ImV5SmhiR2NpT2lKU1V6VXhNaUo5LmV5SnpkV0lpT2lKd1oyeHpMWEJ5WkMxMGNuVnpkR1ZrTHpBd05UZEZNREF3TURBelJ6aDNXRkZCVXlJc0ltbHpjeUk2SWpFaUxDSmxlSEFpT2pFMU1EazVPVEl6T1RVc0ltbGhkQ0k2TVRVd09UazROVEU1TlRVd055d2lhblJwSWpvaU1Ea3hNR1F3TkRBdFlUZzFZaTAwTVRGa0xUbGhNVGt0TTJNd04yRXhNREppWXpReklpd2laR2xrSWpvaWNHZHNjeTF3Y21RdGRISjFjM1JsWkNJc0luVnViU0k2SWpBd05UZEZNREF3TURBelJ6aDNXRkZCVXlJc0ltTjBlQ0k2SW50Y0luVnpaWEpPWVcxbFhDSTZYQ0l3TURVM1JUQXdNREF3TTBjNGQxaFJRVk5jSWl4Y0ltRjBkSEpwWW5WMFpYTmNJanA3WENKemRXSnpZM0pwY0hScGIyNU1aWFpsYkZ3aU9sd2ljM1JoYm1SaGNtUmNJbjE5WEc0aUxDSnZhV1FpT201MWJHeDkuanR3QkNKU2Rxcy1oZzZ4UUU0c2M2UDM1NDhWNFNmZzZrQmZRNXhCTnREREMzT3pGUXV6cUY1ZWxQWC1ELWF5WXhGT3Y4U3ZNYjNhTnl1eUo4SlRKTjNzaUdfQUZiZGhjUnZtc256dGROT1p1YXc2MUhoMjdjcUVycW1yVU9SQWs1LVJGdGpnOXQxc2JaOGNJaE9HRnF2cExhbXl6WEZuV1BxUVZvWThSbkVtT21GbmdLUERyU0pXOFhYLUJPOGRXeDBkRHF2Z0JzbHdGOFBEV0gtclo3TUJMSDF2Sjk3aFhfZ1V5ZjZJM21SaWp3NXRBbU1ZamFBeXVCZWVTRTdkVm1VSVA0YnVXZFB0YktjbHkySi03ekdrZDBhR1lsS1hSekprRzJMNU01RVgxZDd0c2FGRlJtVGFfTWRBZkdSY0xwLVB5bWFRQ0pqNmFpOG5tc0VOOWNBIiwiYXV0aGtleSI6MTUwNTc1Nzk1MCwiZGV2aWNlSWQiOiIwMDE3RTAwMDAwY21CMGxRQUUtMzE4ZTUxYzItZTZiYy01MzYxLThlMjMtMzMzNjg3NDM0ZTA5In0.apCmxDqI4DI5Bqd_rQceC-FoHp0WDZxOf5BGYMuVkdsWFvEdpVuNZ9yKbqBGxmfLOJ8kFgvV-yzcG2RKmq_qcHUJSJfUPHuEmgBrdLpt5SRl1Lg7eb3nIGy-aiBOxxvaVv14TAa44q-XSAcRpdToxLrSa02XufpCxbuwx6xImL5NF5IZbqDCR3kSiH1WqPB71L8sBa1QvDxZ6izqYdFzQyJJjZJcVu6A3qDp5jCTIrcOkDNhl_NI6_h-k3cYhUzkfBEJfeRazXggeswoekEhtAQsSUglj_GlVQ2DdN57jSmjiRd6qC6YXnOzpvTNlJGH4eFenjAYP6McL7ZJnk4lCA=


Returned value from ba.toAsciiString() following fix, still losing the "} from the end of the JSON object :

{"user":"0017E00000cmB0lQAE","issued":1509985195,"exp":1509992395,"userstatus":"ActiveGrace","viewerId":"Ext-03475143","country":"de","userType":0,"canredeemgc":"Enabled","mpx":"eyJhbGciOiJSUzUxMiJ9.eyJzdWIiOiJwZ2xzLXByZC10cnVzdGVkLzAwNTdFMDAwMDAzRzh3WFFBUyIsImlzcyI6IjEiLCJleHAiOjE1MDk5OTIzOTUsImlhdCI6MTUwOTk4NTE5NTUwNywianRpIjoiMDkxMGQwNDAtYTg1Yi00MTFkLTlhMTktM2MwN2ExMDJiYzQzIiwiZGlkIjoicGdscy1wcmQtdHJ1c3RlZCIsInVubSI6IjAwNTdFMDAwMDAzRzh3WFFBUyIsImN0eCI6IntcInVzZXJOYW1lXCI6XCIwMDU3RTAwMDAwM0c4d1hRQVNcIixcImF0dHJpYnV0ZXNcIjp7XCJzdWJzY3JpcHRpb25MZXZlbFwiOlwic3RhbmRhcmRcIn19XG4iLCJvaWQiOm51bGx9.jtwBCJSdqs-hg6xQE4sc6P3548V4Sfg6kBfQ5xBNtDDC3OzFQuzqF5elPX-D-ayYxFOv8SvMb3aNyuyJ8JTJN3siG_AFbdhcRvmsnztdNOZuaw61Hh27cqErqmrUORAk5-RFtjg9t1sbZ8cIhOGFqvpLamyzXFnWPqQVoY8RnEmOmFngKPDrSJW8XX-BO8dWx0dDqvgBslwF8PDWH-rZ7MBLH1vJ97hX_gUyf6I3mRijw5tAmMYjaAyuBeeSE7dVmUIP4buWdPtbKcly2J-7zGkd0aGYlKXRzJkG2L5M5EX1d7tsaFFRmTa_MdAfGRcLp-PymaQCJj6ai8nmsEN9cA","authkey":1505757950,"deviceId":"0017E00000cmB0lQAE-318e51c2-e6bc-5361-8e23-333687434e09
0 Kudos
Roku Employee
Roku Employee

Re: ByteArray FromBase64String not able to handle Valid JWT (RS512) tokens?

Works just fine. i think the problem this time was trying to paste a too long string in the console.
Brightscript Debugger> s = "eyJ1c2VyIjoiMDAxN0UwMDAwMGNtQjBsUUFFIiwiaXNzdWVkIjoxNTA5OTg1MTk1LCJleHAiOjE1MDk5OTIzOTUsInVzZXJzdGF0dXMiOiJBY3RpdmVHcmFjZSIsInZpZXdlcklkIjoiRXh0LTAzNDc1MTQzIiwiY291bnRyeSI6ImRlIiwidXNlclR5cGUiOjAsImNhbnJlZGVlbWdjIjoiRW5hYmxlZCIsIm1weCI6ImV5SmhiR2NpT2lKU1V6VXhNaUo5LmV5SnpkV0lpT2lKd1oyeHpMWEJ5WkMxMGNuVnpkR1ZrTHpBd05UZEZNREF3TURBelJ6aDNXRkZCVXlJc0ltbHpjeUk2SWpFaUxDSmxlSEFpT2pFMU1EazVPVEl6T1RVc0ltbGhkQ0k2TVRVd09UazROVEU1TlRVd055d2lhblJwSWpvaU1Ea3hNR1F3TkRBdFlUZzFZaTAwTVRGa0xUbGhNVGt0TTJNd04yRXhNREppWXpReklpd2laR2xrSWpvaWNHZHNjeTF3Y21RdGRISj"

Brightscript Debugger> s = s + "FjM1JsWkNJc0luVnViU0k2SWpBd05UZEZNREF3TURBelJ6aDNXRkZCVXlJc0ltTjBlQ0k2SW50Y0luVnpaWEpPWVcxbFhDSTZYQ0l3TURVM1JUQXdNREF3TTBjNGQxaFJRVk5jSWl4Y0ltRjBkSEpwWW5WMFpYTmNJanA3WENKemRXSnpZM0pwY0hScGIyNU1aWFpsYkZ3aU9sd2ljM1JoYm1SaGNtUmNJbjE5WEc0aUxDSnZhV1FpT201MWJHeDkuanR3QkNKU2Rxcy1oZzZ4UUU0c2M2UDM1NDhWNFNmZzZrQmZRNXhCTnREREMzT3pGUXV6cUY1ZWxQWC1ELWF5WXhGT3Y4U3ZNYjNhTnl1eUo4SlRKTjNzaUdfQUZiZGhjUnZtc256dGROT1p1YXc2MUhoMjdjcUVycW1yVU9SQWs1LVJGdGpnOXQxc2JaOGNJaE9HRnF2cExhbXl6WEZuV1BxUVZvWThSbkVtT21GbmdLUERyU0pXOFhYLUJPOGRXeDBkRHF2Z0JzbHdGOFBEV0gtclo3TUJMSDF2Sjk3aFhfZ1V5ZjZJM21SaWp3NXRBbU1ZamFBeXVCZWVTRTdkVm1VSVA0YnVXZFB0YktjbHkySi03ekdrZDBhR1lsS1hSekprRzJMNU01RVgxZDd0c2FGRlJtVGFfTWRBZkdSY0xwLVB5bWFRQ0pqNmFpOG5tc0VOOWNBIiwiYXV0aGtleSI6MTUwNTc1Nzk1MCwiZGV2aWNlSWQiOiIwMDE3RTAwMDAwY21CMGxRQUUtMzE4ZTUxYzItZTZiYy01MzYxLThlMjMtMzMzNjg3NDM0ZTA5In0"

Brightscript Debugger> ? len(s)
1379

Brightscript Debugger> b = createObject("roByteArray")

Brightscript Debugger> b.fromBase64String(s): ? b.toAsciiString(), len(s)
{"user":"0017E00000cmB0lQAE","issued":1509985195,"exp":1509992395,"userstatus":"ActiveGrace","viewerId":"Ext-03475143","country":"de","userType":0,"canredeemgc":"Enabled","mpx":"eyJhbGciOiJSUzUxMiJ9.eyJzdWIiOiJwZ2xzLXByZC10cnVzdGVkLzAwNTdFMDAwMDAzRzh3WFFBUyIsImlzcyI6IjEiLCJleHAiOjE1MDk5OTIzOTUsImlhdCI6MTUwOTk4NTE5NTUwNywianRpIjoiMDkxMGQwNDAtYTg1Yi00MTFkLTlhMTktM2MwN2ExMDJiYzQzIiwiZGlkIjoicGdscy1wcmQtdHJ1c3RlZCIsInVubSI6IjAwNTdFMDAwMDAzRzh3WFFBUyIsImN0eCI6IntcInVzZXJOYW1lXCI6XCIwMDU3RTAwMDAwM0c4d1hRQVNcIixcImF0dHJpYnV0ZXNcIjp7XCJzdWJzY3JpcHRpb25MZXZlbFwiOlwic3RhbmRhcmRcIn19XG4iLCJvaWQiOm51bGx9.jtwBCJSdqs-hg6xQE4sc6P3548V4Sfg6kBfQ5xBNtDDC3OzFQuzqF5elPX-D-ayYxFOv8SvMb3aNyuyJ8JTJN3siG_AFbdhcRvmsnztdNOZuaw61Hh27cqErqmrUORAk5-RFtjg9t1sbZ8cIhOGFqvpLamyzXFnWPqQVoY8RnEmOmFngKPDrSJW8XX-BO8dWx0dDqvgBslwF8PDWH-rZ7MBLH1vJ97hX_gUyf6I3mRijw5tAmMYjaAyuBeeSE7dVmUIP4buWdPtbKcly2J-7zGkd0aGYlKXRzJkG2L5M5EX1d7tsaFFRmTa_MdAfGRcLp-PymaQCJj6ai8nmsEN9cA","authkey":1505757950,"deviceId":"0017E00000cmB0lQAE-318e51c2-e6bc-5361-8e23-333687434e09 1379

Brightscript Debugger> if len(s) mod 4 <> 0 then s += string(4 - len(s) mod 4, "=")

Brightscript Debugger> b.fromBase64String(s): ? b.toAsciiString(), len(s), s
{"user":"0017E00000cmB0lQAE","issued":1509985195,"exp":1509992395,"userstatus":"ActiveGrace","viewerId":"Ext-03475143","country":"de","userType":0,"canredeemgc":"Enabled","mpx":"eyJhbGciOiJSUzUxMiJ9.eyJzdWIiOiJwZ2xzLXByZC10cnVzdGVkLzAwNTdFMDAwMDAzRzh3WFFBUyIsImlzcyI6IjEiLCJleHAiOjE1MDk5OTIzOTUsImlhdCI6MTUwOTk4NTE5NTUwNywianRpIjoiMDkxMGQwNDAtYTg1Yi00MTFkLTlhMTktM2MwN2ExMDJiYzQzIiwiZGlkIjoicGdscy1wcmQtdHJ1c3RlZCIsInVubSI6IjAwNTdFMDAwMDAzRzh3WFFBUyIsImN0eCI6IntcInVzZXJOYW1lXCI6XCIwMDU3RTAwMDAwM0c4d1hRQVNcIixcImF0dHJpYnV0ZXNcIjp7XCJzdWJzY3JpcHRpb25MZXZlbFwiOlwic3RhbmRhcmRcIn19XG4iLCJvaWQiOm51bGx9.jtwBCJSdqs-hg6xQE4sc6P3548V4Sfg6kBfQ5xBNtDDC3OzFQuzqF5elPX-D-ayYxFOv8SvMb3aNyuyJ8JTJN3siG_AFbdhcRvmsnztdNOZuaw61Hh27cqErqmrUORAk5-RFtjg9t1sbZ8cIhOGFqvpLamyzXFnWPqQVoY8RnEmOmFngKPDrSJW8XX-BO8dWx0dDqvgBslwF8PDWH-rZ7MBLH1vJ97hX_gUyf6I3mRijw5tAmMYjaAyuBeeSE7dVmUIP4buWdPtbKcly2J-7zGkd0aGYlKXRzJkG2L5M5EX1d7tsaFFRmTa_MdAfGRcLp-PymaQCJj6ai8nmsEN9cA","authkey":1505757950,"deviceId":"0017E00000cmB0lQAE-318e51c2-e6bc-5361-8e23-333687434e09"} 1380 eyJ1c2VyIjoiMDAxN0UwMDAwMGNtQjBsUUFFIiwiaXNzdWVkIjoxNTA5OTg1MTk1LCJleHAiOjE1MDk5OTIzOTUsInVzZXJzdGF0dXMiOiJBY3RpdmVHcmFjZSIsInZpZXdlcklkIjoiRXh0LTAzNDc1MTQzIiwiY291bnRyeSI6ImRlIiwidXNlclR5cGUiOjAsImNhbnJlZGVlbWdjIjoiRW5hYmxlZCIsIm1weCI6ImV5SmhiR2NpT2lKU1V6VXhNaUo5LmV5SnpkV0lpT2lKd1oyeHpMWEJ5WkMxMGNuVnpkR1ZrTHpBd05UZEZNREF3TURBelJ6aDNXRkZCVXlJc0ltbHpjeUk2SWpFaUxDSmxlSEFpT2pFMU1EazVPVEl6T1RVc0ltbGhkQ0k2TVRVd09UazROVEU1TlRVd055d2lhblJwSWpvaU1Ea3hNR1F3TkRBdFlUZzFZaTAwTVRGa0xUbGhNVGt0TTJNd04yRXhNREppWXpReklpd2laR2xrSWpvaWNHZHNjeTF3Y21RdGRISjFjM1JsWkNJc0luVnViU0k2SWpBd05UZEZNREF3TURBelJ6aDNXRkZCVXlJc0ltTjBlQ0k2SW50Y0luVnpaWEpPWVcxbFhDSTZYQ0l3TURVM1JUQXdNREF3TTBjNGQxaFJRVk5jSWl4Y0ltRjBkSEpwWW5WMFpYTmNJanA3WENKemRXSnpZM0pwY0hScGIyNU1aWFpsYkZ3aU9sd2ljM1JoYm1SaGNtUmNJbjE5WEc0aUxDSnZhV1FpT201MWJHeDkuanR3QkNKU2Rxcy1oZzZ4UUU0c2M2UDM1NDhWNFNmZzZrQmZRNXhCTnREREMzT3pGUXV6cUY1ZWxQWC1ELWF5WXhGT3Y4U3ZNYjNhTnl1eUo4SlRKTjNzaUdfQUZiZGhjUnZtc256dGROT1p1YXc2MUhoMjdjcUVycW1yVU9SQWs1LVJGdGpnOXQxc2JaOGNJaE9HRnF2cExhbXl6WEZuV1BxUVZvWThSbkVtT21GbmdLUERyU0pXOFhYLUJPOGRXeDBkRHF2Z0JzbHdGOFBEV0gtclo3TUJMSDF2Sjk3aFhfZ1V5ZjZJM21SaWp3NXRBbU1ZamFBeXVCZWVTRTdkVm1VSVA0YnVXZFB0YktjbHkySi03ekdrZDBhR1lsS1hSekprRzJMNU01RVgxZDd0c2FGRlJtVGFfTWRBZkdSY0xwLVB5bWFRQ0pqNmFpOG5tc0VOOWNBIiwiYXV0aGtleSI6MTUwNTc1Nzk1MCwiZGV2aWNlSWQiOiIwMDE3RTAwMDAwY21CMGxRQUUtMzE4ZTUxYzItZTZiYy01MzYxLThlMjMtMzMzNjg3NDM0ZTA5In0=
0 Kudos
DadOfTwo
Level 7

Re: ByteArray FromBase64String not able to handle Valid JWT (RS512) tokens?

Was applying it to the unpacked token, not the payload. Working now!

Thanks.
0 Kudos