Skip to content

Instantly share code, notes, and snippets.

@rafaeltuelho
Last active June 12, 2023 23:45
Show Gist options
  • Save rafaeltuelho/40e5a57882e2f610f202 to your computer and use it in GitHub Desktop.
Save rafaeltuelho/40e5a57882e2f610f202 to your computer and use it in GitHub Desktop.
Decoding an encoded oAuth JSON Web Token (JWT): access_token

Given an encoded (base64) JWT (access_token).

For example, see this sample OAuth2 response generated by JBoss APIMan/Keycloak

HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/json
Date: Tue, 25 Aug 2015 19:25:12 GMT
Server: WildFly/8
Transfer-Encoding: chunked
X-Powered-By: Undertow/1

{
    "access_token": "eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIyNzU5ODRiZC05OTI0LTQ5NTgtYTQ4OC00OTI2MWIwZDhjMzIiLCJleHAiOjE0NDA1MzEwMTIsIm5iZiI6MCwiaWF0IjoxNDQwNTMwNzEyLCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgwODAvYXV0aC9yZWFsbXMvc3RvdHRpZSIsImF1ZCI6ImFwaW1hbiIsInN1YiI6ImRlNGFmMzIyLTg1YjItNGRiZS04ZDUzLTZhMmVlMjllNDA4MCIsImF6cCI6ImFwaW1hbiIsInNlc3Npb25fc3RhdGUiOiI1MjM4NmU0MS1hZTgxLTQwNWMtYjc1Yi1mMzNlZjM1MTM1OGQiLCJjbGllbnRfc2Vzc2lvbiI6ImY4MGExNDEyLTZiMjYtNGZlYS05YmZiLWJlMGI4OWNhZWM1OSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJlY2hvbWVpc3RlciJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJ2aWV3LXByb2ZpbGUiXX19LCJuYW1lIjoiIiwicHJlZmVycmVkX3VzZXJuYW1lIjoicmluY2V3aW5kIn0.WJXWYogF9cBlTG8PMfrnsxhn6Q-1r2Q0WRSfaKcGGzkr4qJN3kolR6ayIKUDj7PTLsOxAuIWsBMg8ZTwL17aASooW1Z0G70IvWcD-rMPflBn3PemX2eZkZ98A79JbTThw_4ptfx7FR5DJyo4CZT8A64KnRDPXKG1n1cNvyJdY5I1kdtnEGzekgFhBSWFwiLt-sHYl9Zl2zXYpL6_e-XOYMbrd73GmxiyHdMI_yhyeEOYZWPvlpo6CkKZQoPEftb11dJrGbLFw0T5NLzsMyJY5SxfEWnhUAT1ZnD72vgKec2Nfln7PGJBMxyKyvR8xgIjtSbHDb4TUGDxcFS9J7LTDw", 
    "expires_in": 300, 
    "id_token": "eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiJhZjhkODMwNS0wMDQyLTQ4NjgtOThiZC1kMjY3ZDFjMDg2NzciLCJleHAiOjE0NDA1MzEwMTIsIm5iZiI6MCwiaWF0IjoxNDQwNTMwNzEyLCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgwODAvYXV0aC9yZWFsbXMvc3RvdHRpZSIsImF1ZCI6ImFwaW1hbiIsInN1YiI6ImRlNGFmMzIyLTg1YjItNGRiZS04ZDUzLTZhMmVlMjllNDA4MCIsImF6cCI6ImFwaW1hbiIsInNlc3Npb25fc3RhdGUiOiI1MjM4NmU0MS1hZTgxLTQwNWMtYjc1Yi1mMzNlZjM1MTM1OGQiLCJuYW1lIjoiIiwicHJlZmVycmVkX3VzZXJuYW1lIjoicmluY2V3aW5kIn0.YMo6b2gn1ppI1TfagGC-tRVbhMc0ComGL5xXJAZoTurl1rT3Ee9iuDVAazf8LUhkRU5Yx5Yz635De6WBQXCZsU17_UULO_P8Wnh4VXnuoiTM8DF036TWa88486jv9RDudANWWeYuuo5fOtNtkpPOTKPV6GIoo2rHqUuGwRaG4mSY3jlUPNvflcx04pWkIA4cANS4dZTjnKzX9UKwV9DAk2a-739Di4oi9E-k2lXf8kcygXo55eNGFB0YXw30gyJUwYKK4avfDmBsW7wbgyyR_fgYgfRVDpRRlxi8fLqbQJUid-KbpC2myJXJvltQHfzxTMMTpDiR49zhr3IZg3h_cw", 
    "not-before-policy": 0, 
    "refresh_expires_in": 1800, 
    "refresh_token": "eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI3MDBkZDFhZS04MGRjLTQxNWMtYWM2NC1mNTlhMjFkMDMyYjYiLCJleHAiOjE0NDA1MzI1MTIsIm5iZiI6MCwiaWF0IjoxNDQwNTMwNzEyLCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgwODAvYXV0aC9yZWFsbXMvc3RvdHRpZSIsInN1YiI6ImRlNGFmMzIyLTg1YjItNGRiZS04ZDUzLTZhMmVlMjllNDA4MCIsInR5cCI6IlJFRlJFU0giLCJhenAiOiJhcGltYW4iLCJzZXNzaW9uX3N0YXRlIjoiNTIzODZlNDEtYWU4MS00MDVjLWI3NWItZjMzZWYzNTEzNThkIiwiY2xpZW50X3Nlc3Npb24iOiJmODBhMTQxMi02YjI2LTRmZWEtOWJmYi1iZTBiODljYWVjNTkiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZWNob21laXN0ZXIiXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50Iiwidmlldy1wcm9maWxlIl19fX0.UnnYysyRoUmzlTnSoF4WFWXmYVatrp-KN-acpCCuN2WFyri8j9RLOxTYWfckylvl7865nFLTwnRVz7y0bSMwDRuH_u6HOPYR9kYMA7piRVPpF-QT7Cq1MxLDQzOAPhklLCTk-7wreS7HDrKoIjh2n4Y0aPEmofgQBMzv8Y-HDDT12xrGkArX5t2KtSiIO1ZxWWym3_WjsxMaPXQnVt3iqiU--HHi5XC20435qC-xDRNobTfkI4SNA7dIwFGjNp3aWPJqfC_8J53zyPTQ6zmi22lpc63tHJqU2le5VlJSY3sGt0jS2SZae7oGYkmBlFQZ-Fe60lo7CSWwnUxc9FHBPg", 
    "session-state": "52386e41-ae81-405c-b75b-f33ef351358d", 
    "token_type": "bearer"
}

