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.
- 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.
- Make a PKCE pair and a state, keep them, and send the shopper to
authorizeUrl. - On your return address, check the state and trade the code with
exchangeCode. - Act as the shopper with
withAccessToken, and renew the tokens withrefresh.
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:
| Field | Type | Description |
|---|---|---|
token_type | string | One of Bearer. |
expires_in | integer | Seconds (3600). |
access_token | string | |
refresh_token | string |
Errors
| Status | When |
|---|---|
400 | An OAuth error (invalid_request, invalid_grant, unsupported_grant_type…). |
401 | invalid_client: not the client id of one of this shop's active publishable keys. |
402 | The shop is suspended (message only). |
403 | The shop is not live. |
404 | Not found, or the shop's plan has no Integration API. |
429 | Rate 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:
| Field | Type | Description |
|---|---|---|
token_type | string | One of Bearer. |
expires_in | integer | Seconds (3600). |
access_token | string | |
refresh_token | string |
Errors
| Status | When |
|---|---|
400 | An OAuth error (invalid_request, invalid_grant, unsupported_grant_type…). |
401 | invalid_client: not the client id of one of this shop's active publishable keys. |
402 | The shop is suspended (message only). |
403 | The shop is not live. |
404 | Not found, or the shop's plan has no Integration API. |
429 | Rate 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();