diff --git a/README.md b/README.md index eb829a6f..2c11c98b 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ decoded_token = JWT.decode token, nil, false # Array # [ # {"data"=>"test"}, # payload -# {"typ"=>"JWT", "alg"=>"none"} # header +# {"alg"=>"none"} # header # ] puts decoded_token ``` @@ -79,7 +79,7 @@ decoded_token = JWT.decode token, hmac_secret, true, { :algorithm => 'HS256' } # Array # [ # {"data"=>"test"}, # payload -# {"typ"=>"JWT", "alg"=>"HS256"} # header +# {"alg"=>"HS256"} # header # ] puts decoded_token ``` @@ -104,7 +104,7 @@ decoded_token = JWT.decode token, rsa_public, true, { :algorithm => 'RS256' } # Array # [ # {"data"=>"test"}, # payload -# {"typ"=>"JWT", "alg"=>"RS256"} # header +# {"alg"=>"RS256"} # header # ] puts decoded_token ``` @@ -131,7 +131,7 @@ decoded_token = JWT.decode token, ecdsa_public, true, { :algorithm => 'ES256' } # Array # [ # {"test"=>"data"}, # payload -# {"typ"=>"JWT", "alg"=>"ES256"} # header +# {"alg"=>"ES256"} # header # ] puts decoded_token ``` @@ -152,6 +152,38 @@ used. JWT supports these reserved claim names: - 'iat' (Issued At) Claim - 'sub' (Subject) Claim +## Add custom header fields +Ruby-jwt gem supports custom [header fields] (https://tools.ietf.org/html/rfc7519#section-5) +To add custom header fields you need to pass `header_fields` parameter + +```ruby +token = JWT.encode payload, key, algorithm='HS256', header_fields={} +``` + +**Example:** + +```ruby +require 'jwt' + +payload = {:data => 'test'} + +# IMPORTANT: set nil as password parameter +token = JWT.encode payload, nil, 'none', { :typ => "JWT" } + +# eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9. +puts token + +# Set password to nil and validation to false otherwise this won't work +decoded_token = JWT.decode token, nil, false + +# Array +# [ +# {"data"=>"test"}, # payload +# {"typ"=>"JWT", "alg"=>"none"} # header +# ] +puts decoded_token +``` + ### Expiration Time Claim From [Oauth JSON Web Token 4.1.4. "exp" (Expiration Time) Claim](https://tools.ietf.org/html/rfc7519#section-4.1.4): diff --git a/lib/jwt.rb b/lib/jwt.rb index ba148a3d..950c4dec 100644 --- a/lib/jwt.rb +++ b/lib/jwt.rb @@ -81,7 +81,7 @@ def base64url_encode(str) end def encoded_header(algorithm = 'HS256', header_fields = {}) - header = { 'typ' => 'JWT', 'alg' => algorithm }.merge(header_fields) + header = { 'alg' => algorithm }.merge(header_fields) base64url_encode(encode_json(header)) end diff --git a/spec/integration/readme_examples_spec.rb b/spec/integration/readme_examples_spec.rb index b87c9c7c..5a7b9e66 100644 --- a/spec/integration/readme_examples_spec.rb +++ b/spec/integration/readme_examples_spec.rb @@ -10,10 +10,10 @@ token = JWT.encode payload, nil, 'none' decoded_token = JWT.decode token, nil, false - expect(token).to eq 'eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9.' + expect(token).to eq 'eyJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9.' expect(decoded_token).to eq [ { 'data' => 'test' }, - { 'typ' => 'JWT', 'alg' => 'none' } + { 'alg' => 'none' } ] end @@ -21,10 +21,10 @@ token = JWT.encode payload, 'my$ecretK3y', 'HS256' decoded_token = JWT.decode token, 'my$ecretK3y', false - expect(token).to eq 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.ZxW8go9hz3ETCSfxFxpwSkYg_602gOPKearsf6DsxgY' + expect(token).to eq 'eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.pNIWIL34Jo13LViZAJACzK6Yf0qnvT_BuwOxiMCPE-Y' expect(decoded_token).to eq [ { 'data' => 'test' }, - { 'typ' => 'JWT', 'alg' => 'HS256' } + { 'alg' => 'HS256' } ] end @@ -37,7 +37,7 @@ expect(decoded_token).to eq [ { 'data' => 'test' }, - { 'typ' => 'JWT', 'alg' => 'RS256' } + { 'alg' => 'RS256' } ] end @@ -52,7 +52,7 @@ expect(decoded_token).to eq [ { 'data' => 'test' }, - { 'typ' => 'JWT', 'alg' => 'ES256' } + { 'alg' => 'ES256' } ] end end @@ -176,6 +176,17 @@ end end + context 'custom header fields' do + it 'with custom field' do + payload = { data: 'test' } + + token = JWT.encode payload, nil, 'none', { typ: 'JWT' } + jwt_payload, header = JWT.decode token, nil, false + + expect(header['typ']).to eq 'JWT' + end + end + it 'sub' do sub = 'Subject' sub_payload = { data: 'data', sub: sub } diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index 6944ae53..00a47da5 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -18,13 +18,13 @@ 'ES384_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec384-public.pem'))), 'ES512_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-private.pem'))), 'ES512_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-public.pem'))), - 'NONE' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.', - 'HS256' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.tCGvlClld0lbQ3NZaH8y53n5RSBr3zlS4Oy5bXqvzZQ', - 'HS384' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.sj1gc01SawlJSrPZgmveifJ8CzZRYAWjejWm4FRaGaAISESJ9Ncf12fCz2vHrITm', - 'HS512' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.isjhsWMZpRQOWw6LKtlY4L6tMDNkLr0qZ3bQe_xRFXWhzVvJlkclTbLVa1J6Dlj2WyZ_I1jEobTaFMDoXPzwWg', - 'RS256' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.u82QrhjZTtwve5akvfWS_4LPywbkb1Yp0nUwZJWtTW0ID7dY9rRiQF5KGj2UDLZotqRlUjyNQgE_hB5BBzICDQdCjQHQoYWE5n_D2wV4PMu7Qg3FVKoBFbf8ee6irodu10fgYxpUIZtvbWw52_6k6A9IoSLSzx_lCcxoVGdW90dUuKhBcZkDtY5WNuQg7MiDthupSL1-V4Y1jmT_7o8tLNGFiocyZfGNw4yGpEOGNvD5WePNit0xsnbj6dEquovUvSFKsMaQXp2PVDEkLOiLMcyk0RrHqrHw2eNSCquWTH8PhX5Up-CVmjQM5zF9ibkaiq8NyPtsy-7rgtbyVMqXBQ', - 'RS384' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.2_jPwOsUWJ-3r6lXMdJGPdhLNJQSSEmY2mrDXCwNJk-2YhMIqKAzJJCbyso_A1hS7BVkXmHt54RCcNJXroZBOgmGavCcYTPMaT6sCvVVvJJ_wn7jzKHNAJfL5nWeynTQIBWmL-m_v9QpZAgPALdeqjPRv4JHePZm23kvrUgQOxef2ldXv1l6IB3zfF72uEbk9T5pKBvgeeeQ46xm_HtkpXqMdqcTHawUXeXhuiWxuWfy9pAvhm8ivxwJhiQ15-sQNBlS9lG1_gQz1xaZ_Ou_n1nhNfGwpK5HeS0AgmqsqyCOvaGHeAuAOPZ_dSC3cFKu2AP7kc6_AKBgwJzh4agkXg', - 'RS512' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.abwof7BqTvuLkN69OhEuFTP7vjGzfvAvooQdwIRne_a88MsjCq31n4UPvyIlY9_8u69rpU79RbMsrq_UZ6L85zP83EcyYI-HOfFZgYDAL3DJ7biBD99JTzyOsH_2i_E6yCkevjEX6uL_Am_C7jpWyePJQkYzTFni6mW4W1T9UobiVGA1tIZ-XOJDPHHxZkGu6W8lKW0UCsr9Ge2SCSlTs_LDSOa34gqMC5GP89unhLqSMqEMJ_Nm6Rj0rnmk87wBZM-b04LLteWuEU59QDNa4nMTjfXW74U4hX9n5EECDPQdQMecgxlUbFunAfZaoNzP4m7H4vux2FzYkjkXhdqnnw', + 'NONE' => 'eyJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.', + 'HS256' => 'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.kWOVtIOpWcG7JnyJG0qOkTDbOy636XrrQhMm_8JrRQ8', + 'HS384' => 'eyJhbGciOiJIUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.VuV4j4A1HKhWxCNzEcwc9qVF3frrEu-BRLzvYPkbWO0LENRGy5dOiBQ34remM3XH', + 'HS512' => 'eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.8zNtCBTJIZTHpZ-BkhR-6sZY1K85Nm5YCKqV3AxRdsBJDt_RR-REH2db4T3Y0uQwNknhrCnZGvhNHrvhDwV1kA', + 'RS256' => 'eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.eSXvWP4GViiwUALj_-qTxU68I1oM0XjgDsCZBBUri2Ghh9d75QkVDoZ_v872GaqunN5A5xcnBK0-cOq-CR6OwibgJWfOt69GNzw5RrOfQ2mz3QI3NYEq080nF69h8BeqkiaXhI24Q51joEgfa9aj5Y-oitLAmtDPYTm7vTcdGufd6AwD3_3jajKBwkh0LPSeMtbe_5EyS94nFoEF9OQuhJYjUmp7agsBVa8FFEjVw5jEgVqkvERSj5hSY4nEiCAomdVxIKBfykyi0d12cgjhI7mBFwWkPku8XIPGZ7N8vpiSLdM68BnUqIK5qR7NAhtvT7iyLFgOqhZNUQ6Ret5VpQ', + 'RS384' => 'eyJhbGciOiJSUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.Sfgk56moPghtsjaP4so6tOy3I553mgwX-5gByMC6dX8lpeWgsxSeAd_K8IyO7u4lwYOL0DSftnqO1HEOuN1AKyBbDvaTXz3u2xNA2x4NYLdW4AZA6ritbYcKLO5BHTXw5ueMbtA1jjGXP0zI_aK2iJTMBmB8SCF88RYBUH01Tyf4PlLj98pGL-v3prZd6kZkIeRJ3326h04hslcB5HQKmgeBk24QNLIoIC-CD329HPjJ7TtGx01lj-ehTBnwVbBGzYFAyoalV5KgvL_MDOfWPr1OYHnR5s_Fm6_3Vg4u6lBljvHOrmv4Nfx7d8HLgbo8CwH4qn1wm6VQCtuDd-uhRg', + 'RS512' => 'eyJhbGciOiJSUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.LIIAUEuCkGNdpYguOO5LoW4rZ7ED2POJrB0pmEAAchyTdIK4HKh1jcLxc6KyGwZv40njCgub3y72q6vcQTn7oD0zWFCVQRIDW1911Ii2hRNHuigiPUnrnZh1OQ6z65VZRU6GKs8omoBGU9vrClBU0ODqYE16KxYmE_0n4Xw2h3D_L1LF0IAOtDWKBRDa3QHwZRM9sHsHNsBuD5ye9KzDYN1YALXj64LBfA-DoCKfpVAm9NkRPOyzjR2X2C3TomOSJgqWIVHJucudKDDAZyEbO4RA5pI-UFYy1370p9bRajvtDyoBuLDCzoSkMyQ4L2DnLhx5CbWcnD7Cd3GUmnjjTA', 'ES256' => '', 'ES384' => '', 'ES512' => ''