AWS Cognito, authorization code request issue - php

I'm redirecting my user to Cognito hosted UI, then returning to my PHP application. If the code is found then I use Guzzle to exchange this with the access tokens, however I keep on receiving the following error:
{"error":"unauthorized_client"}
This is my code, I have double checked what i'm passing in with the documentation and it all looks fine to me!
if ($code = request()->input('code')) {
$client = new Client();
$confirmCodeDomain = "https://$domain/oauth2/token";
try {
$result = $client->post($confirmCodeDomain, [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => $client_id,
'code' => $code,
'redirect_uri' => 'https://localhost/auth/',
],
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
'Authorization' => 'Basic '.base64_encode("$client_id:$client_secret")
]
]);
} catch (\Exception $e) {
dd($e);
}
dd($result);
}
This is my serverless file which creates the AWS resources required, the error states:
unauthorized_client
Client is not allowed for code grant flow or for refreshing tokens.
However as you can see from my client definition the AllowedOAuthFlows is set to code:
resources:
Resources:
CognitoEmployeePool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: employees
MfaConfiguration: OFF
AdminCreateUserConfig:
AllowAdminCreateUserOnly: true
Policies:
PasswordPolicy:
MinimumLength: 7
RequireLowercase: true
RequireUppercase: true
RequireNumbers: false
RequireSymbols: false
EmailConfiguration:
EmailSendingAccount: "COGNITO_DEFAULT"
UsernameAttributes:
- email
AutoVerifiedAttributes:
- email
CognitoEmployeePoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: employees-webplanner
CallbackURLs:
- "https://localhost"
- "https://localhost/auth"
AllowedOAuthFlowsUserPoolClient: true
SupportedIdentityProviders:
- "COGNITO"
AllowedOAuthFlows:
- "code"
AllowedOAuthScopes:
- "openid"
- "email"
UserPoolId:
Ref: CognitoEmployeePool
ExplicitAuthFlows:
- ALLOW_ADMIN_USER_PASSWORD_AUTH
- ALLOW_REFRESH_TOKEN_AUTH
- ALLOW_USER_PASSWORD_AUTH
GenerateSecret: true
CognitoEmployeePoolDomain:
Type: AWS::Cognito::UserPoolDomain
Properties:
UserPoolId: !Ref CognitoEmployeePool
Domain: "marvs-sso"

Related

Guzzle oauth2 authentification issue

I am trying to connect to an oauth2 system using guzzle but I keep getting this message:
$guzzle = new GuzzleHttp\Client;
$response = $guzzle->post('https://logincert.anaf.ro/anaf-oauth2/v1/authorize', [
'form_params' => [
'grant_type' => 'authorization_code',
'response_type' => 'token',
'client_id' => 'xxxx',
'client_secret' => 'xxxxx',
'redirect_uri' => 'http://redirect'
],
]);
return json_decode((string) $response->getBody(), true)['access_token'];
{
"error":"invalid_client",
"error_description":"The client app does not support implicit grant"
}
The provider doesn't provide much information about the returned message, the only information that they provide are:
Type: OAuth 2.0
Add Authorization Data to: Request Headers
Grant Type: Authorization Code
Callback URL: http://redirect
Authorization Endpoint: https://logincert.anaf.ro/anaf-oauth2/v1/authorize
Token Endpoint: https://logincert.anaf.ro/anaf-oauth2/v1/token
Token Revocation Endpoint: https://logincert.anaf.ro/anaf-oauth2/v1/revoke
Client ID: xxx
Client Secret: xxx
Client Authentication type: Send as Basic Auth header
Any ideas what am I doing wrong?
Thanks,
Chris

Hybridauth 3 - Google Provider - Invalid Credentials

Hy. I have a problem with provider Google with HybridAuth 3.8.0. I have two php pages.
Page Sign-In.php
try
{
$config= [
'callback' => 'https://xxxxxxxxxx/gcallback',
'keys' => [
'id' => 'xxxxxxxxxxapps.googleusercontent.com',
'secret' => 'secret'
],
'scope' => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile',
'authorize_url_parameters' => [
'approval_prompt' => 'force',
'access_type' => 'offline'
],
];
$adapter = new \Hybridauth\Provider\Google($config);
$adapter->authenticate(); // Redirect to Google
}
catch(Exception $e)
{
die($e->getMessage);
}
Page gcallback.php
try
{
$adapter = new \Hybridauth\Provider\Google($config);
// This line is commented because redirect loop to Google
//$adapter->authenticate();
$userdata= $adapter->getUserProfile();
die(var_dump($userdata));
}
catch(Exception $e)
{
die($e->getMessage());
}
After User Login successfully, callback page show this error:
ERROR: Signed API request to https://www.googleapis.com/oauth2/v3/userinfo has returned an error. HTTP error 401. Raw Provider API response: {"error": "invalid_request", "error_description": "invalid Credentials"}
How can I fix it? In my Google Cloud Platform, my project is in testing mode (oauth consent screen). I have created two test email users.

