Sales force refresh token could not generating in Laravel php - laravel

hope you all are doing well. I am stuck with an issue since couple of hours and could not be able to resolve it. Please have a look on error
enter image description here
I am trying to generate refresh token. Access_token generated successfully that is expired after 20 minutes. refresh token could not be generated
$client = new Client();
$res = $client
->request("POST",
"https://test.salesforce.com/services/oauth2/token",[
'body'=> json_encode([
'grant_type'=>'refresh_token',
'client_id'=>Config::get('forrest.info.client_id'),
'client_secret'=>Config::get('forrest.info.client_secret'),
'Authorization'=>'Bearer 00D3H0000008olE!ARYAQOzGGJDDIaygn7GokNk4T319XlDwwBXIDYPkJfej74dfhFT3CMDvBD2pZBQK_x.v2amiRe5Y29ZNXMp9EOA6ZTYyqrTW',
'access_token'=>'00D3H0000008olE!ARYAQOzGGJDDIaygn7GokNk4T319XlDwwBXIDYPkJfej74dfhFT3CMDvBD2pZBQK_x.v2amiRe5Y29ZNXMp9EOA6ZTYyqrTW',
])
]
);
dd ($res->getStatusCode());
any help or comment would be highly appreciated! thank for your time.

It seems like this error is returned from SalesForce API.
Looking at their documentation, it seems that they expect to see application/x-www-form-urlencoded not json.
Try out this code:
$client = new Client();
$response = $client->request('POST', '/post', [
'form_params' => [
'grant_type' => 'refresh_token',
'client_id' => Config::get('forrest.info.client_id'),
'client_secret' => Config::get('forrest.info.client_secret'),
'Authorization' => 'Bearer 00D3H0000008olE!ARYAQOzGGJDDIaygn7GokNk4T319XlDwwBXIDYPkJfej74dfhFT3CMDvBD2pZBQK_x.v2amiRe5Y29ZNXMp9EOA6ZTYyqrTW',
'access_token' => '00D3H0000008olE!ARYAQOzGGJDDIaygn7GokNk4T319XlDwwBXIDYPkJfej74dfhFT3CMDvBD2pZBQK_x.v2amiRe5Y29ZNXMp9EOA6ZTYyqrTW',
],
]);
dd($response);
let me know if it helped.

(Not an answer but too long for a comment)
This looks weird. "Authorization Bearer" should be a http header, not part of the message's body. Are you able to do what you need in plain old Postman, SoapUI etc?
Which OAuth2 flow did you use to generate this access token? Not all flows generate refresh token, for example https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_username_password_flow.htm&type=5 says "this flow doesn't support scopes" so you get full access - but also "this response doesn’t send a refresh token."
Have you checked the connected app (place in SF where you took client id and secret from), do the OAuth2 scopes include refresh? Did you ask for refresh token (included it in the original request's grants)?

Related

Make a post request to a api that uses sanctum via Client (Laravel-6.2)

I have 5 applications that use the same sanctum API for authentication. What I really want to do is to make a POST request sanctum API from another application. I do GET requests like the below and it's working. But when I make a POST request it returns csrf token mismatch error.
So could someone please tell me is it possible to make a post request into a sanctum API via Client?
$response = $client->get('http://localhost:8000/api/user', [
'headers' => [
'accept' => 'application/json',
'cookie' => $request->header('cookie'),
'referer' => $request->header('referer'),
]
]);
Thanks
i use Bearer instead of cookie ,
in sanctum laravel reads access tokens from Authorization in header.
this is how i make request from laravel client to sanctum (an example of my code):
$response = Http::withHeaders([
"Accept"=> "application/json",
"Authorization" => "Bearer " . Cookie::get("Laravel")
])
->post("http://localhost:8088/api/v1/url/find", ["find" => $request->find]);
i send my headers with method withHeaders as an associative array
and send my post body with post method second argument.
read more here : https://laravel.com/docs/9.x/http-client
You're missing some headers on your requests. You need to first make a request to "/sanctum/csrf-cookie", what gives you a CSRF token. Then you pass that token as the value for the header "X-CSRF-TOKEN". Sanctum documentation explains it very well. https://laravel.com/docs/8.x/sanctum#spa-authenticating
Wish you luck!

Laravel HTTP Client Bad Request on Discord API Access Token Exchange

I have a laravel application setup and I'm configuring a Discord auth system.
I have sent & requested authorization & recieved a confirmation code back.
When I try to exchange the code for an access token I'm receiving a 400 bad request and I'm not sure why.
I'm new to laravel and can't seem to find any sort of error that may help to pin point the problem.
Controller function that discord redirects after authorization
public function exchange(Request $request) {
//exchange discord code for access_token
$code = Request::get('code',false);
$params = array(
'grant_type' => 'authorization_code',
'client_id' => env('CLIENT_ID'),
'client_secret' => env('OAUTH2_CLIENT_SECRET'),
'redirect_uri' => Request::root().'/discord/return',
'scope' => 'identify guilds guilds.join',
'code' => $code
);
$access_token = Http::withOptions([
'debug' => true,
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded'
],
'json' => $params
])->post('https://discordapp.com/api/oauth2/token');
dd($access_token);
return redirect()->route('return.discord',['token' => $access_token->access_token]);
}
I've dumped out $params and all the data is pulling in as it should.
Guzzle dumps this:
[CONNECT] [FAILURE] severity: "2" message: "HTTP/1.1 400 Bad Request " message_code: "400" [MIME_TYPE_IS] message: "application/json" [FILE_SIZE_IS] message: "Content-Length: 26" bytes_max: "26" [PROGRESS] bytes_max: "26"
I know that 400 bad request means an issue with the data being sent along, but I can't figure out what I'm doing that's not producing the correct result. The documentation states the required content type which I have set, so I'm really scratching my head here.
Any help would be much appreciated.
Here's the Discord API documentation:
https://discord.com/developers/docs/topics/oauth2#authorization-code-grant
To anyone looking for an answer...
The "invalid grant" error is due to an issue with the Discord API and non-standard requests. I could not get the Laravel HTTP class request to work for exchanging the access token. Instead, I used native php cURL within Laravel.
As for the issue with receiving '400 bad request', that was due to using incorrect function withOptions() as oppossed to asJson()->withHeaders(). Thanks #Zachary Craig!
However, I could not use this in the end due to the problem described above.
If any others find a better solution, let me know :)!
For all who have the same problem.
The solution is to use ->asForm() before the post. This changes the handling of the data from json to form_params. This way the Discord API accepts the parameters.
return Http::asForm()->post($this->endpoint.'/oauth2/token', $data);

