npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

hiko-social-login-react

v1.3.5

Published

HIKO Social Login react for Hydrogen integration

Readme

hiko-social-login-react

npm version license

React bindings for HIKO Social Login — a Shopify social login app — for use in headless / Hydrogen storefronts.

The package ships two things:

  • SocialLoginWidget — a React component that mounts the HIKO login widget and streams customer state to your app via DOM events.
  • hiko-social-login-react/sign — a tiny server-side helper for signing the Headless API (e.g. disconnecting a social provider).

Contents

Installation

npm i hiko-social-login-react --save
# or
yarn add hiko-social-login-react

Prerequisites

Quick start

import { useState, useEffect, useCallback, useRef } from "react";
import { SocialLoginWidget } from "hiko-social-login-react";

export function Login() {
    const shop = "xxxx.myshopify.com";
    const publicAccessToken = "<your Hydrogen public access token>";

    const logoutRef = useRef(null);
    const refreshRef = useRef(null);
    const [customer, setCustomer] = useState(window.HIKO?.customer);

    const handleHiko = useCallback((event) => {
        if (["login", "activate", "multipass"].includes(event.detail.action))
            setCustomer(event.detail.customer);
    }, []);

    useEffect(() => {
        document.addEventListener("hiko", handleHiko);
        return () => document.removeEventListener("hiko", handleHiko);
    }, [handleHiko]);

    if (customer)
        return (
            <ul>
                {Object.keys(customer).map((key) => (
                    <li key={key}>
                        {key}: {String(customer[key])}
                    </li>
                ))}
            </ul>
        );

    return (
        <SocialLoginWidget
            shop={shop}
            publicAccessToken={publicAccessToken}
            baseUrl="https://apps.hiko.link"
            logout={(cb) => (logoutRef.current = cb)}
            refresh={(cb) => (refreshRef.current = cb)}
        />
    );
}

A complete, runnable example lives in src/Demo.tsx.

SocialLoginWidget props

| Prop | Type | Required | Description | | ------------------- | ------------------------ | -------- | --------------------------------------------------------------------------------------------------- | | shop | string | yes | Shop domain, e.g. xxxx.myshopify.com. | | publicAccessToken | string | yes | Hydrogen public access token generated by the Headless app. | | baseUrl | string | yes | Origin that serves the HIKO widget script, e.g. https://apps.hiko.link. | | logout | (cb: () => void) => void | yes | Registration callback — HIKO hands you a logout() function; call it to sign the customer out. | | refresh | (cb: () => void) => void | yes | Registration callback — HIKO hands you a refresh() function; call it to reload the widget script. |

logout and refresh use a callback-registration pattern: you pass a setter, HIKO invokes it with the real function, and you store that in a ref to call later (see src/Demo.tsx).

Customer state & events

The widget dispatches a DOM CustomEvent named hiko on document. Its event.detail carries an action and, for auth actions, the customer:

| action | Meaning | | --------------------------------- | ------------------------------------------- | | login / activate / multipass | Customer authenticated — detail.customer is set. | | click | Widget interaction (no customer change). |

The current customer is also available synchronously at window.HIKO?.customer after the script loads.

Headless API

REST endpoints for headless / Hydrogen storefronts, served by the HIKO backend under /apps/authapp/:action.

Authentication

Every headless request is authenticated by an HMAC-SHA256 signature over the query string, keyed by the shop's Hydrogen public access token (the same publicAccessToken you pass to SocialLoginWidget).

The signed message is every param except signature, keys sorted alphabetically and joined as key=value pairs with & — a plain string with no URL-encoding and no leading ?. The hex-encoded digest is sent as the signature param.

This package ships the signing helper so you don't have to reimplement it:

import { sign } from "hiko-social-login-react/sign";

const signature = sign(
    { customer_id: "gid://shopify/Customer/123", shop: "myshop.myshopify.com", social: "facebook" },
    process.env.HYDROGEN_PUBLIC_ACCESS_TOKEN
);

Failure modes: shop not installed / no public access token / missing signature → 400; signature mismatch → 401.

Sign on the server. The public access token is a signing secret — never expose it in browser code. A storefront should call your own server route, which signs and forwards the request.

DELETE /apps/authapp/disconnect

Remove one social-provider connection from a customer. The customer profile is untouched; only the link to the named provider is deleted. Removing a connection does not revoke the token at the provider. The call is idempotent — safe to retry.

Query parameters

| Param | Required | Description | | ------------- | -------- | ----------------------------------------------------------- | | customer_id | yes | Shopify customer id or GID (normalized to GID server-side). | | social | yes | Provider name, e.g. google, facebook, apple, line. | | shop | yes | Shop domain, e.g. myshop.myshopify.com. | | signature | yes | HMAC-SHA256 hex of the other params (see Authentication). |

Responses

200 OK

{ "customer_id": "gid://shopify/Customer/123", "social": "facebook", "removed": true }

removed is false when the customer had no such connection (idempotent — safe to retry). A well-formed but unrecognized social also returns removed: false rather than an error.

| Status | Meaning | | ------ | ------------------------------------------------------------------------ | | 400 | Missing customer_id, malformed social, shop not installed, no token. | | 401 | Signature mismatch. | | 404 | customer_id does not resolve to a Shopify customer. | | 500 | Shopify API / database error. |

Example — Node.js

import { sign } from "hiko-social-login-react/sign";

const SHOP = "myshop.myshopify.com";
const PUBLIC_ACCESS_TOKEN = process.env.HYDROGEN_PUBLIC_ACCESS_TOKEN;
const BASE = `https://${SHOP}`; // or the app proxy host

async function disconnectSocial(customerId, social) {
    const params = { customer_id: customerId, shop: SHOP, social };
    const signature = sign(params, PUBLIC_ACCESS_TOKEN);
    const query = new URLSearchParams({ ...params, signature }).toString();

    const res = await fetch(`${BASE}/apps/authapp/disconnect?${query}`, {
        method: "DELETE",
    });

    if (!res.ok) {
        const { error } = await res.json().catch(() => ({}));
        throw new Error(`disconnect failed (${res.status}): ${error ?? "unknown"}`);
    }
    return res.json(); // { customer_id, social, removed }
}

// Remove the logged-in customer's Facebook link
await disconnectSocial("gid://shopify/Customer/123", "facebook");

Testing

npm test

Unit tests (Vitest) cover the request-signing helper — deterministic digests, alphabetical key ordering, exclusion of the signature param, and no URL-encoding of values. See src/sign.test.ts.

Links