How to parse the jwt token from controller $jwtManager->decode($jwt) using pure token ( token as a string )

Viewed 13930

So I'm using Lexik JWT Authentication Bundle (Symfony 2.6) and successful created user and token using this code:

$userRegistration = new UserRegistration();
$userRegistration->setPassword($request->request->get('password'));
$userRegistration->setEmail($request->request->filter('email'));
$userRegistration->setName($request->request->filter('name'));

$token = $this->jwtManager->create($RegisteredUser);
return $this->responseProvider->ok((object) [
    'userId' => $RegisteredUser->getId(),
    'token' => $token
]);

Response :

"data": {
    "userId": 24,
    "token": "eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJqYWdhZHVAaHViaWktbmV0d29yay5jb20iLCJleHAiOjE1MzYxNTI0MDAsImlhdCI6MTUzNTU0NzYwMH0.B7gnfGdW1ijAIlo9xUI0DwkGaajQAQPBkRx4ChILXRNtpLdwgEl_9gvWdiidFbSXJseS8jslOfuAFUIWATmbNBoWVa3nc8SxkIrKI29xZuN6hB7R-63RH2BKsAVPsEjgTIJoqkkCrfrSum-_d3LEf36jcXqZb8M-GRKI477IwSDDwG_7YK5v0mu8N4TATXhN0tZGNYxp8Y27EI-g0Gmj9BIiobxnqVVoBWHN5J8d-UCrXRq94ifhEiQBxkG9r_eacMscB80n1VsiN2ouKH2kX-HRxRJmcgmydxvR7RcEW-P6koTxkaZJGO6mv7auSudTFlDENpwD4OD7gtn_wMUDS_OuN8WT7rZp8lwKY9f8J9fiGyq5J-8C_HmyjW-h8WhuJmTUaKhCZ-eLgDm4Vs2IQGYkHJEDFumnIZ607MAa1CW1ChAvurqvUqJ3G4TTN4wYqAHpSKz4y8SAMLjO91cedBPH6K5i9lh5htF-mW_htem7e5ornicU_djSccgHbxfXHQYTHCnqLp7-ONfl_p4nmhIEK0wcF0gkBXbIitzeTjy7C_uf_FV1sLPE5cY3PUP42DmHrG4PuXHLv_L1EjErkrpna7pChKA_TPeiZjqMcQoE70sZw8rr8KnRF2hpABdU_M2ZXOt_vF5-T8mLmKqs0LHxE089vVC3xsAh0mUr4FE"
} 

The problem started when I try to decode current token in other controller using jwtManager->decode method :

$jwt = "eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJqYWdhZHVAaHViaWktbmV0d29yay5jb20iLCJleHAiOjE1MzYxNTI0MDAsImlhdCI6MTUzNTU0NzYwMH0.B7gnfGdW1ijAIlo9xUI0DwkGaajQAQPBkRx4ChILXRNtpLdwgEl_9gvWdiidFbSXJseS8jslOfuAFUIWATmbNBoWVa3nc8SxkIrKI29xZuN6hB7R-63RH2BKsAVPsEjgTIJoqkkCrfrSum-_d3LEf36jcXqZb8M-GRKI477IwSDDwG_7YK5v0mu8N4TATXhN0tZGNYxp8Y27EI-g0Gmj9BIiobxnqVVoBWHN5J8d-UCrXRq94ifhEiQBxkG9r_eacMscB80n1VsiN2ouKH2kX-HRxRJmcgmydxvR7RcEW-P6koTxkaZJGO6mv7auSudTFlDENpwD4OD7gtn_wMUDS_OuN8WT7rZp8lwKY9f8J9fiGyq5J-8C_HmyjW-h8WhuJmTUaKhCZ-eLgDm4Vs2IQGYkHJEDFumnIZ607MAa1CW1ChAvurqvUqJ3G4TTN4wYqAHpSKz4y8SAMLjO91cedBPH6K5i9lh5htF-mW_htem7e5ornicU_djSccgHbxfXHQYTHCnqLp7-ONfl_p4nmhIEK0wcF0gkBXbIitzeTjy7C_uf_FV1sLPE5cY3PUP42DmHrG4PuXHLv_L1EjErkrpna7pChKA_TPeiZjqMcQoE70sZw8rr8KnRF2hpABdU_M2ZXOt_vF5-T8mLmKqs0LHxE089vVC3xsAh0mUr4FE";
$test = $this->jwtManager->decode($jwt);

