I have some some problem...
I create an Microsoft Team WEBHOOK:
WEBHOOK Creation
WEBHOOK Secret
But teams dont send hmac hash authorization to my PHP Script header...
<?php
//The secret share with Microsoft Teams
$secret = "{MY TEAMS WEBHOOK SECRET}";
//get headers
$a = getallheaders();
$provided_hmac = substr($a['Authorization'],5);
//Get data from request
$data = file_get_contents('php://input');
//json decode into array
$json = json_decode($data, true);
//hashing
$hash = hash_hmac("sha256",$data,base64_decode($secret), true);
$calculated_hmac = base64_encode($hash);
//start log var
$log = "\n========".date("Y-m-d H:i:s")."========\n".$provided_hmac."\n".$calculated_hmac."\n";
try{
//compare hashs
if(hash_equals($provided_hmac,$calculated_hmac))
throw new Exception("No hash matching");
//response text
$txt="Hi {$json["from"]["name"]} welcome to your custom bot";
echo '{
"type": "message",
"text": "'.$txt.'"
}';
$log .= "Sended: {$txt}";
}catch (Exception $e){
$log .= $e->getMessage();
}
//write log
$fp = fopen("log.txt","a");
fwrite($fp, $log . PHP_EOL);
fclose($fp);
?>
Any one can help me with this ?
I try some methods but dont work.
Header dont have any part/string with authorization hash...
Thanks for help.
Related
I have a little problem, I have a php script for sending messages to viber. The problem is that bot sends message when I send some message with my profile, but I want only to run php script and send message to chat.
Check the script:
<?php
use Alserom\Viber\Request\Type\SendMessage;
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$access_token = "TOKEN HERE";
$request = file_get_contents("php://input");
$input = json_decode($request, true);
if ($input['event'] == 'webhook') {
$webhook_response['status'] = 0;
$webhook_response['status_message'] = "ok";
$webhook_response['event_tyes'] = "delivered";
echo json_encode($webhook_response);
die;
} else if ($input['event'] == 'message') {
$text_received = $input['message']['text'];
$sender_id = $input['sender']['id'];
$sender_name = $input['sender']['name'];
$message_to_replay = "hello";
$data['auth_token'] = $access_token;
$data['receiver'] = $sender_id;
$data['type'] = "text";
$data['text'] = $message_to_replay;
sendMessage($data);
} else {
$message_to_replay = "Messageeeeeee";
$data['auth_token'] = $access_token;
/* $data['receiver'] = $sender_id; */
$data['type'] = "text";
$data['text'] = $message_to_replay;
sendMessage($data);
}
function sendMessage($data) {
$url = "https://chatapi.viber.com/pa/send_message";
$jsonData = json_encode($data);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$result = curl_exec($ch);
return $result;
}
?>
When I run script through browser, it goes to ELSE and it should send message immediately... but I get this error:
{
"status": 999,
"status_message": "Bad receiver ID",
"message_token": 5485177081717755848,
"chat_hostname": "SN-CHAT-20_"
}
Should I put some static receiver ID? And how to get ID of some user?
*** UPDATE *****
I have added static ID of subscribed user in ELSE statement... now it sends immediately when I run script, but now it sends 100 same messages. How to limit sending only one message?
else {
$message_to_replay = "Messageeeeeee";
$data['auth_token'] = $access_token;
$data['receiver'] = "staticID";
$data['type'] = "text";
$data['text'] = $message_to_replay;
sendMessage($data);
}
According to the Viber documentation, you can only send messages to accounts subscribing to your bot:
The send_message API allows accounts to send messages to Viber users who subscribe to the account.
A requirement for the user id is, that it has to be a user id of a user who subscribed to the bot, so this should be your first step to check.
Edit: I would recommend saving the user ids of those who subscribed by sending an initial message or something to your bot and then you can send messages to them by taking the previously saved user ids.
If your script didn't responded in 5 seconds or responded with HTML status code not equal 200 - then Viber servers will try to resend this webhook every minute.
I am using Firebase/JWT with php. I am trying to read the token in "decoded" php file but it shows be Signature verification failed not sure why that is happening. This is how I am encoding the token
<?php
use \Firebase\JWT\JWT;
require 'vendor/autoload.php';
require('config/Database.php');
$db = new Database;
$key = "helloworld";
//$jwt = JWT::encode($token, $key, 'HS512');
$post = file_get_contents("php://input");
$postdata = json_decode($post);
if($postdata){
$email = $postdata->email;
$password = $postdata->password;
$query = "SELECT * FROM users WHERE email = :email";
$db->query($query);
$db->bind(":email", $email);
$rows = $db->resultset();
if(password_verify($password, $rows[0]["hash"])){
$rows[0]["Success"] = "Success";
$token = array(
"rows" => $rows
);
$jwt = JWT::encode($token, $key, 'HS256');
header("auth: " . $jwt);
echo json_encode($jwt, 128);
}else{
echo "Failed";
}
}
?>
Then I am decoding the token in this file
<?php
use \Firebase\JWT\JWT;
require 'vendor/autoload.php';
require('config/Database.php');
$db = new Database;
$key = "helloworld";
//$jwt = JWT::encode($token, $key, 'HS512');
$post = file_get_contents("php://input");
$postdata = json_decode($post);
if($postdata){
$userData = $postdata->userdata;
// check if token is same stored in the database then decode
$jwt = JWT::decode($userData, $key, array('HS256'));
echo $jwt;
}
?>
It fails, returning a "Signature verification failed" error.
Any help is appreciated. Thank you.
The problem why it wasn't verifying was because I was using json_encode on the jwt and that caused it to be wrapped around quotes again so the token looked something like this ""eY0lkajflajk...."" and that caused the verifying exception. Thank you #zerkms for bring that up.
There are a few libraries for implementing JSON Web Tokens (JWT) in PHP, such as php-jwt. I am writing my own, very small and simple class but cannot figure out why my signature fails validation here even though I've tried to stick to the standard. I've been trying for hours and I'm stuck. Please help!
My code is simple
//build the headers
$headers = ['alg'=>'HS256','typ'=>'JWT'];
$headers_encoded = base64url_encode(json_encode($headers));
//build the payload
$payload = ['sub'=>'1234567890','name'=>'John Doe', 'admin'=>true];
$payload_encoded = base64url_encode(json_encode($payload));
//build the signature
$key = 'secret';
$signature = hash_hmac('SHA256',"$headers_encoded.$payload_encoded",$key);
//build and return the token
$token = "$headers_encoded.$payload_encoded.$signature";
echo $token;
The base64url_encode function:
function base64url_encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
My headers and payload perfectly match the validation site's default JWT, but my signature doesn't match so my token is flagged as invalid. This standard seems really straightforward so what's wrong with my signature?
I solved it! I did not realize that the signature itself needs to be base64 encoded. In addition, I needed to set the last optional parameter of the hash_hmac function to $raw_output=true (see the docs. In short I needed to change my code from the original:
//build the signature
$key = 'secret';
$signature = hash_hmac('sha256',"$headers_encoded.$payload_encoded",$key);
//build and return the token
$token = "$headers_encoded.$payload_encoded.$signature";
To the corrected:
//build the signature
$key = 'secret';
$signature = hash_hmac('sha256',"$headers_encoded.$payload_encoded",$key,true);
$signature_encoded = base64url_encode($signature);
//build and return the token
$token = "$headers_encoded.$payload_encoded.$signature_encoded";
echo $token;
If you want to solve it using RS256 (instead of HS256 like OP) you can use it like this:
//build the headers
$headers = ['alg'=>'RS256','typ'=>'JWT'];
$headers_encoded = base64url_encode(json_encode($headers));
//build the payload
$payload = ['sub'=>'1234567890','name'=>'John Doe', 'admin'=>true];
$payload_encoded = base64url_encode(json_encode($payload));
//build the signature
$key = "-----BEGIN PRIVATE KEY----- ....";
openssl_sign("$headers_encoded.$payload_encoded", $signature, $key, 'sha256WithRSAEncryption');
$signature_encoded = base64url_encode($signature);
//build and return the token
$token = "$headers_encoded.$payload_encoded.$signature_encoded";
echo $token;
Took me way longer than I'd like to admit
https://github.com/gradus0/appleAuth
look method $appleAuthObj->get_jwt_token()
<?php
include_once "appleAuth.class.php";
// https://developer.apple.com/account/resources/identifiers/list/serviceId -- indificator value
$clientId = ""; // com.youdomen
// your developer account id -> https://developer.apple.com/account/#/membership/
$teamId = "";
// key value show in -> https://developer.apple.com/account/resources/authkeys/list
$key = "";
// your page url where this script
$redirect_uri = ""; // example: youdomen.com/appleAuth.class.php
// path your key file, download file this -> https://developer.apple.com/account/resources/authkeys/list
$keyPath =''; // example: ./AuthKey_key.p8
try{
$appleAuthObj = new \appleAuth\sign($clientId,$teamId,$key,$redirect_uri,$keyPath);
if(isset($_REQUEST['code'])){
$jwt_token = $appleAuthObj->get_jwt_token($_REQUEST['code']);
$response = $appleAuthObj->get_response($_REQUEST['code'],$jwt_token);
$result_token = $this->read_id_token($response['read_id_token']);
var_dump($response);
var_dump($result_token);
}else{
$state = bin2hex(random_bytes(5));
echo "<a href='".$appleAuthObj->get_url($state)."'>sign</a>";
}
} catch (\Exception $e) {
echo "error: ".$e->getMessage();
}
$oauth->getAccessToken() causes Invalid auth/bad request (got a 401, expected HTTP/1.1 20X or a redirect).
How do I look at the request headers to figure out what exactly is wrong?
$oauth = new OAuth(CONSUMER_KEY, CONSUMER_SECRET);
$oauth->disableSSLChecks();
$request_token_response = $oauth->getRequestToken('https://api.linkedin.com/uas/oauth/requestToken');
if($request_token_response === FALSE) {
throw new Exception("Failed fetching request token, response was: " . $oauth->getLastResponse());
} else {
$request_token = $request_token_response;
var_dump($request_token);
if (!isset($_GET['oauth_verifier'])) {
$this->redirect("https://api.linkedin.com/uas/oauth/authorize?oauth_token=" . $request_token['oauth_token']);
} else {
$oauth_verifier = $_GET['oauth_verifier'];
$oauth->setToken($request_token['oauth_token'], $request_token['oauth_token_secret']);
$access_token_url = 'https://api.linkedin.com/uas/oauth/accessToken';
$access_token_response = $oauth->getAccessToken($access_token_url, "", $oauth_verifier);
if($access_token_response === FALSE) {
throw new Exception("Failed fetching request token, response was: " . $oauth->getLastResponse());
} else {
$access_token = $access_token_response;
$params = array();
$headers = array();
$method = OAUTH_HTTP_METHOD_GET;
// Specify LinkedIn API endpoint to retrieve your own profile
$url = "http://api.linkedin.com/v1/people/~";
// By default, the LinkedIn API responses are in XML format. If you prefer JSON, simply specify the format in your call
// $url = "http://api.linkedin.com/v1/people/~?format=json";
// Make call to LinkedIn to retrieve your own profile
$oauth->fetch($url, $params, $method, $headers);
echo $oauth->getLastResponse();
}
}
}
}
oauth_verifier only verifies the request_token from which it was obtained. I needed to store the original request_token in session instead of getting a new request_token on callback.
I've followed the directions posted in this stackoverflow question, but I am stuck.
I am using tumblr/tumblr.php from Github (the official "PHP client for the tumblr API").
I am also following directions here (which are actually for twitter), but those directions aren't tailored for the git library I am using.
I have a valid consumer key and secret.
From those I make a request and get oauth_token and oauth_token_secret like so:
$client = new Tumblr\API\Client($consumerKey,$consumerSecret);
$client->getRequestHandler()->setBaseUrl('https://www.tumblr.com/');
$req = $client->getRequestHandler()->request('POST', 'oauth/request_token', [
'oauth_callback' => '...',
]);
// Get the result
$result = $req->body->__toString();
print_r( $result );
Which gives me:
oauth_token=2C6f...MqSF&oauth_token_secret=HaGh...IJLi&oauth_callback_confirmed=true
Then I send the user to the http://www.tumblr.com/oauth/authorize?oauth_token=2C6f...MqSF, so they can allow access for the app. This redirects to: ...?oauth_token=2C6f...MqSF&oauth_verifier=nvjl...GtEa#_=_
And now in the final step I believe I am supposed to convert my request token to an access token. Is that right? I am doing something wrong:
$client = new Tumblr\API\Client($consumerKey,$consumerSecret);
$client->getRequestHandler()->setBaseUrl('https://www.tumblr.com/');
$req = $client->getRequestHandler()->request('POST', 'oauth/access_token', [
'oauth_token' => '2C6f...MqSF',
'oauth_verifier' => 'nvjl...GtEa'
]);
// Get the result
$result = $req->body->__toString();
print_r( $result );
because I get responses like this one:
oauth_signature [AqbbYs0XSZ7plqB0V3UQ6O6SCVI=] does not match expected value [0XwhYMWswlRWgcr6WeA7/RrwrhA=]
What is wrong with my last step?
I am not sure if I should even be sending oauth_verifier with the request. Is #_=_ supposed to be part of oauth_verifier? I wouldn't think so. I get signature errors for all the variations Ive tried.
Without the token and tokenSecret I can't make certain calls to the API. I get unauthorized 403 responses. Same when I use the token and token_secret from the second step. I'm pretty sure I need a new token/secret pair.
You're pretty close, you just are passing the oauth_token incorrectly in the last step, and skipping out on oauth_token_secret altogeter.
I've compiled this working code (which you can also now find posted on the Wiki at https://github.com/tumblr/tumblr.php/wiki/Authentication):
<?php
require_once('vendor/autoload.php');
// some variables that will be pretttty useful
$consumerKey = '<your consumer key>';
$consumerSecret = 'your consumer secret>';
$client = new Tumblr\API\Client($consumerKey, $consumerSecret);
$requestHandler = $client->getRequestHandler();
$requestHandler->setBaseUrl('https://www.tumblr.com/');
// start the old gal up
$resp = $requestHandler->request('POST', 'oauth/request_token', array());
// get the oauth_token
$out = $result = $resp->body;
$data = array();
parse_str($out, $data);
// tell the user where to go
echo 'https://www.tumblr.com/oauth/authorize?oauth_token=' . $data['oauth_token'];
$client->setToken($data['oauth_token'], $data['oauth_token_secret']);
// get the verifier
echo "\noauth_verifier: ";
$handle = fopen('php://stdin', 'r');
$line = fgets($handle);
// exchange the verifier for the keys
$verifier = trim($line);
$resp = $requestHandler->request('POST', 'oauth/access_token', array('oauth_verifier' => $verifier));
$out = $result = $resp->body;
$data = array();
parse_str($out, $data);
// and print out our new keys
$token = $data['oauth_token'];
$secret = $data['oauth_token_secret'];
echo "\ntoken: " . $token . "\nsecret: " . $secret;
// and prove we're in the money
$client = new Tumblr\API\Client($consumerKey, $consumerSecret, $token, $secret);
$info = $client->getUserInfo();
echo "\ncongrats " . $info->user->name . "!\n";