How do I authenticate with JWT using gRPC for PHP? - php

I've generated my client code from proto files. Now I'm trying to connect but get the 'jwt' is not located at the context error from server. Here's what I do:
$myServiceClient = new MyServiceClient(
"$host:$port",
[
'credentials' => ChannelCredentials::createInsecure(),
'update_metadata' => function ($metaData) use ($token) {
// $metaData['authorization'] = ['jwt' . $token]; // doesn't work
// $metaData['authorization']['jwt'] = $token; // doesn't work
// $metaData['jwt'] = $token; // doesn't work
$metaData['authorization'] = ['Bearer ' . $token]; // doesn't work
return $metaData;
},
]
);
$unaryCall = $myServiceClient->MyMethod(new MyMethodRequest());
$wait = $unaryCall->wait();

Try this
$myServiceClient = new MyServiceClient(
"$host:$port",
[
'credentials' => ChannelCredentials::createInsecure(),
'update_metadata' => function ($metaData) use ($token) {
$metaData['Authorization'] = 'Bearer ' . $token;
return $metaData;
},
]
);
Best HTTP Authorization header type for JWT
Or like this:
https://jwt.io/introduction
Authorization: Bearer <token>

The following works for me:
$myServiceClient = new MyServiceClient(
"$host:$port",
[
'credentials' => ChannelCredentials::createInsecure(),
'update_metadata' => function ($metaData) use ($token) {
$metaData['jwt'] = [$token];
return $metaData;
},
]
);

Related

missing_charset for slack-api

I use Guzzle to send messages to the Slack API. It's all working fine except for the warning missing-charset. Here is my Guzzle function:
private function guzzleClient(string $method, string $url, array $parameters = [])
{
$client = new Client(['headers' => [
'Authorization' => "Bearer " . $this->slackOauthToken,
'Content-Type' => 'application/json; charset=utf-8',
]]);
switch (strtoupper($method)) {
case "POST":
$response = $client->post($url, [RequestOptions::JSON => $parameters]);
break;
case "GET":
$response = $client->get($url, ["query" => $parameters]);
break;
}
$json = json_decode($response->getBody()->getContents());
if((is_object($json)) && ($json->ok == false)) {
return "Error: " . $json->error . "\n";
} else {
return $json;
}
}
As far as I can determine, the charset is there and in the headers. But I keep still getting the missing-chaset error - where am I going wrong?

Trying to download mp3 file via API GET response using guzzle client in laravel

I've tried several methods to download an mp3 file via API get request. I feel like as if I'm close but just can't seem to get the download.
My URL returns a binary mp3 file.
This is a portion of what I'm getting in my response header array returning with the get request. Hope this is helpful.
"Content-Disposition" => array:1 [
0 => "attachment; filename=RE3e327a2615b93f528fee111da9b60e17.mp3; filename*=UTF-8''sample.mp3"
]
Here is a sample of my code using the Guzzle client in Laravel. Trying Laravel's download method but I believe I need to get the actual file from the Content-Disposition. Much appreciated for any help. Thanks.
$client = new Client();
try {
$url = 'http://getmp3website.net/recording/sample.mp3';
$response = $client->request('GET', $url,
[
'headers' => [
'Authorization' => 'bearer ' . env("AUTH_TOKEN"),
'Content-Type' => 'audio/mp3',
],
]);
return response()->download($response);
} catch (Exception $ex) {
return $ex;
}
#Note: this is not a tested answer, I have just provided an example to follow the comments above
<?php
$client = new Client();
try {
$url = 'http://getmp3website.net/recording/sample.mp3';
$resource = \GuzzleHttp\Psr7\Utils::tryFopen('/path/to/file', 'w');
//or you can use $myFile = fopen('/path/to/file', 'w') or die('not working');
$stream = \GuzzleHttp\Psr7\Utils::streamFor($resource);
$client->request('GET', $url , [
'save_to' => $stream,
'headers' => [
'Authorization' => 'bearer ' . env("AUTH_TOKEN"),
'Content-Type' => 'audio/mp3',
],
]
);
/**
* // As `save_to` is deprecated(guzzle wants us to download files as stream I guess), you can use sink as well, sink will automatically stream files for you
$resource = \GuzzleHttp\Psr7\Utils::tryFopen('/path/to/file', 'w');
$client->request('GET', $url, ['sink' => $resource]);
*/
return response()->download($pathsavedfile);
} catch(\GuzzleHttp\Exception\RequestException $e){
// you can catch here 400 response errors and 500 response errors
// You can either use logs here
$error['error'] = $e->getMessage();
$error['request'] = $e->getRequest();
if($e->hasResponse()){
if ($e->getResponse()->getStatusCode() == '400'){
$error['response'] = $e->getResponse();
}
}
Log::info('Error occurred in request.', ['error' => $error]);
}catch (Exception $ex) {
return $ex;
}

cURL -d switch: How to use it in a guzzle request

I'm learning to use an API. They provide an example of the following authentication code:
curl -X POST --header "Content-Type: application/json" --header "Accept: application/json" -d " {\"Username\": \"the_username\",
\"Password\": \"the_password\"}
" "https://someurl.someapi.com:443/api/Login/Authenticate"
However I need to reproduce this with a Guzzle request. Here is what I've been trying
$headers = [
"Content-Type" => "application/json",
"Accept" => 'application/json -d " {\"Username\": \"the_username\", \"Password\": \"the_password\" }" ',
];
// $headers = [
// "Content-Type" => "application/json"
// ];
$extra_data = ["proxy" => $proxy,
"headers" => $headers ];
// Defining the Guzzle Client to communicate with Legacy.com
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'https://someurl.someapi.com:443/api/Login/Authenticate',
// You can set any number of default request options.
'timeout' => 10.0,
]);
try {
$response = $client->request('POST', '', $extra_data);
}
However no matter what I try (this was the latest of my failed attempts), I can't get anything other than a code 400 error.
So I finally figured how to do this:
This code worked!
$str = json_decode('{ "Username": "' . $username . '", "Password": "' . $password . '"}',true);
var_dump($str);
if ($str == NULL) return;
$url_authenticate = "Login/Authenticate";
$extra_data = ["proxy" => $proxy,
"json" => $str ];
// Defining the Guzzle Client to communicate with Legacy.com
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'https://someurl.someapi.com:443/api/',
// You can set any number of default request options.
'timeout' => 10.0,
]);
try {
$response = $client->request('POST', $url_authenticate, $extra_data);
}
catch (Exception $e) {
echo 'Exception: ' . $e->getResponse()->getStatusCode() . "\n";
exit;
}
$body = $response->getBody();
echo $body;
The key was use the json field int the extra data and transform the json to php array using json_decode. I hope this helps someone else

How to properly configure Guzzle to download zip files from other servers

This function is meant to download .zip files
function download($url, $debug = false)
{
$client = new Client([
'connect_timeout' => 10,
'timeout' => 60.0,
'debug' => $debug
]);
$response = $client->request('GET', $url);
try {
if ($response->getStatusCode() == 200) {
return $response->getBody()->getContents();
}
} catch (RequestException $e) {
//var_dump($response->getBody()->getContents());
$txt = json_encode(['log_error' => $e->getResponse(), 'response' => $response->getBody()->getContents(), 'url' => $url]);
file_put_contents(storage_path() . '/logs-etiquetas/log-' . microtime(true) . '-' . auth()->user()->company_id . '.txt', $txt);
}
return false;
}
I'm getting error below
production_ERROR: Client error: GET https: //api.mercadolibre.com/shipment_labels? shipment_ids = 27868452659,27864682043,27168438675,27868264704,27868866716,27868738288,27867965828 & response_type = zpl2 & caller.id = 23264143 & access_token = 400 Bad Request response:
bad_request

Non supported claims in JWT implementation

I am implementing JWT in my application using php-jwt library from Firebase. I tried the example in the site and it is working fine.
$token = array(
"iss" => "http://example.org",
"aud" => "http://example.com",
"iat" => 1356999524,
"nbf" => 1357000000
);
However if I try to include other claims such as exp or sub, it throws UnexpectedValueException ('Wrong number of segments') exception. Has somebody encountered this issue ? Does the php-jwt library supports only the four claims shown in the example ? The code to receive the token in api is given below:
$headers = null;
if (isset($_SERVER['Authorization'])) {
$headers = trim($_SERVER["Authorization"]);
}
else if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
$headers = trim($_SERVER["HTTP_AUTHORIZATION"]);
} elseif (function_exists('apache_request_headers')) {
$requestHeaders = apache_request_headers();
$requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders));
//print_r($requestHeaders);
if (isset($requestHeaders['Authorization'])) {
$headers = trim($requestHeaders['Authorization']);
}
}
if (!empty($headers)) {
if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) {
$jwt = $matches[1];
}
}
$key = "example_key";
$decoded = JWT::decode($jwt, $key, array('HS256'));
$decoded_array = (array) $decoded;
If the token is generated using the example in the site, then it works fine. If the token is generated using claims like:
$tokenId = base64_encode(mcrypt_create_iv(32));
$issuedAt = time();
$notBefore = $issuedAt + 3;
$expire = $notBefore + 3600;
$token = array(
"iss" => "http://example.com",
"aud" => "http://example.com",
"iat" => $issuedAt,
"nbf" => $notBefore,
"exp" => $expire,
"gate" => "kanchanjuri",
"tokenId" => $tokenId
);
then the api call fails.
From app, the token is sent s follows:
HttpURLConnection con = null;
URL url = new URL(query);
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.addRequestProperty("Authorization", "Bearer " + token);
if (con.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ con.getResponseCode());
}
Thanks

Categories