GuzzleHTTP returns 404 on existing page

My Guzzle POST request to https://api.scarif.dev/auth gives back a 404, while the page exists through Postman, or browser, or javascript. It should return a 200 with a 401 message, but Guzzle gives back a 404. In both POST and GET mode that is.
I've tried multiple Client setups, including different headers and disabling SSL verification, but without any success. Now I've copied the exact same headers that made it work in postman, but still no success.
I've been searching through google and stackoverflow, but couldn't find an answer that fixed my problem.
Request in PHP:
<?php
$client = new Client([
'header' => [
'Accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded'
],
'verify' => false
]);
$response = $client->request('POST', 'https://api.scarif.dev/auth', [
'form_params' => []
]);
echo $response->getBody()->getContents();
?>
Expected result:
{
"detail": "https://login.scarif.dev",
"status": 401,
"title": "Unauthorized",
"type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"
}
Actual result:
Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client
error: POST https://api.scarif.dev/auth resulted in a 404 Not
Found response:
404 Not Found Not Found
(truncated...) in
/home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113
Stack trace: #0
/home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/guzzle/src/Middleware.php(66):
GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request),
Object(GuzzleHttp\Psr7\Response)) #1
/home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/promises/src/Promise.php(203):
GuzzleHttp\Middleware::GuzzleHttp{closure}(Object(GuzzleHttp\Psr7\Response))
2 /home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/promises/src/Promise.php(156):
GuzzleHttp\Promise\Promise::callHandler(1,
Object(GuzzleHttp\Psr7\Response), Array) #3
/home/admin/domains/login.scarif.dev/framework/ven in
/home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php
on line 113
API endpoint controller:
<?php
namespace Controller;
use Core\Config;
use Core\Request;
use Core\Response;
use Model\Token;
use Model\User;
use MongoDB\BSON\UTCDateTime;
class AuthController extends Controller
{
public function view(User $user, Token $token)
{
extract(Request::getPostData());
if (isset($access_token) && !empty($access_token)) {
$_token = $token->getTokenByToken($access_token);
if (
$_token['type'] !== Token::TYPE_ACCESS_TOKEN ||
$_token['expires_on'] <= new UTCDateTime()
) {
return $this->view->display('json', [
'payload' => Response::apiResponse(
$this->config->get('url.login'), 401
)
]);
}
$token->delete($_token['_id']);
$newToken = $token->create(Token::TYPE_ACCESS_TOKEN, $_token['user_id']);
return $this->view->display('json', [
'payload' => Response::apiResponse($newToken['token'])
]);
}
if (!isset($email) || !isset($password) || empty($email) || empty($password)) {
return $this->view->display('json', [
'payload' => Response::apiResponse(
$this->config->get('url.login'), 401
)
]);
}
if (!$user->checkCredentials($email, $password)) {
return $this->view->display('json', [
'payload' => Response::apiResponse(
"The email address or password you've entered is invalid. Please check your entry and try again.",
422
)
]);
}
$user = $user->getUserByEmail($email);
$token = $token->create(Token::TYPE_ACCESS_TOKEN, $user['_id']);
return $this->view->display('json', [
'payload' => Response::apiResponse($token['token'])
]);
}
}
It seems like the issue is coming from the API you are consuming. When using your code with a different url it works just fine:
$client = new Client([
'header' => [
'Accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded'
],
'verify' => false
]);
$response = $client->request('POST', 'https://jsonplaceholder.typicode.com/posts', [
'form_params' => []
]);
echo $response->getBody()->getContents();
Could you show the code for the API endpoints?
I had the same issue and was looking for solutions until I landed here. Didn't get any help online though and solutions of other people didn't work for me but later I solved myself through extensive debugging and I am sharing the solution in a hope it might help someone else in the future.
Scenario: In my case I had an API gateway and client (Postman in my case) was making request to the API gateway and gateway in turn was making request to a microservice using Guzzle 7 in Laravel 8. I used to pass all headers I received from the client to microservice as is and that was causing 404 error. When I changed that and passed only my own headers in the request to the microservice, there was light and 404 was gone.
These were default headers of Postman and I was passing in the request as is:
{
"authorization": [
"Bearer eyJ0eXAiOiJKV1 .."
],
"user-agent": [
"PostmanRuntime/7.29.0"
],
"accept": [
"*/*"
],
"postman-token": [
"ca180f3a-ec65-4212-bd9f-dc294846dc65"
],
"host": [
"sagateway.com"
],
"accept-encoding": [
"gzip, deflate, br"
],
"connection": [
"keep-alive"
]
}
I removed all of it and only passed one thing in the header:
['Authorization' => "<Key Here>"]
It then worked fine and I took a breath of relief after a few days of continuous googling.

