Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"The JWT string must have two dots" #349

Closed
libasoles opened this issue Apr 14, 2017 · 4 comments
Closed

"The JWT string must have two dots" #349

libasoles opened this issue Apr 14, 2017 · 4 comments

Comments

@libasoles
Copy link

libasoles commented Apr 14, 2017

I can't get authorized with "CreateFreshApiToken" feature. I get: "The resource owner or authorization server denied the request.". So I researched a little.

Basically, League's OAuth2 BearerTokenValidator keeps complaning that "The JWT string must have two dots".

And it's true. A JWT token must have dots to concatenate the three component parts: header.payload.signature

The Passport docs says: "This cookie contains an encrypted JWT". So, I get it, you are encoding the JWT somehow. But then, how can I do in js to decrypt that? I'm not using Vue.js, So I write my own authorization headers passing the "encoded JWT token". And as far as I see, Passport is not performing that decoding step.

@libasoles
Copy link
Author

libasoles commented Apr 14, 2017

Tried with base64 decode and passed from this:

eyJpdiI6ImNqcUhJSXJYUUJmWFBwWXNDbkRFVnc9PSIsInZhbHVlIjoiRnZFR2laVldyeTdndnhxY292eWkzc241VkdtQU9iNjMwaTB0aFJSYVdQNTBpcGpRVUFMd0ZNT0wzTHptWFRZXC82SVpWa2FNck1uUkh0U29Hc1lmeVh4RFgrTlNLaE1zd0N5Zmgxd0JYTmFaZXU1YU45UWNVQVVLbnRxdnlWYmh2aGdcL1VBNmMyaGZYRWZ5T1JPTEVCTklpaW1xcnBTcUJPR3E0RGxEaEpKZXV3VGxzbGkrQjVNZkdudDZ5ZHdyeGkzMllRODFOM2o2S1hYSkUwY3JjWEVreUVcLzI4Q3I3bTlaQ2JSRUJzVnRjVjR0dFhGTDVjdHEzMU5BRWk1eWhDR01qQjJOcnNGNXNuYkozQzFFT1hneFE9PSIsIm1hYyI6IjBhNGM5YjhhMWQ0YWVlMzg2MTZiNWE2NDBiNzdjMWZlYWFkZjY3MDE1YTkyZjMzMjNlYWY3MGY3NjcyY2Y2YzIifQ==

to this:

{"iv":"cjqHIIrXQBfXPpYsCnDEVw==","value":"FvEGiZVWry7gvxqcovyi3sn5VGmAOb630i0thRRaWP50ipjQUALwFMOL3LzmXTY\/6IZVkaMrMnRHtSoGsYfyXxDX+NSKhMswCyfh1wBXNaZeu5aN9QcUAUKntqvyVbhvhg\/UA6c2hfXEfyOROLEBNIiimqrpSqBOGq4DlDhJJeuwTlsli+B5MfGnt6ydwrxi32YQ81N3j6KXXJE0crcXEkyE\/28Cr7m9ZCbREBsVtcV4ttXFL5ctq31NAEi5yhCGMjB2NrsF5snbJ3C1EOXgxQ==","mac":"0a4c9b8a1d4aee38616b5a640b77c1feaadf67015a92f3323eaf70f7672cf6c2"}

So, it looks decoded. But not a valid JWT token.

Not sure what to do. Can't get passport to work and there are a lot of threads out there with the same issue. And it's funny, but some of the said the solved it copying the token right (like, the were copying the cookie from the browser and it was cut, but it's not my case).

@libasoles
Copy link
Author

libasoles commented Apr 14, 2017

I keep trying. So, the three dots does exists. I was getting them in the wrong way, using PHP $_COOKIE instead of Laravel helpers.

This is what I'm trying to do:

<script>
        window.Laravel = {!! json_encode([
            'csrfToken' => csrf_token(),
            'laravel_token' => request()->cookie('laravel_token') 
        ]) !!};
</script>

And then, I configure ajax request for angularjs like this:

$httpProvider.defaults.headers.common = { 
        'Authorization': 'Bearer '+Laravel.laravel_token,
        'access_token': Laravel.laravel_token,
        'Content-Type': 'application/json',
        'Accept': 'application/json;odata=verbose',
        'X-Requested-With': "XMLHttpRequest",
        'X-CSRF-TOKEN': Laravel.csrfToken,
      };

The error now that I get the correct JWT token is: 'Access token could not be verified'

So, can't get passport to work but the error changed so I think we should close the issue. Any clue is welcome anyway.

@libasoles
Copy link
Author

FYI:

CreateFreshApiToken calls Laravel\Passport\ApiTokenCookieFactory to generate the JWT token. And as far as I understand it uses "HS256" algorithm (see Firebase\JWT class, line 153).

Then, when receiving a new request with the Bearer auth token, we get into: BearerTokenValidator class. Line 52:

$token = (new Parser())->parse($jwt);
 if ($token->verify(new Sha256(), $this->publicKey->getKeyPath()) === false) {
      throw OAuthServerException::accessDenied('Access token could not be verified');
}

That verification fails. See:

Class /vendor/lcobucci/jwt/src/Token.php line 191
Method: Verify

if ($this->headers['alg'] !== $signer->getAlgorithmId()) {
      return false;
}

That method returns false. And if I compare the algorithms with a var dump I get:
"HS256" !== "RS256"

So, Passport with CreateFreshApiToken wont work for me. Don't know why!

@libasoles
Copy link
Author

Nevermind. I knew I was over-complicating something.

There's no need to send 'Authorization' header using CreateFreshApiToken feature.

There's a nice tutorial here btw: https://laracasts.com/series/whats-new-in-laravel-5-3/episodes/13

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant