diff --git a/blocks/identity-block/components/login/index.jsx b/blocks/identity-block/components/login/index.jsx
index 1fc61c6ac..6eab30487 100644
--- a/blocks/identity-block/components/login/index.jsx
+++ b/blocks/identity-block/components/login/index.jsx
@@ -11,6 +11,7 @@ const useLogin = ({
loggedInPageLocation,
isOIDC,
appleCode,
+ appleState,
}) => {
const { Identity } = useIdentity();
@@ -32,8 +33,13 @@ const useLogin = ({
};
useEffect(() => {
- const askForloginWithApple = async (code) => {
- await Identity.appleSignOn(code);
+ const askForloginWithApple = async (code, state) => {
+ if (state) {
+ await Identity.signInWithOIDC(code, state);
+ } else {
+ await Identity.appleSignOn(code);
+ }
+
const isLoggedIn = await Identity.isLoggedIn();
if (isLoggedIn) {
@@ -42,9 +48,9 @@ const useLogin = ({
};
if (Identity && appleCode) {
- askForloginWithApple(appleCode);
+ askForloginWithApple(appleCode, appleState);
}
- }, [appleCode, Identity]);
+ }, [appleCode, Identity, appleState]);
useEffect(() => {
const searchParams = new URLSearchParams(window.location.search.substring(1));
diff --git a/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.jsx b/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.jsx
index f03e23747..7e5742aad 100644
--- a/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.jsx
+++ b/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.jsx
@@ -5,15 +5,38 @@ import { SIGN_UP } from "../constants";
const AppleIcon = ;
-function AppleSignIn({ customButtons, socialSignOnIn, className }) {
+function AppleSignIn({ customButtons, socialSignOnIn, className, oidcClients = [], appleClientId }) {
const phrases = usePhrases();
const { Identity } = useIdentity();
+ const appleOIDCClient = oidcClients.find((oidcClient) => {
+ const parsedClientId = oidcClient.clientId.split(';')[0];
+
+ return oidcClient.protocol === 'Apple' && parsedClientId === appleClientId;
+ });
+
+ const handleClick = () => {
+ if (appleOIDCClient?.clientId) {
+ Identity.initiateOIDC(
+ appleOIDCClient.clientId,
+ ['name', 'email'],
+ true,
+ true
+ );
+ } else {
+ Identity.initAppleSignOn();
+ }
+ };
+
return (
+
+
);
}
diff --git a/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.test.jsx b/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.test.jsx
index a65b73950..d07488ecf 100644
--- a/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.test.jsx
+++ b/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.test.jsx
@@ -19,6 +19,21 @@ jest.mock("@wpmedia/arc-themes-components", () => ({
Icon: () => ,
}));
+const mockInitAppleSignOn = jest.fn();
+const mockInitiateOIDCMock = jest.fn();
+
+jest.mock("@wpmedia/arc-themes-components", () => ({
+ ...jest.requireActual("@wpmedia/arc-themes-components"),
+ Icon: () => ,
+ useIdentity: () => {
+ const Identity = {
+ initiateOIDC: mockInitiateOIDCMock,
+ initAppleSignOn: mockInitAppleSignOn,
+ };
+ return { Identity };
+ },
+}));
+
describe("Identity Social Login Component", () => {
beforeEach(() => {
jest.clearAllMocks();
@@ -37,4 +52,28 @@ describe("Identity Social Login Component", () => {
render();
expect(screen.getByText("identity-block.social-signOn-apple-signUp")).not.toBeNull();
});
+
+ it("triggers Identity.initiateOIDC when using Apple OIDC is used", () => {
+ render();
+ screen.getByText("identity-block.social-signOn-apple-login").click();
+ expect(mockInitiateOIDCMock).toHaveBeenCalled();
+ });
+
+ it("triggers Identity.initAppleSignOn when using Apple v1 sign on is used", () => {
+ render();
+ screen.getByText("identity-block.social-signOn-apple-login").click();
+ expect(mockInitAppleSignOn).toHaveBeenCalled();
+ });
+
+ it("triggers Identity.initAppleSignOn when clientId is not available in OIDC client list", () => {
+ render();
+ screen.getByText("identity-block.social-signOn-apple-login").click();
+ expect(mockInitAppleSignOn).toHaveBeenCalled();
+ });
+
+ it("triggers Identity.initAppleSignOn when clientId is not a protocol: 'Apple'", () => {
+ render();
+ screen.getByText("identity-block.social-signOn-apple-login").click();
+ expect(mockInitAppleSignOn).toHaveBeenCalled();
+ });
});
diff --git a/blocks/identity-block/components/social-sign-on/index.jsx b/blocks/identity-block/components/social-sign-on/index.jsx
index 833231b31..b717577ee 100644
--- a/blocks/identity-block/components/social-sign-on/index.jsx
+++ b/blocks/identity-block/components/social-sign-on/index.jsx
@@ -5,19 +5,60 @@ import GoogleSignIn from "./_children/GoogleSignIn";
import AppleSignIn from "./_children/AppleSignIn";
import useSocialSignIn from "./utils/useSocialSignIn";
-const SocialSignOn = ({ className, onError, redirectURL, isOIDC, socialSignOnIn, customButtons }) => {
- const { facebookAppId, googleClientId, appleTeamId, appleKeyId, appleUrlToReceiveAuthToken} = useSocialSignIn(redirectURL, isOIDC, socialSignOnIn, onError, customButtons);
+const SocialSignOn = ({
+ className,
+ onError,
+ redirectURL,
+ isOIDC,
+ socialSignOnIn,
+ customButtons,
+ appleClientId,
+}) => {
+ const {
+ facebookAppId,
+ googleClientId,
+ appleTeamId,
+ appleKeyId,
+ appleUrlToReceiveAuthToken,
+ oidcClients,
+ } = useSocialSignIn(redirectURL, isOIDC, socialSignOnIn, onError, customButtons);
+
+ const hasAppleClient = () => {
+ const hasOIDCAppleClient = oidcClients && oidcClients.find((oidcClient) => (
+ oidcClient.protocol === "Apple" && oidcClient.clientId === appleClientId
+ ));
+
+ if (hasOIDCAppleClient) {
+ return true;
+ }
+
+ if (appleTeamId && appleKeyId && appleUrlToReceiveAuthToken) {
+ return true;
+ }
+
+ return false;
+ }
+
return (
- {googleClientId ? : null}
- {facebookAppId ? : null}
- {appleTeamId && appleKeyId && appleUrlToReceiveAuthToken ? : null}
+ {googleClientId && }
+ {facebookAppId && }
+ {hasAppleClient() && (
+
+ )}
);
};
SocialSignOn.propTypes = {
redirectURL: PropTypes.string.isRequired,
+ appleClientId: PropTypes.string,
onError: PropTypes.func.isRequired,
};
diff --git a/blocks/identity-block/components/social-sign-on/index.test.jsx b/blocks/identity-block/components/social-sign-on/index.test.jsx
index 9451a0d1d..c8c30bb6a 100644
--- a/blocks/identity-block/components/social-sign-on/index.test.jsx
+++ b/blocks/identity-block/components/social-sign-on/index.test.jsx
@@ -12,7 +12,7 @@ jest.mock('@wpmedia/arc-themes-components', () => ({
Button: (props) => mockButton(props),
useIdentity: jest.fn(),
usePhrases: jest.fn()
- }));
+}));
describe("Identity Social Login Component", () => {
it("renders nothing if config settings are false", () => {
@@ -24,8 +24,8 @@ describe("Identity Social Login Component", () => {
googleClientId: false,
facebookAppId: false,
},
- initFacebookLogin: () => {},
- initializeFacebook: () => {},
+ initFacebookLogin: () => { },
+ initializeFacebook: () => { },
},
}));
usePhrases.mockImplementation(() => ({
@@ -61,8 +61,8 @@ describe("Identity Social Login Component", () => {
recaptchaSiteKey: "6LdXKVQcAAAAAO2tv3GdUbSK-1vcgujX6cP0IgF_",
}),
),
- initFacebookLogin: () => {},
- initializeFacebook: () => {},
+ initFacebookLogin: () => { },
+ initializeFacebook: () => { },
isLoggedIn: jest.fn(() => false),
},
}));
@@ -82,8 +82,8 @@ describe("Identity Social Login Component", () => {
useIdentity.mockImplementation(() => ({
Identity: {
getConfig: getConfigMock,
- initFacebookLogin: () => {},
- initializeFacebook: () => {},
+ initFacebookLogin: () => { },
+ initializeFacebook: () => { },
isLoggedIn: jest.fn(() => false),
},
isInitialized: true,
@@ -110,9 +110,9 @@ describe("Identity Social Login Component", () => {
facebookAppId: true,
},
facebookSignOn: facebookSignOnMock,
- getConfig: () => {},
- initFacebookLogin: () => {},
- initializeFacebook: () => {},
+ getConfig: () => { },
+ initFacebookLogin: () => { },
+ initializeFacebook: () => { },
isLoggedIn: jest.fn(() => false),
},
}));
@@ -140,9 +140,9 @@ describe("Identity Social Login Component", () => {
facebookAppId: true,
},
facebookSignOn: facebookSignOnMock,
- getConfig: () => {},
- initFacebookLogin: () => {},
- initializeFacebook: () => {},
+ getConfig: () => { },
+ initFacebookLogin: () => { },
+ initializeFacebook: () => { },
isLoggedIn: jest.fn(() => false),
},
}));
@@ -162,6 +162,48 @@ describe("Identity Social Login Component", () => {
window.onFacebookSignOn();
expect(onErrorMock).toHaveBeenCalled();
});
+
+ it("renders Apple Sign in", () => {
+ useIdentity.mockImplementation(() => ({
+ isInitialized: true,
+ isLoggedIn: () => true,
+ Identity: {
+ configOptions: {
+ googleClientId: true,
+ facebookAppId: true,
+ teamId: "teamId",
+ keyId: "keyId",
+ urlToReceiveAuthToken: "urlToReceiveAuthToken",
+ oidcClients: [],
+ },
+ getConfig: jest.fn(() =>
+ Promise.resolve({
+ signinRecaptcha: false,
+ recaptchaSiteKey: "6LdXKVQcAAAAAO2tv3GdUbSK-1vcgujX6cP0IgF_",
+ }),
+ ),
+ initFacebookLogin: () => { },
+ initializeFacebook: () => { },
+ isLoggedIn: jest.fn(() => false),
+ },
+ }));
+
+ usePhrases.mockImplementation(() => ({
+ t: jest
+ .fn()
+ .mockReturnValue(
+ "Sign-in prompt was suppressed by the user or dismissed. Please try again later or use another sign-in method.",
+ ),
+ }));
+
+ render(
+
+ null} redirectURL="#" />
+ ,
+ );
+
+ expect(screen.getByTestId("apple-sign-in-button")).toBeInTheDocument();
+ });
});
describe("Identity Social Login Component - Google Button", () => {
@@ -174,8 +216,8 @@ describe("Identity Social Login Component - Google Button", () => {
googleClientId: true,
facebookAppId: false,
},
- initFacebookLogin: () => {},
- initializeFacebook: () => {},
+ initFacebookLogin: () => { },
+ initializeFacebook: () => { },
},
}));
});
@@ -215,8 +257,8 @@ describe("Identity Social Login Component - Facebook Button", () => {
googleClientId: false,
facebookAppId: true,
},
- initFacebookLogin: () => {},
- initializeFacebook: () => {},
+ initFacebookLogin: () => { },
+ initializeFacebook: () => { },
},
}));
});
diff --git a/blocks/identity-block/components/social-sign-on/utils/useSocialSignIn.js b/blocks/identity-block/components/social-sign-on/utils/useSocialSignIn.js
index 4bf7692ed..37f024e53 100644
--- a/blocks/identity-block/components/social-sign-on/utils/useSocialSignIn.js
+++ b/blocks/identity-block/components/social-sign-on/utils/useSocialSignIn.js
@@ -182,6 +182,7 @@ function useSocialSignIn(
appleTeamId: config.teamId,
appleKeyId: config.keyId,
appleUrlToReceiveAuthToken: config.urlToReceiveAuthToken,
+ oidcClients: config.oidcClients,
updateIdentities,
};
}
diff --git a/blocks/identity-block/features/social-sign-on/default.jsx b/blocks/identity-block/features/social-sign-on/default.jsx
index 735608290..439de9293 100644
--- a/blocks/identity-block/features/social-sign-on/default.jsx
+++ b/blocks/identity-block/features/social-sign-on/default.jsx
@@ -18,7 +18,8 @@ const SocialSignOnBlock = ({ customFields }) => {
OIDC,
socialSignOnIn,
hideDiv,
- customButtons
+ customButtons,
+ appleClientId,
} = customFields;
const checkAppleCodeExists = (url) => {
@@ -27,7 +28,8 @@ const SocialSignOnBlock = ({ customFields }) => {
const charsAfterLastQuestionMark = urlQueryParams[urlQueryParams.length - 1];
const queryParams = new URLSearchParams(charsAfterLastQuestionMark);
const appleCode = queryParams.get("code");
- return appleCode;
+ const appleState = queryParams.get("state");
+ return { appleCode, appleState };
}
return null;
};
@@ -37,7 +39,7 @@ const SocialSignOnBlock = ({ customFields }) => {
const isOIDC =
OIDC && url.searchParams.get("client_id") && url.searchParams.get("response_type") === "code";
- const appleCode = checkAppleCodeExists(urlString);
+ const { appleCode, appleState } = checkAppleCodeExists(urlString);
const { isAdmin, arcSite } = useFusionContext();
const { locale } = getProperties(arcSite);
const phrases = getTranslatedPhrases(locale);
@@ -53,6 +55,7 @@ const SocialSignOnBlock = ({ customFields }) => {
loggedInPageLocation,
isOIDC,
appleCode,
+ appleState,
});
if (!isInitialized) {
@@ -72,6 +75,7 @@ const SocialSignOnBlock = ({ customFields }) => {
isOIDC={isOIDC}
socialSignOnIn={socialSignOnIn}
customButtons={customButtons}
+ appleClientId={appleClientId}
/>
{error ? (
@@ -91,6 +95,12 @@ SocialSignOnBlock.propTypes = {
name: "Redirect URL",
defaultValue: "/account/",
}),
+ appleClientId: PropTypes.string.tag({
+ name: "Apple OIDC Client ID",
+ defaultValue: "",
+ description:
+ 'Client ID for Apple OIDC authentication provider. This is the "Provider key" in your "Authentication Providers" settings',
+ }),
redirectToPreviousPage: PropTypes.bool.tag({
name: "Redirect to previous page",
defaultValue: true,
diff --git a/blocks/identity-block/package.json b/blocks/identity-block/package.json
index 128438508..d06868e8c 100644
--- a/blocks/identity-block/package.json
+++ b/blocks/identity-block/package.json
@@ -30,7 +30,7 @@
},
"dependencies": {
"@arc-fusion/prop-types": "^0.1.5",
- "@arc-publishing/sdk-identity": "^1.88.0",
+ "@arc-publishing/sdk-identity": "^1.89.0",
"react-google-recaptcha": "^3.1.0",
"react-google-recaptcha-v3": "^1.10.1"
},
@@ -38,4 +38,4 @@
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/react": "^16.0.0"
}
-}
+}
\ No newline at end of file
diff --git a/blocks/subscriptions-block/package.json b/blocks/subscriptions-block/package.json
index 4a3d08263..7f004645f 100644
--- a/blocks/subscriptions-block/package.json
+++ b/blocks/subscriptions-block/package.json
@@ -31,9 +31,9 @@
"dependencies": {
"@arc-fusion/prop-types": "^0.1.5",
"@arc-publishing/sdk-sales": "^1.55.0",
- "@arc-publishing/sdk-identity": "^1.88.0",
+ "@arc-publishing/sdk-identity": "^1.89.0",
"@stripe/react-stripe-js": "^2.4.0",
"@stripe/stripe-js": "^2.3.0",
"is-url": "^1.2.4"
}
-}
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index fe7dc801d..c9f8ed09a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -83,7 +83,7 @@
},
"devDependencies": {
"@arc-fusion/prop-types": "^0.1.5",
- "@arc-publishing/sdk-identity": "^1.88.0",
+ "@arc-publishing/sdk-identity": "^1.89.0",
"@babel/core": "^7.23.2",
"@babel/eslint-parser": "^7.23.3",
"@babel/plugin-proposal-class-properties": "^7.16.7",
@@ -405,7 +405,7 @@
"license": "CC-BY-NC-ND-4.0",
"dependencies": {
"@arc-fusion/prop-types": "^0.1.5",
- "@arc-publishing/sdk-identity": "^1.88.0",
+ "@arc-publishing/sdk-identity": "^1.89.0",
"react-google-recaptcha": "^3.1.0",
"react-google-recaptcha-v3": "^1.10.1"
},
@@ -927,7 +927,7 @@
"license": "CC-BY-NC-ND-4.0",
"dependencies": {
"@arc-fusion/prop-types": "^0.1.5",
- "@arc-publishing/sdk-identity": "^1.55.0",
+ "@arc-publishing/sdk-identity": "^1.89.0",
"@arc-publishing/sdk-sales": "^1.55.0",
"@stripe/react-stripe-js": "^2.4.0",
"@stripe/stripe-js": "^2.3.0",
@@ -1188,9 +1188,9 @@
}
},
"node_modules/@arc-publishing/sdk-identity": {
- "version": "1.88.0",
- "resolved": "https://registry.npmjs.org/@arc-publishing/sdk-identity/-/sdk-identity-1.88.0.tgz",
- "integrity": "sha512-CSq/eAsE3tppnDnxRTHnTbO9HAo+4eS3byn+xHSPvDbDU/E+tPngWi0Hu9skfJxC1kBb/X3I97NBPcNxGs9fXQ==",
+ "version": "1.89.0",
+ "resolved": "https://registry.npmjs.org/@arc-publishing/sdk-identity/-/sdk-identity-1.89.0.tgz",
+ "integrity": "sha512-fgHgaL6qtcOLpXasRhjSJrNlu5+O17rd+LBgALdlViRiaStuXra4trOL2kstCnb2JSE1O87m6hYygkoa4uEjzg==",
"engines": {
"node": ">=8"
}
diff --git a/package.json b/package.json
index e281a1f4e..2ea7271b5 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,7 @@
},
"devDependencies": {
"@arc-fusion/prop-types": "^0.1.5",
- "@arc-publishing/sdk-identity": "^1.88.0",
+ "@arc-publishing/sdk-identity": "^1.89.0",
"@babel/core": "^7.23.2",
"@babel/eslint-parser": "^7.23.3",
"@babel/plugin-proposal-class-properties": "^7.16.7",
@@ -199,4 +199,4 @@
"stylelint": "$stylelint"
}
}
-}
+}
\ No newline at end of file