Guzzle HTTP Client and Shopify access token exception

I'm getting Client error: POST https://testing-shop.myshopify.com/admin/oauth/access_token resulted in a 400 Bad Requestwhile trying to exchange temporary code for access token in Shopify. I'm using the latest version of Guzzle HTTP client and in Chrome, Windows 8.1. What's even more weird is that it worked before.
$client = new Client();
try{
$response = $client->request(
'POST',
"https://{$store}/admin/oauth/access_token",
[
'form_params' => [
'client_id' => $api_key,
'client_secret' => $secret_key,
'code' => $query['code']
]
]
);
}catch(Exception $e){
var_dump($e);
}
I also checked all my variables ($api_key, $secret_key)... and they're good which means they have values. What could be the problem here that I missed? TIA
EDIT:
It turned out to be the problem when registering the web hook .
$response = $client->request(
'POST',
"https://{$store}/admin/webhooks.json",
[
'webhook' => [
'topic' => 'app/uninstalled',
'address' => 'http://example.com/shopify/uninstall',
'format' => 'json'
]
]
);
This code causes the error but I'm not though why.
Think I've got it. And it fits with having worked then stopped working:
After July 1st 2018, apps will be required to use HTTPS webhook addresses.
See: https://help.shopify.com/en/api/getting-started/webhooks

Setting post data with a Laravel request object

I'm trying to test a Laravel API endpoint and want to call it in code.
$request = Request::create( $path, $method );
$response = Route::dispatch( $request );
This snippet works fine for GET but I need to be able to set up POST calls too. Setting the $method to POST works as well, but I can't find documentation detailing how to attach post data.
Any advice?
As you mentioned in the comments, you could use $this->call() but you can actually do it with your current code too. If you take a look at the signature of the Request::create() function you can see that it takes $parameters as third argument:
public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null)
And the docblock says: The query (GET) or request (POST) parameters
So you can simply add the data to Request::create()
$data = array('foo' => 'bar');
$request = Request::create( $path, $method, $data );
$response = Route::dispatch( $request );
I've spent nearly a day trying to get this working myself for social authentication with passport and Angular front-end.
When I use the Restlet API Client to make the request I always get a successful response.
Restlet Client Request
Restlet client response
However using the following method of making internal requests always gave me an error.
$request = Request::create(
'/oauth/token',
'POST',
[
'grant_type' => 'social',
'client_id' => 'your_oauth_client_id',
'client_secret' => 'your_oauth_client_secret',
'provider' => 'social_auth_provider', // e.g facebook, google
'access_token' => 'access_token', // access token issued by specified provider
]
);
$response = Route::dispatch($request);
$content = json_decode($response->getContent(), true);
if (! $response->isSuccessful()) {
return response()->json($content, 401);
}
return response()->json([
'content' => $content,
'access_token' => $content['access_token'],
'refresh_token' => $content['refresh_token'],
'token_type' => $content['token_type'],
'expires_at' => Carbon::parse(
$content['expires_in']
)->toDateTimeString()
]);
This specific error:
{
error: "unsupported_grant_type",
error_description: "The authorization grant type is not supported by the
authorization server.",
hint: "Check that all required parameters have been provided",
message: "The authorization grant type is not supported by the authorization server."
}
I had the feeling it has to do with the way the form data is sent in the request, so while searching for a proper way to make such internal requests in laravel I came across this sample project with a working implementation: passport-social-grant-example.
In summary here's how to do it:
$proxy = Request::create(
'/oauth/token',
'POST',
[
'grant_type' => 'social',
'client_id' => 'your_oauth_client_id',
'client_secret' => 'your_oauth_client_secret',
'provider' => 'social_auth_provider', // e.g facebook, google
'access_token' => 'access_token', // access token issued by specified provider
]
);
return app()->handle($proxy);
Hope this helps.

Categories