security: restrict installs to ALLOWED_SHOP and remove generic landing form
This commit is contained in:
+20
-35
@@ -1,56 +1,41 @@
|
||||
import type { LoaderFunctionArgs } from "react-router";
|
||||
import { redirect, Form, useLoaderData } from "react-router";
|
||||
|
||||
import { login } from "../../shopify.server";
|
||||
import { redirect, useLoaderData } from "react-router";
|
||||
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const url = new URL(request.url);
|
||||
const allowedShop = process.env.ALLOWED_SHOP?.trim();
|
||||
const shop = url.searchParams.get("shop");
|
||||
|
||||
if (url.searchParams.get("shop")) {
|
||||
throw redirect(`/app?${url.searchParams.toString()}`);
|
||||
// If a shop param is present and it's the allow-listed merchant, send them
|
||||
// straight into the embedded app. Any other shop is rejected so this URL
|
||||
// can't be used to install the app on arbitrary stores.
|
||||
if (shop) {
|
||||
if (!allowedShop || shop.toLowerCase() === allowedShop.toLowerCase()) {
|
||||
throw redirect(`/app?${url.searchParams.toString()}`);
|
||||
}
|
||||
throw new Response("This app is private and not available for installation.", { status: 403 });
|
||||
}
|
||||
|
||||
return { showForm: Boolean(login) };
|
||||
return { allowedShop: allowedShop ?? null };
|
||||
};
|
||||
|
||||
export default function App() {
|
||||
const { showForm } = useLoaderData<typeof loader>();
|
||||
const { allowedShop } = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<div className={styles.index}>
|
||||
<div className={styles.content}>
|
||||
<h1 className={styles.heading}>A short heading about [your app]</h1>
|
||||
<h1 className={styles.heading}>LinumIQ Invoice</h1>
|
||||
<p className={styles.text}>
|
||||
A tagline about [your app] that describes your value proposition.
|
||||
Private Shopify app for issuing GoBD-compliant PDF invoices.
|
||||
</p>
|
||||
<p className={styles.text}>
|
||||
{allowedShop
|
||||
? `This installation is reserved for ${allowedShop}. Open the app from the Shopify admin.`
|
||||
: "Open the app from the Shopify admin."}
|
||||
</p>
|
||||
{showForm && (
|
||||
<Form className={styles.form} method="post" action="/auth/login">
|
||||
<label className={styles.label}>
|
||||
<span>Shop domain</span>
|
||||
<input className={styles.input} type="text" name="shop" />
|
||||
<span>e.g: my-shop-domain.myshopify.com</span>
|
||||
</label>
|
||||
<button className={styles.button} type="submit">
|
||||
Log in
|
||||
</button>
|
||||
</Form>
|
||||
)}
|
||||
<ul className={styles.list}>
|
||||
<li>
|
||||
<strong>Product feature</strong>. Some detail about your feature and
|
||||
its benefit to your customer.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Product feature</strong>. Some detail about your feature and
|
||||
its benefit to your customer.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Product feature</strong>. Some detail about your feature and
|
||||
its benefit to your customer.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user