###Stripping the JWT parts...

According to the oAuth JSON Web Token spec the JWT is divided in three pices (with a . delimiter). So in the above sample response we have:

  • Header:
eyJhbGciOiJSUzI1NiJ9
  • Payload:
eyJqdGkiOiIyNzU5ODRiZC05OTI0LTQ5NTgtYTQ4OC00OTI2MWIwZDhjMzIiLCJleHAiOjE0NDA1MzEwMTIsIm5iZiI6MCwiaWF0IjoxNDQwNTMwNzEyLCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgwODAvYXV0aC9yZWFsbXMvc3RvdHRpZSIsImF1ZCI6ImFwaW1hbiIsInN1YiI6ImRlNGFmMzIyLTg1YjItNGRiZS04ZDUzLTZhMmVlMjllNDA4MCIsImF6cCI6ImFwaW1hbiIsInNlc3Npb25fc3RhdGUiOiI1MjM4NmU0MS1hZTgxLTQwNWMtYjc1Yi1mMzNlZjM1MTM1OGQiLCJjbGllbnRfc2Vzc2lvbiI6ImY4MGExNDEyLTZiMjYtNGZlYS05YmZiLWJlMGI4OWNhZWM1OSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJlY2hvbWVpc3RlciJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJ2aWV3LXByb2ZpbGUiXX19LCJuYW1lIjoiIiwicHJlZmVycmVkX3VzZXJuYW1lIjoicmluY2V3aW5kIn0
  • Signature:
WJXWYogF9cBlTG8PMfrnsxhn6Q-1r2Q0WRSfaKcGGzkr4qJN3kolR6ayIKUDj7PTLsOxAuIWsBMg8ZTwL17aASooW1Z0G70IvWcD-rMPflBn3PemX2eZkZ98A79JbTThw_4ptfx7FR5DJyo4CZT8A64KnRDPXKG1n1cNvyJdY5I1kdtnEGzekgFhBSWFwiLt-sHYl9Zl2zXYpL6_e-XOYMbrd73GmxiyHdMI_yhyeEOYZWPvlpo6CkKZQoPEftb11dJrGbLFw0T5NLzsMyJY5SxfEWnhUAT1ZnD72vgKec2Nfln7PGJBMxyKyvR8xgIjtSbHDb4TUGDxcFS9J7LTDw

###Decoding...

Using the Linux Bash base64 command and the jq utility (JSON processor for shell)

  • Header
> echo "eyJhbGciOiJSUzI1NiJ9" | base64 -d | jq '.'
{
  "alg": "RS256"
}

  • Payload
> echo "eyJqdGkiOiIyNzU5ODRiZC05OTI0LTQ5NTgtYTQ4OC00OTI2MWIwZDhjMzIiLCJleHAiOjE0NDA1MzEwMTIsIm5iZiI6MCwiaWF0IjoxNDQwNTMwNzEyLCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgwODAvYXV0aC9yZWFsbXMvc3RvdHRpZSIsImF1ZCI6ImFwaW1hbiIsInN1YiI6ImRlNGFmMzIyLTg1YjItNGRiZS04ZDUzLTZhMmVlMjllNDA4MCIsImF6cCI6ImFwaW1hbiIsInNlc3Npb25fc3RhdGUiOiI1MjM4NmU0MS1hZTgxLTQwNWMtYjc1Yi1mMzNlZjM1MTM1OGQiLCJjbGllbnRfc2Vzc2lvbiI6ImY4MGExNDEyLTZiMjYtNGZlYS05YmZiLWJlMGI4OWNhZWM1OSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJlY2hvbWVpc3RlciJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJ2aWV3LXByb2ZpbGUiXX19LCJuYW1lIjoiIiwicHJlZmVycmVkX3VzZXJuYW1lIjoicmluY2V3aW5kIn0=" | base64 -d | jq '.'
{
  "preferred_username": "rincewind",
  "name": "",
  "resource_access": {
    "account": {
      "roles": [
        "manage-account",
        "view-profile"
      ]
    }
  },
  "realm_access": {
    "roles": [
      "echomeister"
    ]
  },
  "allowed-origins": [],
  "client_session": "f80a1412-6b26-4fea-9bfb-be0b89caec59",
  "session_state": "52386e41-ae81-405c-b75b-f33ef351358d",
  "jti": "275984bd-9924-4958-a488-49261b0d8c32",
  "exp": 1440531012,
  "nbf": 0,
  "iat": 1440530712,
  "iss": "http://127.0.0.1:8080/auth/realms/stottie",
  "aud": "apiman",
  "sub": "de4af322-85b2-4dbe-8d53-6a2ee29e4080",
  "azp": "apiman"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment