Laravel: Solution for using custom Passport sign in with Guzzle - laravel

I am trying to do a route /api/user/signin and inside of controller to make a Guzzle HTTP post to /oauth/token. Great but the server stall. I found this: https://stackoverflow.com/a/46350397/5796307
So how I should do? How to call /oauth/token without a HTTP request? I can "create" a request class and pass to that function?

No need to use Guzzle or file_get_contents, create a new HTTP request from within the controller function and route it through the framework:
public function signin (Request $request) {
// get an appropriate client for the auth flow
$client = Client::where([
'password_client' => true,
'revoked' => false
])->first();
// make an internal request to the passport server
$tokenRequest = Request::create('/oauth/token', 'post', [
'grant_type' => 'password',
'client_id' => $client->id,
'client_secret' => $client->secret,
'username' => $request->input('email'),
'password' => $request->input('password')
]);
// let the framework handle the request
$response = app()->handle($tokenRequest);
// get the token from the response if authenticated, other wise redirect to login
}

Related

How to generate client access token for any client from controller?

We can generate token using oauth work flow.
But i want to generate the token internally from my own controller. How do we achieve that?
As the documentation suggest, you can call your own oauth server to get the token.
use Illuminate\Support\Facades\Http;
private function getClientToken() {
$response = Http::asForm()->post(route('passport.token'),[
'grant_type' => 'client_credentials',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
'scope' => 'your-scope',
]);
return $response->json()['access_token'];
}

Laravel cors throws error when trying to run Request::create

I have a custom login method for my Laravel Passport API.
I am using Request::create to call the /oauth/token endpoint from inside my login method.
The problem is that from within my React project, I am getting a CORS error.
The error ONLY happens when using the login method and I think I have traced it down to the way that the data is being 'returned'
I am using the barryvdh/laravel-cors package and the relevant portion of my login method is as follows;
$data = [
'grant_type' => 'password',
'client_id' => 2,
'client_secret' => 'ggdfgdvsreckuscenusekubsvbd',
'username' => $request->email,
'password' => $request->password,
'scope' => '',
];
$request = Request::create('/oauth/token', 'POST', $data);
return app()->handle($request);
Is there a way that I can cast that $request response to a variable and then return it using the standard response->json?
If i return the $request as it is, it doesnt give me any of the data that the return app()->handle($request); line gives me i.e token, refresh token etc etc
I can use all other POST methods in my API except this one.
You can try it this way. Its basically launching a new request from a another request
$data = [
'grant_type' => 'password',
'client_id' => 2,
'client_secret' => 'ggdfgdvsreckuscenusekubsvbd',
'username' => $request->email,
'password' => $request->password,
'scope' => '',
];
$request = app()->make('request');
$request->request->add($data);
$tokenRequest = Request::create(
env('APP_URL') . '/oauth/token',
'post'
);
return Route::dispatch($tokenRequest);
Dispatch the route and handle the response internally instead of returning different headers
protected function attemptLogin(Request $request)
{
// forward the request to the oauth token request endpoint
$res = Route::dispatch(request()->create('oauth/token', 'POST', $data));
// Return true or false based on response status code
return $res->getStatusCode() === 200 ? true : false;
}

Laravel passport refresh token

I am using a Laravel version 5.5 using Passport for authentication.
I have successfully create the token and can access it using the auth:api middleware.
But whenever user login into system it create new token for that user. I just want to refresh user last token and send it back instead of creating a new token.
I have used the following code to generate auth token
$token = $user->createToken('string-'.$user->id)->accessToken;
It generate the token with 1075 characters but when i checked in database table oauth_access_tokens it shows me the token with 80 characters.
How can i get last generated token using 80 character token and refresh it and send it back?
Thanks in Advance
If your application issues short-lived access tokens, users will need to refresh their access tokens via the refresh token that was provided to them when the access token was issued. In this example, we'll use the Guzzle HTTP library to refresh the token:
$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'refresh_token',
'refresh_token' => 'the-refresh-token',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
This /oauth/token route will return a JSON response containing access_token, refresh_token, and expires_in attributes. The expires_in attribute contains the number of seconds until the access token expires.
I've done something like.
Created an endpoint for grant refresh token.
and in my controller,
public function userRefreshToken(Request $request)
{
$client = DB::table('oauth_clients')
->where('password_client', true)
->first();
$data = [
'grant_type' => 'refresh_token',
'refresh_token' => $request->refresh_token,
'client_id' => $client->id,
'client_secret' => $client->secret,
'scope' => ''
];
$request = Request::create('/oauth/token', 'POST', $data);
$content = json_decode(app()->handle($request)->getContent());
return response()->json([
'error' => false,
'data' => [
'meta' => [
'token' => $content->access_token,
'refresh_token' => $content->refresh_token,
'type' => 'Bearer'
]
]
], Response::HTTP_OK);
}

