Store Hugs Developers

Shopper sign-in

Shoppers sign in on the shop's own page, with OAuth (authorization code with S256 PKCE). Your site gets their tokens and never sees their password.

  1. In the panel, add your site's return address to a publishable key's Sign-in return addresses. The key's client id is shown below it.
  2. Make a PKCE pair and a state, keep them, and send the shopper to authorizeUrl.
  3. On your return address, check the state and trade the code with exchangeCode.
  4. Act as the shopper with withAccessToken, and renew the tokens with refresh.

Access tokens last an hour and refresh tokens 30 days.

Reach these through $storefront->signIn. The PKCE pair and state come from the PKCE helpers.

Build the sign-in address

$storefront->signIn->authorizeUrl(
    string $clientId,
    string $redirectUri,
    string $state,
    string $codeChallenge,
): string

The shop's sign-in page to send the shopper to: https://{host}/account/authorize with these query values:

Query value Value
client_id The client id you pass.
redirect_uri The return address you pass.
response_type code
scope storefront:customer
state The state you pass.
code_challenge The PKCE challenge you pass.
code_challenge_method S256

Parameters

Parameter Type
$clientId string The publishable key's client id.
$redirectUri string One of the key's sign-in return addresses.
$state string A random value you keep, to check on the return address.
$codeChallenge string The challenge of the PKCE pair whose verifier you keep.

Returns

The address, as a string. No request is made.

Example

use StoreHugs\Integration\Pkce;

$pkce = Pkce::create();
$state = Pkce::state();
session(['storehugs_sign_in' => ['verifier' => $pkce->verifier, 'state' => $state]]);

return redirect()->away($storefront->signIn->authorizeUrl(
    clientId: 'the-key-client-id',
    redirectUri: 'https://www.example.com/account/callback',
    state: $state,
    codeChallenge: $pkce->challenge,
));

Exchange the code

$storefront->signIn->exchangeCode(
    string $code,
    string $clientId,
    string $redirectUri,
    string $codeVerifier,
): array

Trades the code from the redirect for the shopper's tokens, with the authorization_code grant. No Idempotency-Key is sent.

Parameters

Parameter Type
$code string The code query value on your return address.
$clientId string The publishable key's client id.
$redirectUri string The same return address you sent the shopper with.
$codeVerifier string The verifier of the PKCE pair you kept.

Returns

A ShopperTokenResponse array:

FieldTypeDescription
token_typestringOne of Bearer.
expires_inintegerSeconds (3600).
access_tokenstring
refresh_tokenstring

Errors

StatusWhen
400An OAuth error (invalid_request, invalid_grant, unsupported_grant_type…).
401invalid_client: not the client id of one of this shop's active publishable keys.
402The shop is suspended (message only).
403The shop is not live.
404Not found, or the shop's plan has no Integration API.
429Rate limited.

Example

$saved = session()->pull('storehugs_sign_in');

abort_unless(hash_equals($saved['state'], (string) $request->query('state')), 400);

$tokens = $storefront->signIn->exchangeCode(
    code: $request->query('code'),
    clientId: 'the-key-client-id',
    redirectUri: 'https://www.example.com/account/callback',
    codeVerifier: $saved['verifier'],
);

Refresh the tokens

$storefront->signIn->refresh(string $refreshToken, string $clientId): array

New tokens for a refresh token, with the refresh_token grant, before or after the access token runs out.

Parameters

Parameter Type
$refreshToken string The shopper's refresh token.
$clientId string The publishable key's client id.

Returns

A ShopperTokenResponse array:

FieldTypeDescription
token_typestringOne of Bearer.
expires_inintegerSeconds (3600).
access_tokenstring
refresh_tokenstring

Errors

StatusWhen
400An OAuth error (invalid_request, invalid_grant, unsupported_grant_type…).
401invalid_client: not the client id of one of this shop's active publishable keys.
402The shop is suspended (message only).
403The shop is not live.
404Not found, or the shop's plan has no Integration API.
429Rate limited.

Example

$tokens = $storefront->signIn->refresh($tokens['refresh_token'], 'the-key-client-id');

Act as the shopper

$storefront->withAccessToken(string $accessToken): StorefrontClient

The same client, acting for a signed-in shopper: it sends the access token with every request, next to the key. The original client is unchanged.

Parameters

Parameter Type
$accessToken string The shopper's access token.

Returns

A new StorefrontClient. No request is made.

Example

$shopper = $storefront->withAccessToken($tokens['access_token']);
$me = $shopper->customer->get();