docs
  1. SCAYLE Resource Center
  2. Developer Guide
  3. Basic Setup
  4. Authentication

Authentication

Overview

This guide will show you how to configure:

Storefront Core uses OAuth to authenticate with the SCAYLE Checkout.

Before you start

Make sure you've completed the Setup your Storefront Guide.

Create a new API client using the SCAYLE Panel to get your:

  • client_id
  • client_secret

Token-based authentication using JWKS

Token-based authentication allows us to implement our login forms instead of relying on forms provided by the Checkout service.

Token-based authentication flow

Token-based authentication flow

Token verification (System overview)

Token verification

Configuration

To implement our login forms, Storefront Core acts as an OAuth client and uses the Get JSON Web Key Set Auth API endpoint returning keys for verify JSON Web Token:
{OAUTH_API_HOST}/.well-known/jwks.json.

The API host, client ID, and client secret are configured in the oauth property:

let config = {
    oauth: {
        apiHost: 'https://{{tenant-space}}.storefront.api.scayle.cloud/v1/',
        clientId: '1',
        clientSecret: '', // Set in .env NUXT_STOREFRONT_OAUTH_CLIENT_SECRET
    },
    auth: {
        redirect: {
            home: '',
            logout: ''
        }
    },
}

Environment variables

OAUTH_API_HOSTURL of the Oauth service
OAUTH_CLIENT_IDID that the authorization server assigned to this application
OAUTH_CLIENT_SECRETSecret is known only to the application and the authorization server. It is essentially the application’s password.

Protected RPC

If you want to add a protected RPC, the RPC must check again if there is a user within the request and the requested data/action can be requested/done by the user. This can be done by e.g. matching user IDs within the access token and e.g. the user ID within an order.
For user-related actions like changing the password, this is done by the Auth Service itself.

Password reset URL

Add a URL where a user can reset their password:

  1. Go to the nuxt.config.ts.
  2. Set storefront.shops.[1001].auth.resetPasswordUrl to the URL where a user can reset their password.

The password reset URL must include the query param hash={hash}. When the password-forgotten mail is sent, {hash} will be replaced with an actual hash, which is needed to reset the password.

export default {
  //...
  storefront: {
    //...
    shops: {
      1001: {
        //...
        auth: {
          resetPasswordUrl: 'http://localhost:3000/signin?hash={hash}',
        },
      },
    },
  },
}

Identity Providers

Identity Provider (IDP) support enables the option to use Single Sign-On (SSO). This simplifies the login process by reducing the number of passwords users need to remember, as one set of credentials is used across multiple websites.

The backbone of the Storefront Core integrated IDP support consists of two functionalities:

  1. The internal part that runs useIDP() composable generates redirect URLs for all of the configured IDPs.
  2. handleIDPLoginCallback performs the actual login in our system.

For more information, check the Authentication API Guide.

Configure Identity Provider

Configure your available Identity Providers in the nuxt.config.ts.

Currently available IDPs are Google, Facebook, Keycloak, Apple, and Okta.

export default {
  //...
  storefront: {
    // Global IDP configuration for all shops
    idp: {
      enabled: true,
      idpKeys: ['facebook', 'google'],
      idpRedirectURL: 'http://localhost:3000/signin',
    },
    //...
    shops: {
      1001: {
        // Shop-specific overrides for the IDP configuration
        idp: {
          enabled: true,
          idpKeys: ['facebook'],
          idpRedirectURL: 'http://localhost:3000/signin',
        },
      },
    },
  },
}

Redirect URL

Redirects of the URLs for the IDPs you configured are handled by the useIDP composable. Composables pack related functions together so that you can use them within Vue components.

The function checks if IDP is enabled, validates necessary configurations, and returns a list of redirect URLs for each IDP based on your shop configuration as the data return value.

const { data: externalIDPRedirects, handleIDPLoginCallback } = await useIDP()

handleIDPLogin callback

Once the user clicks on the IDP button, the user is redirected to the IDP login page. After successful login, the user is redirected to the callback URL. That is the shop URL with the query parameter code appended to it. This code is used to generate the access token and refresh token.

watch(
  () => route.query,
  async (query) => {
    if (query.code && isString(query.code)) {
      await handleIDPLoginCallback(query.code)
    }
  },
  {
    immediate: true,
  },
)

IDP Authentication flow

IDP Authentication flow

Styling IDP buttons

The IDPForm component in the Storefront Boilerplate renders login buttons for each provider defined by your configuration. Currently, we have pre-built style buttons for Google, Facebook, Keycloak, Apple, and Okta.

Add a new style to an IDP Service

If you want to add styles to a new IDP Service that is not predefined or override the default class name, you can modify the idpClasses object.

const idpClasses: Record<string, string> = {
  google: 'bg-[#4285F4] text-white hover:bg-[#3869c1] focus:bg-[#3869c1]',
  facebook: 'bg-[#1877F2] text-white hover:bg-[#165dbb] focus:bg-[#165dbb]',
  keycloak: 'bg-[#C43A31] text-white hover:bg-[#a32b26] focus:bg-[#a32b26]',
  apple: 'bg-black text-white hover:bg-[#333333] focus:bg-[#333333]',
  okta: 'bg-[#0061F2] text-white hover:bg-[#004ecb] focus:bg-[#004ecb]',
}

App keys for baskets and wishlists

The appKeys configuration defines how keys are generated for baskets and wishlists.

appKeysmust remain confidential. Exposure may enable unauthorized modifications to customer baskets and wishlists.

wishlistKey and basketKey are template strings. When creating the key Storefront Core will replace {shopId} and {userId} with the current shopId and userId. It will then hash the result with the chosen hash algorithm.

sha256 is the recommended hash algorithm for security reasons and also because it is supported natively in different runtime environments.

md5 is currently still supported to provide backward-compatibility.

let config = {
    appKeys: {
        wishlistKey: 'wishlist_{shopId}_{userId}',
        basketKey: 'basket_{shopId}_{userId}',
        hashAlgorithm: 'sha256',
    },
}