Since upgrading my application from Laravel 7 to 8, I've been having some minor issues with Laravel Passport. I created a test feature to retrieve a Passport token to make sure it was working, but I can't get it back. When I call passport.token I always get the same message:
array:3 [
"error" => "invalid_client"
"error_description" => "Client authentication failed"
"message" => "Client authentication failed"
]
I have tried several things, but here is my current code:
use Illuminate\Support\Str;
use Laravel\Passport\Client as OauthClient;
use Modules\Sapiendo\Tests\SapiendoTestCase;
/** #test */
public function we_can_authenticate_and_use_api_endpoints_with_client_credential_grant_token()
{
$customer = $this->createFullCustomer();
/** #var OauthClient $oauthClient */
$oauthClient = OauthClient::create([
'user_id' => null,
'name' => 'ClientCredentials Grant Client',
'secret' => Str::random(40),
'redirect' => 'http://localhost',
'personal_access_client' => false,
'password_client' => false,
'revoked' => false,
]);
$state = Str::random(40);
$autorization = $this->get(route('passport.authorizations.authorize', [
'client_id' => $oauthClient->id,
'redirect_uri' => 'http://localhost',
'response_type' => 'code',
'scope' => '',
'state' => $state,
]));
$autorization->assertStatus(302);
// D'abord on demande un token avec les identifiants créés
$tokenRequest = $this->post(route('passport.token'), [
'grant_type' => 'client_credentials',
'client_id' => $oauthClient->getKey(),
'client_secret' => $oauthClient->secret,
'code' => $state,
]);
//->assertSuccessful();
dd($tokenRequest->json());
...
Before this update I didn't have to go through the passport.authorizations.authorize route to get the code, I could go directly to the passport.token step
Since Passport 9.0, the client ID and secret are hashed. There is a function to retrieve this non-hashed secret from the Passport client object
$oauthClient = OauthClient::create([
'user_id' => null,
'name' => 'ClientCredentials Grant Client',
'secret' => Str::random(40),
'redirect' => 'http://localhost',
'personal_access_client' => false,
'password_client' => false,
'revoked' => false,
]);
$tokenRequest = $this->post(route('passport.token'), [
'grant_type' => 'client_credentials',
'client_id' => $oauthClient->id,
'client_secret' => $oauthClient->getPlainSecretAttribute(),
'code' => $state,
]);
Related
this is my get access token method
protected function getAccessToken($code)
{
$request = new \XLite\Core\HTTP\Request(static::TOKEN_REQUEST_URL);
$request->body = array(
'code' => $code,
'client_id' => $this->getClientId(),
'client_secret' => $this->getClientSecret(),
'redirect_uri' => $this->getRedirectUrl(),
'grant_type' => 'authorization_code',
);
$response = $request->sendRequest();
$accessToken = null;
if (200 == $response->code) {
$data = json_decode($response->body, true);
$accessToken = $data['access_token'];
}
return $accessToken;
}
and here i got the response in my logs:
[06:35:13.000000] array (
'request response from google' =>
(object) array(
'__CLASS__' => 'PEAR2\\HTTP\\Request\\Response',
'code' => 400,
'headers' =>
(object) array(
'__CLASS__' => 'PEAR2\\HTTP\\Request\\Headers',
'iterationStyle' => 'lowerCase',
'fields:protected' => 'Array(13)',
'camelCase:protected' => NULL,
'lowerCase:protected' => NULL,
),
'cookies' =>
array (
),
'body' => '{
"error": "invalid_grant",
"error_description": "Bad Request"
}',
'scheme' => 'https',
'host' => 'accounts.google.com',
'path' => '/o/oauth2/token',
'uri' => 'https://accounts.google.com/o/oauth2/token',
'port' => 443,
),
)
you can see the in response body if you required any thing else let me know
The post body is sent as a query string not an array
POST https://accounts.google.com/o/oauth2/token
code=AuthorizationCode&client_id=ClientId}&client_secret={ClientSecret}&redirect_uri=RedirectURI&grant_type=authorization_code
remember the code will expire in five minutes and can only be used once.
I beleave in php you should be using http-build-query for your post data.
I've installed Laravel Passport.
Here is how I generate auth code:
public function auth(Request $request)
{
$request->session()->put('state', $state = Str::random(40));
$request->session()->put(
'code_verifier', $code_verifier = Str::random(128)
);
$codeChallenge = strtr(rtrim(
base64_encode(hash('sha256', $code_verifier, true))
, '='), '+/', '-_');
$query = http_build_query([
'client_id' => '1',
'redirect_uri' => 'http://127.0.0.1:8000/authorize/response',
'response_type' => 'code',
'scope' => '',
'state' => $state,
'code_challenge' => $codeChallenge,
'code_challenge_method' => 'S256',
]);
return redirect('http://127.0.0.1:9000/oauth/authorize?'.$query);
}
Above request all passes well.
Here is how I try to generate access token:
public function authResponse(Request $request)
{
$state = $request->session()->pull('state');
throw_unless(
strlen($state) > 0 && $state === $request->state,
InvalidArgumentException::class
);
$response = Http::asForm()->post('http://127.0.0.1:9000/oauth/token', [
'grant_type' => 'authorization_code',
'client_id' => '1',
'client_secret' => 'hYMELQ1VKAWrG0TwrkM3JxUuoICSCWCzCztClZZi',
'redirect_uri' => 'http://127.0.0.1:8000/authorize/response',
'code' => $request->code,
]);
return $response->json();
}
When I execute the code for generating the access token I get the following error:
{"error":"invalid_client","error_description":"Client authentication
failed","message":"Client authentication failed"}
Any idea what can be the cause of this error? I've taken the client_secret from the DB.
Any idea what can be the problem and how can I fix it?
You are missing to pull from session the code_verifier on your authResponse() method.
$codeVerifier = $request->session()->pull('code_verifier');
Then add the $codeVerifier to the 'code_verifier' in post method when your are converting authorization codes to access tokens.
$response = Http::asForm()->post('http://127.0.0.1:9000/oauth/token', [
'grant_type' => 'authorization_code',
'client_id' => '1',
'client_secret' => 'hYMELQ1VKAWrG0TwrkM3JxUuoICSCWCzCztClZZi',
'redirect_uri' => 'http://127.0.0.1:8000/authorize/response',
'code' => $request->code,
]);
Check out the docs about this.
Here is my code:
use Aws\CognitoIdentityProvider\CognitoIdentityProviderClient;
$args = [
'credentials' => [
'key' => 'valid',
'secret' => 'valid',
],
'region' => 'us-west-2',
'version' => 'latest',
'app_client_id' => 'valid',
'app_client_secret' => 'valid',
'user_pool_id' => 'valid',
];
$email = 'test32#test.com';
$client = new CognitoIdentityProviderClient($args);
$hash_key = cognitoSecretHash($email);
$login = $client->adminInitiateAuth([
'AuthFlow' => 'ADMIN_NO_SRP_AUTH',
'AuthParameters' => [
'Username' => $email,
'Password' => '12345678',
'SecretHash' => $hash_key,
],
'ClientId' => 'valid',
'UserPoolId' => 'valid',
]);
return $login;
function cognitoSecretHash($username)
{
$message = $username . 'app_client_id';
$hash = hash_hmac(
'sha256',
$message,
'app_client_secret',
true
);
return base64_encode($hash);
}
Its give me this error:
Fatal error: Uncaught exception 'Aws\CognitoIdentityProvider\Exception\CognitoIdentityProviderException' with message 'Error executing "AdminInitiateAuth" on "https://cognito-idp.us-west-2.amazonaws.com"; AWS HTTP error: Client error: POST https://cognito-idp.us-west-2.amazonaws.com resulted in a 400 Bad Request response: {"__type":"ResourceNotFoundException","message":"User pool client {id} does not exist."} ResourceNotFoundException (client): User pool client {id} does not exist. - {"__type":"ResourceNotFoundException","message":"User pool client {id} does not exist."}' GuzzleHttp\Exception\ClientException: Client error: POST https://cognito-idp.us-west-2.amazonaws.com resulted in a 400 Bad Request response: {"__type":"ResourceNotFoundException","message":"User pool client {id} does not exist."} in D:\xampp\htdocs\test\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php:113 Stack trace: #0 D:\xampp\htdocs\test\vend in D:\xampp\htdocs\test\vendor\aws\aws-sdk-php\src\WrappedHttpHandler.php on line 195
$login = $client->adminInitiateAuth([
'AuthFlow' => 'ADMIN_NO_SRP_AUTH',
'AuthParameters' => [
'USERNAME' => $email,
'PASSWORD' => $password,
'SECRET_HASH' => $hash_key,
],
'ClientId' => $clientId,
'UserPoolId' => $poolId,
]);
I had this issue and just had to do an amplify pull - problem was out of sync project on different computers and git pull didn't cover the aws backend stuffs I think.
I am using guzzle 6.3 to post a file along with some data to my api built on laravel 5.5. When i post the data, i am not able to get the data sent to the api except the file posted.
Client Side
$client = new Client([
'headers' => [ 'Content-Type' => 'application/json' ]
]);
$response = $client->request('POST',$url, [
'multipart' => [
[
'name' => 'body',
'contents' => json_encode(['documentation' => 'First Doc', 'recipient' => ['78011951231']]),
'headers' => ['Content-Type' => 'application/json']
],
[
'name' => 'file',
'contents' => fopen('/path/public/media/aaaah.wav', 'r'),
'headers' => ['Content-Type' => 'audio/wav']
],
],
]);
echo($response->getBody()->getContents());
API Controller
if (($Key)) {
return response()->json([
'status' => 'success',
'documenation' => $request->get('documentation'),
'recipient' => $request->get('recipient'),
'file' =>$request->get('file'),
'media'=>$request->hasFile('file')
]);
}
Response
{"status":"error","documentation":null,,"recipient":null,"file":null,"media":true}
Why am i getting NULL returned for the data that i am posting? Could it be because of the file that i am posting ?
I successfully create server and client app both using laravel, I can access data from server app to client app also. But now I want to create another client app using codeigniter. Authorization works except for the callback method. So how can I convert the this code
Route::get('/callback', function (Request $request) {
$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
'redirect_uri' => 'http://example.com/callback',
'code' => $request->code,
],
]);
return json_decode((string) $response->getBody(), true);
});
into CodeIgniter 2?
Thanks
Anyways, I already fixed it.
adding "guzzlehttp/guzzle": "~6.0" in composer.json
running composer update
callback method code
$http = new \GuzzleHttp\Client;
$response = $http->post('http://localhost:8000/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => '3',
'client_secret' => 'client-secret-from-db',
'redirect_uri' => 'ci-client-app/callback',
'code' => $this->input->get('code', TRUE)
],
]);
echo '<pre>', print_r(json_decode((string) $response->getBody(), true));