Invalid token errors when trying to tweet

I'm using the ThuJohn Twitter package for Laravel and am trying to post tweets as a site user, but keep getting [89] Invalid or expired token. errors.
I know the package is installed correctly because I can send tweets using the website's app credentials; it's when I'm trying to tweet as a site user I run into problems.
I'm using the reconfig method, yet am still encountering issues. I'm wondering if my user credentials are wrong?
Here's the reconfig method:
Twitter::reconfig([
'consumer_key' => env('TWITTER_CONSUMER_KEY'),
'consumer_secret' => env('TWITTER_CONSUMER_SECRET'),
'token' => $user->twitter->token,
'secret' => $user->twitter->secret
]);
And this is how I'm grabbing the user's token and secret inside the callback method. Is this the correct way?
$request_token = [
'token' => Session::get('oauth_request_token'),
'secret' => Session::get('oauth_request_token_secret'),
];

JWT Token Refresh

Hello I am using JWT for authentication in my laravel 5 application. The application currently resides on a live server and has several APIs that other apps can connect to.
Currently I am building a mobile app that connects to some of these APIs, as you know with mobile apps when the user logs in once I want them to remain logged in for a very long time.
To do this I found out that I need to refresh the JWT when it's a expired, apparently this will generate a new token and blacklist the old one.
I use that latest version of Tymon/JWT which includes a new
blacklist_grace_period feature. This allows me to set a delay for when the token is refreshed and the old one is blacklisted.
My question now is, having the following in my route file:
Route::group(['domain' => 'admin.website'.(App::environment('production') ? '.com' : '.dev'), 'prefix' => '/api/v1/manager/', 'namespace' => 'App\Http\BackEnd\Controllers', 'middleware' => ['before' => 'jwt.auth', 'after' => 'jwt.refresh', 'acl'], 'is' => 'manager'], function() {
/** Manager Resource Routes */
Route::resource('events', 'EventManagerController');
});
How do I then get the newly generated token and return to the client after a jwt.refresh? Or is that automatically appended to the response of the request?
Take a look at the after-middleware that you are using:
vendor/tymon/jwt-auth/src/Middleware/RefreshToken.php
First it parses the token, then refreshes it:
try {
$newToken = $this->auth->setRequest($request)->parseToken()->refresh();
}
Then it adds it to the response's header:
$response->headers->set('Authorization', 'Bearer '.$newToken);
return $response;
So, yes, this is indeed where the newly refreshed token is added to the response.

mailchimp 3.0 authentication fails

Authentication fails for the following, which gets posted to mailchimp using CURL, where API_KEY is defined as a string containing my key. Similar code used to work just fine for mailchimp v2:
$params = array ('apikey' => API_KEY,
'email_address' => $email,
'status' => 'pending',
'merge_fields' => array ('fname' => $first_name,
'lname' => $last_name
)
);
The error is:
{"type":"http://kb.mailchimp.com/api/error-docs/401-api-key-missing",
"title":"API Key Missing",
"status":401,"detail":
"Your request did not include an API key.",
"instance":"(long number)"
}
That's not how authentication works in v3.0. From the documentation:
The easiest way to authenticate is using HTTP Basic Auth. Enter any string as the username and supply your API Key as the password. Your HTTP client library should have built-in support for basic authorization.
If you're using PHP, every HTTP library knows how to do this. I'd recommend Guzzle or PHP Requests, but even basic cURL in PHP can do basic auth easily.
The interests syntax looks okay, except that the value should be a boolean instead of a string.

Resources