But the JWTManager::decode() must implement interface Symfony\Component\Security\Core\Authentication\Token\TokenInterface and not expect string given.

My goal is just to get userId form this token but can't find any information how to decode the token. Does anyone have any idea how to simply decode the token?

3 Answers

Manually getting the information out of a token without using a JWT lib is quite simple.

A JWT string consists of 3 parts: The base64url encoded header and payload, both are JSON 'objects', and the signature. All 3 parts are separated by a ..

So you just need to split the token into its 3 parts, done here with explode, then decode the base64url encoded strings (base64_decode) and finally decode the JSON (json_decode):

$token = "eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJqYWdhZHVAaHViaWktbmV0d29yay5jb20iLCJleHAiOjE1MzYxNTI0MDAsImlhdCI6MTUzNTU0NzYwMH0.B7gnfGdW1ijAIlo9xUI0DwkGaajQAQPBkRx4ChILXRNtpLdwgEl_9gvWdiidFbSXJseS8jslOfuAFUIWATmbNBoWVa3nc8SxkIrKI29xZuN6hB7R-63RH2BKsAVPsEjgTIJoqkkCrfrSum-_d3LEf36jcXqZb8M-GRKI477IwSDDwG_7YK5v0mu8N4TATXhN0tZGNYxp8Y27EI-g0Gmj9BIiobxnqVVoBWHN5J8d-UCrXRq94ifhEiQBxkG9r_eacMscB80n1VsiN2ouKH2kX-HRxRJmcgmydxvR7RcEW-P6koTxkaZJGO6mv7auSudTFlDENpwD4OD7gtn_wMUDS_OuN8WT7rZp8lwKY9f8J9fiGyq5J-8C_HmyjW-h8WhuJmTUaKhCZ-eLgDm4Vs2IQGYkHJEDFumnIZ607MAa1CW1ChAvurqvUqJ3G4TTN4wYqAHpSKz4y8SAMLjO91cedBPH6K5i9lh5htF-mW_htem7e5ornicU_djSccgHbxfXHQYTHCnqLp7-ONfl_p4nmhIEK0wcF0gkBXbIitzeTjy7C_uf_FV1sLPE5cY3PUP42DmHrG4PuXHLv_L1EjErkrpna7pChKA_TPeiZjqMcQoE70sZw8rr8KnRF2hpABdU_M2ZXOt_vF5-T8mLmKqs0LHxE089vVC3xsAh0mUr4FE";

$tokenParts = explode(".", $token);  
$tokenHeader = base64_decode($tokenParts[0]);
$tokenPayload = base64_decode($tokenParts[1]);
$jwtHeader = json_decode($tokenHeader);
$jwtPayload = json_decode($tokenPayload);
print $jwtPayload->username;

In the last line you have the desired information.

You can also inspect your token on https://jwt.io to see which fields are in the payload. There's also a good introduction about JWT on that site.

You can use the JWTEncoder service for this. The service name is lexik_jwt_authentication.jws_provider.lcobucci

Or if you want class named services use Lexik\Bundle\JWTAuthenticationBundle\Encoder\JWTEncoderInterface

The method you are looking for is decode()

$jwtEncoder->decode($yourToken);

Please find my code for doing this without any libraries.

function decodeJWTPayloadOnly($token){
        $tks = explode('.', $token);
        if (count($tks) != 3) {
            return null;
        }
        list($headb64, $bodyb64, $cryptob64) = $tks;
        $input=$bodyb64;
        $remainder = strlen($input) % 4;
        if ($remainder) {
            $padlen = 4 - $remainder;
            $input .= str_repeat('=', $padlen);
        }
        $input = (base64_decode(strtr($input, '-_', '+/')));

        if (version_compare(PHP_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) {
            $obj = json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
        } else {
            $max_int_length = strlen((string) PHP_INT_MAX) - 1;
            $json_without_bigints = preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
            $obj = json_decode($json_without_bigints);
        }
        return $obj;
}
Related