Encrypting parameters
Learn how to encrypt parameters so that only certain values can be passed to generate your image.You can use the following code sample to explore using parameters and
different content types with
next/og
.
To learn more about OG Image Generation, see Open Graph Image
Generation.
This is the directory structure for these files:
import { ImageResponse } from 'next/og';
// App router includes @vercel/og.
// No need to install it.
const key = crypto.subtle.importKey(
'raw',
new TextEncoder().encode('my_secret'),
{ name: 'HMAC', hash: { name: 'SHA-256' } },
false,
['sign'],
);
function toHex(arrayBuffer: ArrayBuffer) {
return Array.prototype.map
.call(new Uint8Array(arrayBuffer), (n) => n.toString(16).padStart(2, '0'))
.join('');
}
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
const token = searchParams.get('token');
const verifyToken = toHex(
await crypto.subtle.sign(
'HMAC',
await key,
new TextEncoder().encode(JSON.stringify({ id })),
),
);
if (token !== verifyToken) {
return new Response('Invalid token.', { status: 401 });
}
return new ImageResponse(
(
<div
style={{
display: 'flex',
fontSize: 40,
color: 'black',
background: 'white',
width: '100%',
height: '100%',
padding: '50px 200px',
textAlign: 'center',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h1>Card generated, id={id}.</h1>
</div>
),
{
width: 1200,
height: 630,
},
);
}
If you're not using a framework, you must either add
"type": "module"
to your
package.json
or change your JavaScript Functions'
file extensions from .js
to
.mjs
Then, you need to create a frontend component that can take an id
query parameter, which will be passed to the API route you created above.
Create the dynamic route [id]/page
under /app/encrypted
and paste the following code:
// This page generates the token to prevent generating OG images with random parameters (`id`).
import { createHmac } from 'node:crypto';
function getToken(id: string): string {
const hmac = createHmac('sha256', 'my_secret');
hmac.update(JSON.stringify({ id: id }));
const token = hmac.digest('hex');
return token;
}
interface PageParams {
params: {
id: string;
};
}
export default function Page({ params }: PageParams) {
console.log(params);
const { id } = params;
const token = getToken(id);
return (
<div>
<h1>Encrypted Open Graph Image.</h1>
<p>Only /a, /b, /c with correct tokens are accessible:</p>
<a
href={`/api/encrypted?id=${id}&token=${token}`}
target="_blank"
rel="noreferrer"
>
<code>
/api/encrypted?id={id}&token={token}
</code>
</a>
</div>
);
}
If you're not using a framework, you must either add
"type": "module"
to your
package.json
or change your JavaScript Functions'
file extensions from .js
to
.mjs
Run your project locally and browse to http://localhost/encrypted/a
(b
or c
will also work).
Click on the generated link to be directed to the generated image.
In your actual implementation, you will use the code in /app/encrypted/[id]/page.tsx
with a page to create your post html that will look like this.
Was this helpful?