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

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'];
}

Related

is it dangerous to put the client_secret on the client side?

I want to create an authentication system with laravel , passport and vue js . Which is the best choice
1 - laravel
public function login(Request $request)
{
$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
'username' => $request->username,
'password' => $request->password,
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
}
1 - vuejs
axios.post('/login', {
'username': 'xxxxxx',
'password':'xxxxxxxxx'
})
.then(response => {
//login
}).catch(error => {
//error
})
2-vuejs
axios.post('/oauth/token', {
'username': 'xxxxxx',
'password':'xxxxxxxxx',
'grant_type' => 'password',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
})
.then(response => {
//login
}).catch(error => {
//error
})
In Solution 2, is it dangerous to put the client_secret on the client side?
Not at all. Keep it in a .env file and make sure to put it in your .gitignore
I would prefer Solution 1. In Solution 2 everyone can read the client_secret and pretend to be the client.
I would suggest option 3: using passports built in JS authentication.
You authenticate using the standard auth flow that ships with Laravel. Then add the \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class middleware on the routes that serve VueJS. Make sure your axios is configured to include the CSRF token by default. If you use the app.js that ships with laravel then this is already done for you. You can then make your axios requests as usual. (making sure to include the CSRF token. Th.
I would suggest you to use solution 1. It protects your OAuth service keeping it hidden and not reacheable. In addition you should implement a mechanism to refresh the tokens.

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);
}

refresh token in passport

I am new in laravel. I am using laravel passport for authentication in APIs for mobile app. Now i want to know that how can i achieve following functionality.
I want to expire my current accesstoken within 24 hours.
After expire current accesstoken i want to refresh my accesstoken.
using that refreshed accesstoken i want to access app.
Can anyone help me to solve this. I have create following code to generate token as well as to refresh token
My login function code
$client = \Laravel\Passport\Client::where('password_client', 1)->first();
$request->request->add([
'grant_type' => 'password',
'client_id' => $client->id,
'client_secret' => $client->secret,
'scope' => null,
'username' => request('email'),
'password' => request('password'),
]);
$proxy = Request::create(
'oauth/token', 'POST'
);
$tokens = \Route::dispatch($proxy);
$tokrnresponse = (array) $tokens->getContent();
$tokendata = json_decode($tokrnresponse[0]);
echo $tokendata->access_token
will give me accesstoken and
echo $tokendata->refresh_token
will give me refresh token
now from postman i am try to refresh token using another api called refresh_token(). i am passing access token in header.
refresh_token() Code
$client = \Laravel\Passport\Client::where('password_client', 1)->first();
$request->request->add([
'grant_type' => 'refresh_token',
'client_id' => $client->id,
'refresh_token' => '<refresh_token>',
'client_secret' => $client->secret,
'scope' => null
]);
$proxy = Request::create(
'oauth/token', 'POST'
);
$tokens = \Route::dispatch($proxy);
$tokrnresponse = (array) $tokens->getContent();
$tokendata = json_decode($tokrnresponse[0]);
print_r($tokendata);
exit;
I got new access token using above code, but when i try to access other api using refreshed access token then it gives me "Unauthenticated" error. can anyone help me.

Laravel: Solution for using custom Passport sign in with Guzzle

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
}

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