@stueynet I have been playing with Passport for the last two days to see if it would work in my own personal setup. The direct JWT authentication you mentioned has nothing to do with oAuth2.
The way it works is by adding the CreateFreshApiToken middleware to your web middleware group which will create an encrypted JWT cookie called laravel_token. You can utilize that cookie along with a csrf token to authenticate through your API without having to go through the whole oAuth flow. Take a look at the example below.
In your master view (usually) you can add an inline script that will house your csrf token.
window.Laravel = {
csrfToken: "{{ csrf_token() }}"
};
Then when making your Ajax request you can attach that as a header. I'll write it with Vue and Vue Resource to keep in line with the documentation.
export default {
ready() {
this.$http.get('/users')
.then(response => {
console.log(response.data);
});
}
}
By default, Laravel 5.3 includes a bootstrap.js file that sets up an interceptor to add the csrf token. It looks like this.
Vue.http.interceptors.push((request, next) => {
request.headers['X-CSRF-TOKEN'] = Laravel.csrfToken; // Laravel is coming from the window object
next();
});
Now assuming that your API exists on the same domain, you can skip down to the next part, but what if you're using a sub domain? There's a bit more work you have to do.
With good ol' jQuery we were used to setting something like the following.
$.ajax({
xhrFields: {
withCredentials: true
}
});
But with Vue Resource (at least the latest version), we have to do this (the documentation is a bit lacking at the moment, but I'm sure that will be solved soon enough).
Vue.http.options.credentials = true;
So all in all, we end up with whats below. We can add in the request.url line so we don't have to write the full hostname before every url in every ajax call.
Vue.http.options.credentials = true;
Vue.http.interceptors.push((request, next) => {
request.url = 'http://api.example.dev' + request.url;
request.headers['X-CSRF-TOKEN'] = Laravel.csrfToken;
next();
});
So now we get back to the server side, with Passport installed and set up, we reach the auth:api middleware. We see one call in the handle method in this new middleware, to the authenticate method which looks like this.
protected function authenticate(array $guards)
{
if (empty($guards)) {
return $this->auth->authenticate();
}
foreach ($guards as $guard) {
if ($this->auth->guard($guard)->check()) {
return $this->auth->shouldUse($guard);
}
}
throw new AuthenticationException;
}
The $guard that get's passed through in the default setup is api and when we call ->check() it is being called on the \Illuminate\Auth\RequestGuard class. check() does nothing more then the following.
return ! is_null($this->user());
If we following that through, we eventually get taken to our proper guard for passport, which is \Laravel\Passport\Guards\TokenGuard. The user() method takes the following form.
public function User(Request $request)
{
if ($request->bearerToken()) {
return $this->authenticateViaBearerToken($request);
} elseif ($request->cookie('laravel_token')) {
return $this->authenticateViaCookie($request);
}
}
So from this, we can see that either a bearer token (the actual oAuth2 stuff) or the cookie is required to authenticate. Now seeing as a cookie can only be read by the domain (or a subdomain if set up properly), that makes it a prime candidate for consuming your own API with javascript. I'm not going to bother going further, but that is the basics of how to consume your own API without the whole oAuth flow.