Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for private scope #34

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/app/@typing/Settings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ declare module 'App' {
* Read more at {@link https://docs.commercelayer.io/core/authentication#authorization-scopes}
*/
scope: string
/**
* Additional scope used to obtain an access token valid for public organization data in case the `scope` param is a private scope.
* Read more at {@link https://docs.commercelayer.io/core/authentication#authorization-scopes}
*/
publicScope?: string
/**
* Access Token for a sales channel API credentials to be used to authenticate all Commerce Layer API requests.
* Read more at {@link https://docs.commercelayer.io/core/authentication/client-credentials#sales-channel}, {@link https://docs.commercelayer.io/core/authentication/client-credentials}
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/components/forms/SignUpForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ export const SignUpForm = (): JSX.Element => {
domain: config.domain
})

/**
* TODO: Do we need to perform any additional action here if both scope and publicScope are set?
* If a publicScope is set, the customer is expected to match the (private) scope provided.
*/
const createCustomerResponse = await client.customers
.create({
email: formData.customerEmail,
Expand Down
5 changes: 3 additions & 2 deletions packages/app/src/providers/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,14 @@ export function IdentityProvider({

const clientId = getParamFromUrl('clientId') ?? ''
const scope = getParamFromUrl('scope') ?? ''
const publicScope = getParamFromUrl('publicScope') ?? ''
const returnUrl = getParamFromUrl('returnUrl') ?? ''

useEffect(() => {
dispatch({ type: 'identity/onLoad' })

if (clientId != null && scope != null) {
getSettings({ clientId, scope, config })
getSettings({ clientId, scope, publicScope, config })
.then((settings) => {
if (settings.isValid) {
dispatch({ type: 'identity/loaded', payload: settings })
Expand All @@ -73,7 +74,7 @@ export function IdentityProvider({
dispatch({ type: 'identity/onError' })
})
}
}, [clientId, scope])
}, [clientId, scope, publicScope])

if (clientId.length === 0 || scope.length === 0 || returnUrl.length === 0) {
return (
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/utils/getParamFromUrl.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
type UrlParam =
| 'clientId'
| 'scope'
| 'publicScope'
| 'returnUrl'
| 'resetPasswordUrl'
| 'customerEmail'
Expand Down
9 changes: 6 additions & 3 deletions packages/app/src/utils/getSettings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import CommerceLayer from '@commercelayer/sdk'
import type { Settings, InvalidSettings } from 'App'
import type { InvalidSettings, Settings } from 'App'

import { getOrganization } from '#utils/getOrganization'
import { getSubdomain } from '#utils/getSubdomain'
Expand All @@ -22,7 +22,7 @@ const makeInvalidSettings = (): InvalidSettings => ({
retryable: false
})

type GetSettingsProps = Pick<Settings, 'clientId' | 'scope'> & {
type GetSettingsProps = Pick<Settings, 'clientId' | 'scope' | 'publicScope'> & {
config: CommerceLayerAppConfig
}

Expand All @@ -31,6 +31,7 @@ type GetSettingsProps = Pick<Settings, 'clientId' | 'scope'> & {
*
* @param clientId - Commerce Layer application's clientId.
* @param scope - Commerce Layer access token scope (market, stock location).
* @param publicScope - Commerce Layer access token scope suitable for public organization data in case main `scope` param is related to a private scope.
* @param config - Commerce Layer app configuration available from global window object.
* Read more at {@link https://docs.commercelayer.io/developers/authentication/client-credentials#sales-channel}, {@link https://docs.commercelayer.io/core/authentication/password}
*
Expand All @@ -39,6 +40,7 @@ type GetSettingsProps = Pick<Settings, 'clientId' | 'scope'> & {
export const getSettings = async ({
clientId,
scope,
publicScope,
config
}: GetSettingsProps): Promise<Settings | InvalidSettings> => {
const hostname = window !== undefined ? window.location.hostname : ''
Expand All @@ -54,7 +56,7 @@ export const getSettings = async ({
slug,
domain,
clientId,
scope
scope: publicScope ?? scope
})
)

Expand Down Expand Up @@ -82,6 +84,7 @@ export const getSettings = async ({
return {
clientId,
scope,
publicScope,
accessToken: storedToken?.access_token ?? '',
isValid: true,
companySlug: slug,
Expand Down
6 changes: 5 additions & 1 deletion packages/app/src/utils/oauthStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ interface GetStoredSalesChannelTokenConfig {
scope: string
}

// TODO: Define if storageKey needs a naming differentiation for sales channel tokens and customer tokens
/**
* Retrieve and store a Sales Channel `accessToken` used by the app to obtain organization settings and perform suitable requests.
* @param config - Configuration object containing parameters needed by the Sales Channel authentication procedure.
* @returns an access token data set, if available, or `null`.
*/
export const getStoredSalesChannelToken = async ({
app,
slug,
Expand Down