showing {"error":"Unauthenticated."} on laravel api call

showing {"error":"Unauthenticated."}, while calling larvel API in Laravel 5.4 and passport version: v1.0.9, using ajax call.
Calling from route api:
Route::get('category/get_tree_data', 'CategoryApiController#getTreeData')->middleware('auth:api');
If you set up Laravel Passport properly, you should have this in your view:
You need to create a client, that client has a client id and a client secret.
Now you need to open your consumer app which shall contain your client id and your client secret.
It looks like this(you have to change the token and id to your specific one):
class OAuthController extends Controller
{
public function redirect()
{
$query = http_build_query([
'client_id' => 3,
'redirect_uri' => 'http://localhost/app/public/callback',
'response_type' => 'code',
'scope' => '',
]);
return redirect('http://localhost/app/public/oauth/authorize?' . $query);
}
public function callback(Request $request)
{
$http = new Client;
$response = $http->post('http://localhost/app/public/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => 3, // from admin panel above
'client_secret' => 'BcTgzw6YiwWUaU8ShX4bMTqej9ccgoA4NU8a2U9j', // from admin panel above
'redirect_uri' => 'http://localhost/app/public/callback',
'code' => $request->code // Get code from the callback
]
]);
return json_decode((string) $response->getBody(), true);
}
}
Now you need to call that consumer app and authorize your application.
If that worked you get an access token + a refresh token.
It should look like this:
Now you can test this using a program like postman.
You basically call your get route and add the access token, which gives you access to the api, like this:
If you have any more question I recommend reading the docs.
Thus I highly recommend watching following video from Taylor Otwell.
Of course you can give me a comment aswell if you have any more questions.
Add this code inside your /resources/assets/js/bootstrap.js file
window.axios.defaults.headers.common = {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
'X-Requested-With': 'XMLHttpRequest'
};
working perfectly...
I have the same issue with Laravel 5.8 when calling /api/user on auth:api middleware, I've tried to call the API url using Postman but got unauthenticated message
And I am able to fixed it by changing the hash value to false in config/auth.php file
// routes/api.php
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
// config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false, // <-- change this to false
],
],
I faced the same issue.
In my case, I was caching generated token after user login.
$token = $user->createToken('API'.'-'.strtoupper($user->username).'-'.'-X-AUTH-TOKEN', [$this->scope]);
Cache::add(strtoupper($user->username).'-'. 'X-TOKEN', $token->accessToken, $expiresAt);
After debugging, tried clearing cache
Cache::clear();
and it's working now.

Laravel Passport Authenticate User Before Authorize

I am working on a project where 3rd party apps can access data from Laravel server. I also have created a client application in laravel for testing.
Following code ask for authorization and its working fine.
Route::get('/applyonline', function () {
$query = http_build_query([
'client_id' => 5,
'redirect_uri' => 'http://client.app/callback',
'response_type' => 'code',
'scope' => '',
]);
return redirect('http://server.app/oauth/authorize?'.$query);
});
How can I authenticate a user before authorization? Right now I can access data form server using this code.
Route::get('/callback', function (Request $request) {
$http = new GuzzleHttp\Client;
$response = $http->post('http://server.app/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 2,
'client_secret' => 'fcMKQc11SwDUdP1f8ioUf8OJwzIOxuF8b2VKZyip',
'username'=> 'ali#gmail.com',
'password' => 'password',
],
]);
$data = json_decode((string) $response->getBody(), true);
$access_token = 'Bearer '. $data['access_token'];
$response = $http->get('http://server.app/api/user', [
'headers' => [
'Authorization' => $access_token
]
]);
$applicant = json_decode((string) $response->getBody(), true);
return view('display.index',compact('applicant'));
});
Although above code works fine but I don't think its a good way to ask username and password at client side.
I want to use this flow (Same as facebook allows)
Click To Get Data From Server
Enter Username and Password
Authorize App
Access data for authenticated user
Well that was a stupid mistake. It works fine with authorization_code grant type. My mistake was that I was testing both server and client in same browser without logout. So client was accessing its own data from server. Also this flow diagram really helped me to understand the process of passport authorization.
http://developer.agaveapi.co/images/2014/09/Authorization-Code-Flow.png
Route::get('/callback', function (Request $request) {
$http = new GuzzleHttp\Client;
$response = $http->post('http://server.app/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => 5,
'client_secret' => 'fcMKQc11SwDUdP1f8ioUf8OJwzIOxuF8b2VKZyip',
'redirect_uri' => 'http://client.app/callback',
'code' => $request->code,
],
]);
return json_decode((string) $response->getBody(), true);});

Resources