I'm trying to use a JWT authentication with Firebase, but I got always this error: "Fatal error: Uncaught Firebase\JWT\SignatureInvalidException: Signature verification failed".
The code is this:
$key = "test";
$tokenId = base64_encode(mcrypt_create_iv(32));
$issuedAt = time();
$notBefore = $issuedAt + 10;
$expire = $notBefore + 60;
$serverName = $_SERVER["SERVER_NAME"];
$data = [
'iat' => $issuedAt,
'jti' => $tokenId,
'iss' => $serverName,
'nbf' => $notBefore,
'exp' => $expire,
"userId" => 1
];
$secretKey = base64_decode($key);
$jwt = \Firebase\JWT\JWT::encode($data, $secretKey, 'HS256');
// and when I decode the tokens, I got that exception
$decoded = \Firebase\JWT\JWT::decode($jwt, $key, array('HS256'));
What I wrong?
You don't need $secretKey or base64_decode the key for that matter, just do:
$jwt = \Firebase\JWT\JWT::encode($data, $key, 'HS256');
$decoded = \Firebase\JWT\JWT::decode($jwt, $key, array('HS256'));
Related
I'm new using jwts and I want to return a query,
how could i do it?
With this code I generate the token with the header, payload etc..
Help would be greatly appreciated
// php code //
$secret = "examamplesecrett";
function CreateToken($secret){
$header = json_encode(
[
"type"=> "JWT","alg" => "HS256"
]
);
// creas el payload
$payload = json_encode(
[
'idUsuarioexample' => '100',
'iat' => time(),
'exp' => time() + 1800,
]
);
$headerbase64 = str_replace('*','',strtr(base64_encode($header),'*/','-_'));
$payloadbase64 = str_replace('*','',strtr(base64_encode($payload),'*/','-_'));
$signature = hash_hmac('sha256',$headerbase64.'.'.$payloadbase64,$secret,true);
$base64signature = str_replace('*','',strtr(base64_encode($signature),'+/','-_'));
$jwt = $headerbase64.".".$payloadbase64.".".$base64signature;
return $jwt;
}
$token = CreateTokenToken($secret);
echo $token ;
can someone assist where i am doing mistake
generate vapid keys and store them
use push-api and store endpoint, p256dh and auth
send push notification using webPush protocol
but getting this at 3rd stage
Warning: openssl_sign(): Supplied key param cannot be coerced into a private key
code from 1 to 3 please go through
generate VAPID keys in php on server side and store them
// Generate VAPID keys
$private_key = openssl_pkey_new([
'private_key_type' => OPENSSL_KEYTYPE_EC,
'curve_name' => 'prime256v1',
]);
$details = openssl_pkey_get_details($private_key);
$private_key_raw = $details['ec']['d'];
$public_key_raw = $details['ec']['x'] . $details['ec']['y'];
$auth_token = base64_encode(openssl_random_pseudo_bytes(16));
$vapid = [
'private_key' => rtrim(strtr(base64_encode($private_key_raw), '+/', '-_'), '='),
'public_key' => rtrim(strtr(base64_encode($public_key_raw), '+/', '-_'), '='),
'auth_token' => $auth_token,
];
echo json_encode($vapid);
generate applicationServerKey using public key
$publicKey = 'SzRJTTxfRvvoIfYJye-Oj-xJ-eDxHjIBhPLxILieNbZ86KjRE_EIvdjdKDmUH9RLwgmkITs-v_z_6J44aP1TtA';
// Base64-decode the public key
$public_key_bytes = base64_decode($publicKey);
// Check that the public key has the correct format
if (strlen($public_key_bytes) != 65 || ord($public_key_bytes[0]) != 4) {
// The public key has an incorrect format
// Handle the error here
}
// Extract the x and y coordinates of the point
$x = substr($public_key_bytes, 1, 32);
$y = substr($public_key_bytes, 33, 32);
// Pack the bytes of the public key in the correct order
$application_server_key = "\x04" . $x . $y;
echo base64_encode($application_server_key);
use the base64 applicationServerKey on client side
let b64ASK = 'BDRJTTxfRvvoIfYJyeOjxJeDxHjIBhPLxILieNbZ86KjREEIvdjdKDmUH9RLwgmkITsvz6J44aP1TtAauthtokc=';
let asKey = encodeToUint8Array(b64ASK);
pushManager.subscribe({applicationServerKey:asKey,userVisibleOnly:true})
.then(subscription=>{console.log(subscription.toJSON())})
store endpoint,p256dh,auth and send push notification using vapid keys on server side
send-notification.php
$publicKey = 'SzRJTTxfRvvoIfYJye-Oj-xJ-eDxHjIBhPLxILieNbZ86KjRE_EIvdjdKDmUH9RLwgmkITs-v_z_6J44aP1TtA';
$privateKey = '-----BEGIN EC PRIVATE KEY-----
Lnp9eUjWE7o8oqneZPzOW8nbz7hTVosE25sJm47Arrg=
-----END EC PRIVATE KEY-----';
$endpoint = "https://fcm.googleapis.com/fcm/send/cI0XqQ4quFM:APA91bExZFUuSZ9lgTDJQqmrHJpV-w5pIVnvaiODI9WIeER-K0Vg0U5P8wfTslRF5KdTlCmF9_Tp7bpAohKLxLvQCuS2Cy6ZG2BpVKO4f0wLWrfU-mGD6GCMCVUYLna3uwDLR6NqZxNi";
$auth = "X6syP0cUxjDjMAcUunH3FA";
$p256dh = "BIUuCWdoJykH6u3vERcfZe8gxEx1ajaFTPGnM4cWdYv-Hp-qRgt5GShAtbFYRr5my8hH66uIJEiHf22XW_i_Bps";
// Set the payload for the notification
$payload = [
'title' => 'push-message-test',
'body' => 'This is a test notification using VAPID.',
'icon' => 'assets/icons/favicon-32x32.png',
];
// Encode the payload as a JSON string
$payloadJson = json_encode($payload);
// Generate the JWT header
$header = [
'alg' => 'ES256',
'typ' => 'JWT',
];
$headerJson = json_encode($header);
$headerBase64Url = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($headerJson));
// Generate the JWT claim
$now = time();
$exp = $now + (12 * 60 * 60); // 12 hours in the future
$claim = [
'aud' => $endpoint,
'exp' => $exp,
'sub' => 'https://example.com',
];
$claimJson = json_encode($claim);
$claimBase64Url = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claimJson));
// Generate the JWT signature
$signingString = $headerBase64Url . '.' . $claimBase64Url;
$signature = '';
$privateKeyResource = openssl_pkey_get_private($privateKey);
openssl_sign($signingString, $signature, $privateKeyResource, 'sha256');
// Encode the signature as base64url
$signatureBase64Url = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
// Combine the JWT components into a string
$jwt = $headerBase64Url . '.' . $claimBase64Url . '.' . $signatureBase64Url;
// Send the notification using the Web Push protocol
$headers = [
'Authorization: Bearer ' . $jwt,
'Crypto-Key: p256ecdsa=' . $publicKey,
'Content-Length: ' . strlen($payloadJson),
'Content-Type: application/json',
];
$data = [
'endpoint' => $endpoint,
'publicKey' => $p256dh,
'authToken' => $auth,
'payload' => $payloadJson,
];
$options = [
'http' => [
'header' => implode("\r\n", $headers),
'method' => 'POST',
'content' => json_encode($data),
],
];
$context = stream_context_create($options);
$result = file_get_contents($endpoint, false, $context);
// Handle the response
if ($result === false) {
// Error handling
echo 'failed to send push';
} else {
// Success handling
echo 'succesfully sent push using push protocol';
}
I am writing a webhook in bref and want it to send a message to SQS. Using the entire AWS SDK for this is a colossal waste. How could I calculate the signature?
const AWS_DATETIME_FORMAT = 'Ymd\THis\Z';
$url = getenv('SQS_URL');
$data = [
'Action' => 'SendMessage',
'MessageBody' => $body,
'Expires' => (new DateTime('UTC'))->add(new DateInterval('PT1M'))->format(AWS_DATETIME_FORMAT),
'Version' => '2012-11-05',
];
$result = Requests::post($url, sign_request($url, $data), $data);
function sign_request($url, $data) {
// These values are provided by AWS Lambda itself.
$secret_key = getenv('AWS_SECRET_ACCESS_KEY');
$access_key = getenv('AWS_ACCESS_KEY_ID');
$token = getenv('AWS_SESSION_TOKEN');
$region = getenv('AWS_REGION');
$service = 'sqs';
$current = new DateTime('UTC');
$current_date_time = $current->format(AWS_DATETIME_FORMAT);
$current_date = $current->format('Ymd');
$signed_headers = [
'content-type' => 'application/x-www-form-urlencoded',
'host' => "sqs.$region.amazonaws.com",
'x-amz-date' => $current_date_time,
'x-amz-security-token' => $token, // leave this one out if you have a IAM created fixed access key - secret pair and do not need the token.
];
$signed_headers_string = implode(';', array_keys($signed_headers));
$canonical = [
'POST',
parse_url($url, PHP_URL_PATH),
'', // this would be the query string but we do not have one.
];
foreach ($signed_headers as $header => $value) {
$canonical[] = "$header:$value";
}
$canonical[] = ''; // this is always an empty line
$canonical[] = $signed_headers_string;
$canonical[] = hash('sha256', http_build_query($data));
$canonical = implode("\n", $canonical);
$credential_scope = [$current_date, $region, $service, 'aws4_request'];
$key = array_reduce($credential_scope, fn ($key, $credential) => hash_hmac('sha256', $credential, $key, TRUE), 'AWS4' . $secret_key);
$credential_scope = implode('/', $credential_scope);
$string_to_sign = implode("\n", [
'AWS4-HMAC-SHA256',
$current_date_time,
$credential_scope,
hash('sha256', $canonical),
]);
$signature = hash_hmac('sha256', $string_to_sign, $key);
unset($signed_headers['host']);
$signed_headers['Authorization'] = "AWS4-HMAC-SHA256 Credential=$access_key/$credential_scope, SignedHeaders=$signed_headers_string, Signature=$signature";
return $signed_headers;
}
Note this code is using rmccue/requests to do a POST request.
My serverless.yml looks like:
provider:
name: aws
region: us-east-1
runtime: provided.al2
environment:
SQS_URL: !Ref BadgeQueue
resources:
Resources:
BadgeQueue:
Type: AWS::SQS::Queue
Properties:
RedrivePolicy:
maxReceiveCount: 3
deadLetterTargetArn: !GetAtt BadgeDeadLetterQueue.Arn
BadgeDeadLetterQueue:
Type: AWS::SQS::Queue
Properties:
MessageRetentionPeriod: 1209600
I'm trying use firebase/php-jwt in CodeIgniter 3, but I get this error:
Parse error: syntax error, unexpected 'use' (T_USE) in /opt/lampp/htdocs/kpittu_api/application/controllers/User.php on line 23
this is my code:
require('vendor/autoload.php');
use \Firebase\JWT\JWT;
$key = "example_key";
$payload = array(
"iat" => time(),
"exp" => time() + 86400,
"data" => [
"login" => "sii1995",
"fname" => "Salim",
"sname" => "Ibrogimovich",
"lname" => "Ibrogimov"
]
);
$jwt = JWT::encode($payload, $key);
$decoded = JWT::decode($jwt, $key, array('HS256'));
$decoded_array = (array) $decoded;
/*
JWT::$leeway = 60; // $leeway in seconds
$decoded = JWT::decode($jwt, $key, array('HS256'));
*/
echo '<pre>';
print_r($jwt);
echo '<hr>';
print_r($decoded_array);
echo '</pre>';
When I using this code outside CodeIgniter it's work well.
How can Use namespace / use keyword in CodeIgniter?
Dear friends I solve it: I just need to put these two lines above class declarations:
require('vendor/autoload.php');
use \Firebase\JWT\JWT;
class User extends CI_Controller {
I am trying to store object at S3 and retrieve it for that I am doing following
$key = 'myverykey';
$hash = hash_hmac('sha256',$key,true);
$SSECustomerKey = substr($hash,0,32);
$params = [
'Bucket' => 'somebucketname',
'Key' => 'abc.png',
'Body' => "resource",
'ACL' => 'private',
'SSECustomerAlgorithm' => 'AES256',
'SSECustomerKey' => $SSECustomerKey,
'SSECustomerKeyMD5' => md5($SSECustomerKey, true),
];
s3->putObject($params);
And then I am creating signed url like
echo el_s3_getTemporaryLink(id, 'mysecretkey', 'cloudfront-config', 'ab.png');
function el_crypto_hmacSHA1($key, $data, $blocksize = 64) {
if (strlen($key) > $blocksize) $key = pack('H*', sha1($key));
$key = str_pad($key, $blocksize, chr(0x00));
$ipad = str_repeat(chr(0x36), $blocksize);
$opad = str_repeat(chr(0x5c), $blocksize);
$hmac = pack( 'H*', sha1(
($key ^ $opad) . pack( 'H*', sha1(
($key ^ $ipad) . $data
))
));
return base64_encode($hmac);
}
function el_s3_getTemporaryLink($accessKey, $secretKey, $bucket, $path, $expires = 1) {
$expires = time() + intval(floatval($expires) * 60);
$path = str_replace('%2F', '/', rawurlencode($path = ltrim($path, '/')));
$signpath = '/'. $bucket .'/'. $path;
$signsz = implode("\n", $pieces = array('GET', null, null, $expires, $signpath));
$signature = el_crypto_hmacSHA1($secretKey, $signsz);
$url = sprintf('http://%s.s3.amazonaws.com/%s', $bucket, $path);
$qs = http_build_query($pieces = array(
'AWSAccessKeyId' => $accessKey,
'Expires' => $expires,
'Signature' => $signature,
));
return $url.'?'.$qs;
}
it works perfectly fine I am getting url like
http://demobucketname.s3.amazonaws.com/ab.png?AWSAccessKeyId=AKIAJUZQHGRTYNOLEUXQ&Expires=1445855704&Signature=3y6eAq1fe5PVASma5DPFmjV7BB3dY%3D
I can access private object with that if I don't add
'SSECustomerAlgorithm' => 'AES256',
'SSECustomerKey' => $SSECustomerKey,
'SSECustomerKeyMD5' => md5($SSECustomerKey, true),
while putting object to bucket and now I am getting following error
<Error>
<Code>InvalidRequest</Code>
<Message>
The object was stored using a form of Server Side Encryption. The correct parameters must be provided to retrieve the object.
</Message>
<RequestId>E19B53C0EE2A6E7C</RequestId>
<HostId>
WOwzj29NBh49uE5Lmtut96PFY8pf3UD8bBWGLXdAFHryNT94WD7qJbqMbu7fKCfROKEIWKwPPX4=
</HostId>
</Error>
now how to create signed url which works in this case too?
When using the presigned URL to upload a new object, retrieve an existing object, or retrieve only object metadata, you must provide all the encryption headers in your client application. (emphasis added)
http://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html
Note "headers," not query string parameters.
SSE-C essentially doesn't support signed URLs for use in web browsers... which makes sense, since exposing pre-signed URL with the encryption key embedded would also expose the encryption key.
If you need user data encrypted server-side, and for users to access the data with pre-signed URLs, SSE-C isn't likely the correct choice.