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"
}