sending push notification with vapid keys

992 Views Asked by At

can someone assist where i am doing mistake

  1. generate vapid keys and store them
  2. use push-api and store endpoint, p256dh and auth
  3. 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';
    }
0

There are 0 best solutions below