0
votes

I have recently developed a password grant API to be used by my client application. It is successfully generating access tokens for users after the client has been authorized.

The problem I'm facing now is how to pass the access token back from client application to Laravel with each request? (as done by Headers in passport) I have gone through the laravel API Authentication by passport documentation.

What I'm trying to do

I have already tested the work flow of the API on postman. It was working fine. But now I'm trying to hard code everything. SO now I'm trying to fetch posts for the users who are having the access tokens.

api.php (routes file)

Route::post('login', 'API\UserController@userSignIn')->name('login');

Route::middleware('auth:api')->get('/posts', function() {
$accessToken = Cookie::get('accessToken');

$client = new \GuzzleHttp\Client;
  $response = $client->request('GET', 'http://tcc.devp/api/posts', [
    'headers' => [
      'Accept' => 'application/json',
      'Authorization' => 'Bearer '.$accessToken,
    ],
  ]);
  return $accessToken;
})->name('posts');

API/UserController.php

public function userSignIn(Request $request){
  if(Auth::attempt(['email' => $request['email'], 'password' => $request['password']])){

  $http = new \GuzzleHttp\Client;

  $response = $http->post('http://tcc.devp/oauth/token', [
      'form_params' => [
      'grant_type' => 'password',
      'client_id' => 'client_id',
      'client_secret' => 'client_secret',
      'username' => $request['email'],
      'password' => $request['password'],
      'scope' => '*'
      ],
  ]);
  $response_array = json_decode((string) $response->getBody()->getContents(), true);

  $accessToken = $response_array['access_token'];
  $refreshToken = $response_array['refresh_token'];

  Cookie::queue('accessToken', $accessToken, 60);
  Cookie::queue('refreshToken', $refreshToken, 60);

  return redirect()->route('posts'); //MethodNotAllowedException due to this line
  }
  else{
      return response()->json(['error'=>'Unauthorised'], 401);
  }
}

While doing so, I'm getting this error MethodNotAllowedHttpException. I got to know that it is because I'm redirecting my post request to some other page in the controller. network tab is showing 302 status.

I have two questions to ask you-

  1. How can I get rid of MethodNotAllowedHttpException error?
  2. Is my way of passing the access token to the request correct? If not how can I do that? I have found no resources on the internet to guide me in this direction

Error Stack

Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException: in file C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\RouteCollection.php on line 255 Stack trace:

  1. Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException->() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\RouteCollection.php:255

  2. Illuminate\Routing\RouteCollection->methodNotAllowed() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\RouteCollection.php:242

  3. Illuminate\Routing\RouteCollection->getRouteForMethods() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\RouteCollection.php:176

  4. Illuminate\Routing\RouteCollection->match() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\Router.php:612

  5. Illuminate\Routing\Router->findRoute() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\Router.php:601

  6. Illuminate\Routing\Router->dispatchToRoute() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\Router.php:590

  7. Illuminate\Routing\Router->dispatch() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php:176

  8. Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http{closure}() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php:30

  9. Illuminate\Routing\Pipeline->Illuminate\Routing{closure}() C:\xampp\htdocs\xampp\tcc\vendor\fideloper\proxy\src\TrustProxies.php:56

  10. Fideloper\Proxy\TrustProxies->handle() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php:149

  11. Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php:53

  12. Illuminate\Routing\Pipeline->Illuminate\Routing{closure}() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\TransformsRequest.php:30

  13. Illuminate\Foundation\Http\Middleware\TransformsRequest->handle() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php:149

  14. Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php:53

  15. Illuminate\Routing\Pipeline->Illuminate\Routing{closure}() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\TransformsRequest.php:30

  16. Illuminate\Foundation\Http\Middleware\TransformsRequest->handle() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php:149

  17. Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php:53

  18. Illuminate\Routing\Pipeline->Illuminate\Routing{closure}() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\ValidatePostSize.php:27

  19. Illuminate\Foundation\Http\Middleware\ValidatePostSize->handle() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php:149

  20. Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php:53

  21. Illuminate\Routing\Pipeline->Illuminate\Routing{closure}() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode.php:46

  22. Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode->handle() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php:149

  23. Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php:53

  24. Illuminate\Routing\Pipeline->Illuminate\Routing{closure}() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php:102

  25. Illuminate\Pipeline\Pipeline->then() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php:151

  26. Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter() C:\xampp\htdocs\xampp\tcc\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php:116

  27. Illuminate\Foundation\Http\Kernel->handle() C:\xampp\htdocs\xampp\tcc\public\index.php:55

1
It looks like the way of passing the access token (good or not), should work. What feels inaccurate is trying to return posts right inside your userSignIn method. That would give the method two different responsibilities. What about performing a new call to posts once you have successfully signed in the user?alariva
I have to redirect user after signing him in. It will have to perform two responsibilities anyway. It is giving error for api requests only.Ujjwal Verma
There’s no need to do redirection in API on User sign-in as others mentioned. After invoking userLogIn consumers will receive a cookie to use in other calls that will be authenticating the user. For that you will need to add additional middleware as per rosswintle.uk/2018/01/laravel-simple-cookie-auth-simple-apisDaniel Protopopov

1 Answers

1
votes

How can I get rid of MethodNotAllowedHttpException error?

If you return a redirection response from a Laravel controller, the next request is always a GET request. To avoid the MethodNotAllowedHttpException error:

  • Make sure that you have a GET method registered for the path you used in the redirection response
  • (Or) return a JSON object to tell the client to send another request to the target URI.

Is my way of passing the access token to the request correct? If not how can I do that? I have found no resources on the internet to guide me in this direction

Your way of sending access token will work. It will be better if you can handle the case when the access token expires. In that case, the server can automatically exchange a new access token by using the refresh token.

Personally, I recommend against sending access token and refresh token to the client. I usually save these tokens to databases or server caches, keeping tokens hidden from the client side.