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

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!

Related

Sales force refresh token could not generating in Laravel php

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)?

How to verify a token with Laravel Passport?

I want to validate a token using Laravel Passport. My API's consumer will pass the token via the Authorization header as a Bearer token and I want that Laravel Passport returns me if is a valid token.
I don't want to use a middleware, my API will be in another Laravel Project, but I want this project to call the Laravel Passport server just for check if a token is valid, how can I check the token?
I'm issuing the tokens right, just left verify them, but I don't know how:(
This is how you can verify tokens without the middleware:
Auth::guard('api')->check();
You can create your own middleware. Inside that middleware's handle, pick the Bearer token and call your Passport server, depending on the response returned call next if true, or abort if false. Something like this:
public function handle($request, Closure $next)
{
try {
$passportEndpoint = 'your_passport_endpoint_here';
$client = Http::withHeaders([
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => $request->header('Authorization')
]);
$response = $client->get($passportEndpoint);
if ($response->status() === 200) {
$body = $response->object();
//do some stuff with response here, like setting the global logged in user
return $next($request);
}
}
catch (RequestException $exception) {
}
return abort(401, 'You are not authenticated to this service');
}
If you don't want to use the Passport middleware in the project where you want to validate the tokens, you would have to create an endpoint in the Laravel Passport server that can accept the token, perform the usual Passport validation and return a response to your service.
It would be an implementation of the Token Introspection spec: https://www.rfc-editor.org/rfc/rfc7662 - though you have to implement it yourself, as I think that Laravel Passport doesn't support it out-of-the-box.
Also, when verifying JSON Web Tokens (if this is the type of tokens that you use), remember that verifying the signature is not enough. Have a look at this best practices article to know how to properly work with JWTs.

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

Can't get auth user with laravel passport, keep getting "Unauthenticated" error

I can't get the information of the authenticated user in a Laravel passport app with JWT and vue.
I've installed laravel passport. Ive done everything in the documentation and added:
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
To consume it with js for a SPA app.
I've protected my routes with the auth:api middleware, but i keep getting:
{"Status":{"api_status":0,"Code":401,"Message":"Unauthenticated"}}
When i use postman to manually insert the CSRF-TOKEN in Authorization Bearer Token. It does give me the auth user.
Whatever i do, i keep getting null on Auth::user(); in my controllers and routes
Laravel V5.7
Node V10.15.3
Npm V.6.9.0
You need to send a POST request (using Postman/Insomnia) with the details of the user you want to log in as to /oauth/token in your app which will respond with an API token. You save this api token locally, and then add add it as a Header variable to your guzzle/axios/whatever function's http calls (every one of them!) to your API.
$http = new GuzzleHttp\Client;
$data = 'Whatever';
$response = $http->request('POST','api/user',[
'data' => $data,
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer xxxxxxxxxxxxThis is the long authentication string returned from the Postman requestxxxxxxxxxxxxxx'
]
]);
dd(json_decode((string) $response->getBody())); // To view the response
From: https://laravel.com/docs/5.5/passport#creating-a-password-grant-client

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