diff --git a/README.md b/README.md index 22cf5239..6180b9e9 100644 --- a/README.md +++ b/README.md @@ -239,12 +239,12 @@ This library works on MacOS 10.15+ if using in conjunction with [react-native-ma ```js // App.js -import React from 'react'; +import React from "react"; import { View, - TouchableWithoutFeedback + TouchableWithoutFeedback, Text -} from 'react-native'; +} from "react-native"; import { appleAuth, appleAuthAndroid, diff --git a/example/app.android.js b/example/app.android.js index faff15f7..d941dd10 100644 --- a/example/app.android.js +++ b/example/app.android.js @@ -16,21 +16,22 @@ * */ -import React from 'react'; -import { StyleSheet, View, Image, Text } from 'react-native'; -import { AppleButton, appleAuthAndroid } from '@invertase/react-native-apple-authentication'; +import React, { useState } from 'react'; +import { StyleSheet, View, Image, TouchableOpacity, Text } from 'react-native'; +import { AppleButton, appleAuthAndroid, AppleAuthWebView } from '@invertase/react-native-apple-authentication'; import 'react-native-get-random-values'; import { v4 as uuid } from 'uuid' import appleLogoWhite from './images/apple_logo_white.png'; import appleLogoBlack from './images/apple_logo_black.png'; +import { getAppleAuthConfig, parseAppleAuthResponse } from './app.shared'; - -export default RootComponent = () => { +export default function RootComponent() { + const [appleAuthConfig, setAppleAuthConfig] = useState(null); const doAppleLogin = async () => { // Generate secure, random values for state and nonce const rawNonce = uuid(); - const state = uuid(); + const rawState = uuid(); try { // Initialize the module @@ -63,7 +64,7 @@ export default RootComponent = () => { // [OPTIONAL] // Unique state value used to prevent CSRF attacks. A UUID will be generated if nothing is provided. - state, + state: rawState, }); const response = await appleAuthAndroid.signIn(); @@ -96,70 +97,85 @@ export default RootComponent = () => { } }; + if (appleAuthConfig) { + return ( + { + setAppleAuthConfig(null); + parseAppleAuthResponse(responseContent); + } + } + /> + ); + } + return ( - {appleAuthAndroid.isSupported && ( - - Buttons + { + appleAuthAndroid.isSupported && ( + + Buttons - Continue Styles - doAppleLogin()} - leftView={( - - )} - /> - doAppleLogin()} - leftView={( - - )} - /> - doAppleLogin()} - leftView={( - - )} - /> + Continue Styles + doAppleLogin()} + leftView={( + + )} + /> + doAppleLogin()} + leftView={( + + )} + /> + doAppleLogin()} + leftView={( + + )} + /> Sign-in Styles { )} - {!appleAuthAndroid.isSupported && ( - Sign In with Apple requires Android 4.4 (API 19) or higher. - )} + { + !appleAuthAndroid.isSupported && ( + + + Sign In with Apple requires Android 4.4 (API 19) or higher. + + + But in such cases you can always use apple webView sign in! + + + ) + } + + { + { + setAppleAuthConfig(getAppleAuthConfig()); + } + }> + + + WebView sign in with Apple + + + + } ); } diff --git a/example/app.ios.js b/example/app.ios.js index 38e84210..de9bcbf9 100644 --- a/example/app.ios.js +++ b/example/app.ios.js @@ -17,8 +17,9 @@ */ import React, { useState, useEffect } from 'react'; -import { StyleSheet, View, Text } from 'react-native'; -import { appleAuth, AppleButton } from '@invertase/react-native-apple-authentication'; +import { StyleSheet, View, Text, TouchableOpacity} from 'react-native'; +import { appleAuth, AppleButton, AppleAuthWebView } from '@invertase/react-native-apple-authentication'; +import { getAppleAuthConfig, parseAppleAuthResponse } from './app.shared'; /** * You'd technically persist this somewhere for later use. @@ -93,6 +94,8 @@ async function onAppleButtonPress(updateCredentialStateForUser) { export default function RootComponent() { const [credentialStateForUser, updateCredentialStateForUser] = useState(-1); + const [appleAuthConfig, setAppleAuthConfig] = useState(null); + useEffect(() => { if (!appleAuth.isSupported) return; @@ -112,64 +115,103 @@ export default function RootComponent() { }); }, []); - if (!appleAuth.isSupported) { + if (appleAuthConfig) { return ( - - Apple Authentication is not supported on this device. - + { + setAppleAuthConfig(null); + parseAppleAuthResponse(responseContent); + } + } + /> ); } return ( - Credential State - {credentialStateForUser} - - Buttons - Continue Styles - onAppleButtonPress(updateCredentialStateForUser)} - /> - onAppleButtonPress(updateCredentialStateForUser)} - /> - onAppleButtonPress(updateCredentialStateForUser)} - /> - Sign-in Styles - onAppleButtonPress(updateCredentialStateForUser)} - /> - onAppleButtonPress(updateCredentialStateForUser)} - /> - onAppleButtonPress(updateCredentialStateForUser)} - /> + { + appleAuth.isSupported && ( + + Credential State + {credentialStateForUser} + + Buttons + Continue Styles + onAppleButtonPress(updateCredentialStateForUser)} + /> + onAppleButtonPress(updateCredentialStateForUser)} + /> + onAppleButtonPress(updateCredentialStateForUser)} + /> + Sign-in Styles + onAppleButtonPress(updateCredentialStateForUser)} + /> + onAppleButtonPress(updateCredentialStateForUser)} + /> + onAppleButtonPress(updateCredentialStateForUser)} + /> + + ) + } + + { + !appleAuth.isSupported && ( + + + Apple Authentication is not supported on this device. + + + But in such cases you can always use apple webView sign in! + + + ) + } + + { + { + setAppleAuthConfig(getAppleAuthConfig()); + } + }> + + + WebView sign in with Apple + + + + } ); } diff --git a/example/app.shared.js b/example/app.shared.js new file mode 100644 index 00000000..0bd68b3c --- /dev/null +++ b/example/app.shared.js @@ -0,0 +1,57 @@ +export function getAppleAuthConfig() { + + // Generate secure, random values for state and nonce + const nonce = "uio";//uuid(); + const state = "uio";//uuid(); + + // https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/incorporating_sign_in_with_apple_into_other_platforms + const appleAuthConfig = { + // The Service ID you registered with Apple + clientId: "com.example.client-web", + + // Return URL added to your Apple dev console. It must still match the URL you provided to Apple. + redirectUri: "https://example.com/auth/callback", + + // The type of response requested - code, id_token, or both. + responseType: "code id_token", + + // [OPTIONAL] + // The amount of user information requested from Apple - code id_token, code, id_token + scope: "name email", + + // [OPTIONAL] + // Random nonce value that will be SHA256 hashed before sending to Apple. + nonce: nonce, + + // [OPTIONAL] + // Unique state value used to prevent CSRF attacks. A UUID will be generated if nothing is provided. + state: state + }; + + return appleAuthConfig; +} + +export function parseAppleAuthResponse(responseContent) { + + // Handle your server response (after login - apple redirects to your server url) + console.log("parseAppleAuthResponse responseContent", responseContent); + + try { + + // We expecting json response from a server + const serverResponse = JSON.parse(responseContent); + + // Next code depents what your server returns on error. + // If it is json error pbject then check it. + // On success my server return a json with {jwt: "some value"} + const jwt = serverResponse.jwt; + + if (jwt) { + console.log("parseAppleAuthResponse responseContent jwt", jwt); + } else { + console.error("parseAppleAuthResponse responseContent does not contain expected jwt"); + } + } catch (error) { + console.error("parseAppleAuthResponse responseContent is not a valid json", error); + } +} diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index a6859dcc..0281c8c6 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -284,6 +284,8 @@ PODS: - glog - react-native-get-random-values (1.9.0): - React-Core + - react-native-webview (13.6.2): + - React-Core - React-NativeModulesApple (0.72.6): - React-callinvoker - React-Core @@ -397,7 +399,7 @@ PODS: - React-Core - React-jsi - ReactTestApp-Resources (1.0.0-dev) - - RNAppleAuthentication (2.2.2): + - RNAppleAuthentication (2.3.0): - React-Core - SocketRocket (0.6.1) - Yoga (1.14.0) @@ -425,6 +427,7 @@ DEPENDENCIES: - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) - React-logger (from `../node_modules/react-native/ReactCommon/logger`) - react-native-get-random-values (from `../node_modules/react-native-get-random-values`) + - react-native-webview (from `../node_modules/react-native-webview`) - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) @@ -496,6 +499,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/logger" react-native-get-random-values: :path: "../node_modules/react-native-get-random-values" + react-native-webview: + :path: "../node_modules/react-native-webview" React-NativeModulesApple: :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" React-perflogger: @@ -564,6 +569,7 @@ SPEC CHECKSUMS: React-jsinspector: 194e32c6aab382d88713ad3dd0025c5f5c4ee072 React-logger: cebf22b6cf43434e471dc561e5911b40ac01d289 react-native-get-random-values: dee677497c6a740b71e5612e8dbd83e7539ed5bb + react-native-webview: 8fc09f66a1a5b16bbe37c3878fda27d5982bb776 React-NativeModulesApple: 63505fb94b71e2469cab35bdaf36cca813cb5bfd React-perflogger: e3596db7e753f51766bceadc061936ef1472edc3 React-RCTActionSheet: 17ab132c748b4471012abbcdcf5befe860660485 @@ -584,7 +590,7 @@ SPEC CHECKSUMS: ReactNativeHost: 5caf8c9381f26c453fabbe8c3b87f6a013a3c459 ReactTestApp-DevSupport: b1c7adc1c49c50d3bc1cbe7f23191170bdac0319 ReactTestApp-Resources: 1f512f66574607bcfa614e9c0d30e7a990fecf30 - RNAppleAuthentication: 0571c08da8c327ae2afc0261b48b4a515b0286a6 + RNAppleAuthentication: e99eaf3c4c01ad8ecb6125dd6f0cfd98871685b5 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Yoga: b76f1acfda8212aa16b7e26bcce3983230c82603 diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index 98635c33..861e216b 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -284,6 +284,8 @@ PODS: - glog - react-native-get-random-values (1.9.0): - React-Core + - react-native-webview (13.6.2): + - React-Core - React-NativeModulesApple (0.72.5): - React-callinvoker - React-Core @@ -397,7 +399,7 @@ PODS: - React-Core - React-jsi - ReactTestApp-Resources (1.0.0-dev) - - RNAppleAuthentication (2.2.2): + - RNAppleAuthentication (2.3.0): - React-Core - SocketRocket (0.7.0) - Yoga (1.14.0) @@ -425,6 +427,7 @@ DEPENDENCIES: - React-jsinspector (from `../node_modules/react-native-macos/ReactCommon/jsinspector`) - React-logger (from `../node_modules/react-native-macos/ReactCommon/logger`) - react-native-get-random-values (from `../node_modules/react-native-get-random-values`) + - react-native-webview (from `../node_modules/react-native-webview`) - React-NativeModulesApple (from `../node_modules/react-native-macos/ReactCommon/react/nativemodule/core/platform/ios`) - React-perflogger (from `../node_modules/react-native-macos/ReactCommon/reactperflogger`) - React-RCTActionSheet (from `../node_modules/react-native-macos/Libraries/ActionSheetIOS`) @@ -496,6 +499,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-macos/ReactCommon/logger" react-native-get-random-values: :path: "../node_modules/react-native-get-random-values" + react-native-webview: + :path: "../node_modules/react-native-webview" React-NativeModulesApple: :path: "../node_modules/react-native-macos/ReactCommon/react/nativemodule/core/platform/ios" React-perflogger: @@ -564,6 +569,7 @@ SPEC CHECKSUMS: React-jsinspector: c25519b0c5b03eaedbb8332f9a42b30a0a3d05fe React-logger: 2f13e5bdf0bfe2edc6b0473c4749a96a3a7ac048 react-native-get-random-values: dee677497c6a740b71e5612e8dbd83e7539ed5bb + react-native-webview: 8fc09f66a1a5b16bbe37c3878fda27d5982bb776 React-NativeModulesApple: 91f44f048ff46a6df8c2e9018e3ff79497a5438c React-perflogger: 6ccd6df1be652005b9e635df8fae345618466bde React-RCTActionSheet: 4adbdcae93457b2b0d146d9fa8ab7c835f661fb6 @@ -584,7 +590,7 @@ SPEC CHECKSUMS: ReactNativeHost: 5caf8c9381f26c453fabbe8c3b87f6a013a3c459 ReactTestApp-DevSupport: b1c7adc1c49c50d3bc1cbe7f23191170bdac0319 ReactTestApp-Resources: 8539dac0f8d2ef3821827a537e37812104c6ff78 - RNAppleAuthentication: 0571c08da8c327ae2afc0261b48b4a515b0286a6 + RNAppleAuthentication: e99eaf3c4c01ad8ecb6125dd6f0cfd98871685b5 SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d Yoga: eb938eb0ef4d510b93617486cf6cbe1ad6a94436 diff --git a/example/package.json b/example/package.json index 4bceadf3..7365338f 100644 --- a/example/package.json +++ b/example/package.json @@ -18,7 +18,9 @@ "react": "18.2.0", "react-native": "0.72.6", "react-native-get-random-values": "^1.9.0", - "react-native-macos": "^0.72.0" + "react-native-macos": "^0.72.0", + "react-native-webview": "^13.6.2", + "uuid": "^9.0.1" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/example/yarn.lock b/example/yarn.lock index c1493b30..6451e3d1 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -1215,7 +1215,7 @@ integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== "@invertase/react-native-apple-authentication@../": - version "2.2.2" + version "2.3.0" "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" @@ -3022,16 +3022,16 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== +escape-string-regexp@2.0.0, escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -3727,7 +3727,7 @@ internal-slot@^1.0.5: hasown "^2.0.0" side-channel "^1.0.4" -invariant@*, invariant@^2.2.4: +invariant@*, invariant@2.2.4, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -5564,6 +5564,14 @@ react-native-test-app@^2.5.32: semver "^7.3.5" uuid "^8.3.2" +react-native-webview@^13.6.2: + version "13.6.2" + resolved "https://registry.yarnpkg.com/react-native-webview/-/react-native-webview-13.6.2.tgz#0a9b18793e915add5b5dbdbf32509d7751b49167" + integrity sha512-QzhQ5JCU+Nf2W285DtvCZOVQy/MkJXMwNDYPZvOWQbAOgxJMSSO+BtqXTMA1UPugDsko6PxJ0TxSlUwIwJijDg== + dependencies: + escape-string-regexp "2.0.0" + invariant "2.2.4" + react-native@0.72.6: version "0.72.6" resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.72.6.tgz#9f8d090694907e2f83af22e115cc0e4a3d5fa626" @@ -6473,6 +6481,11 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + v8-to-istanbul@^9.0.1: version "9.1.3" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz#ea456604101cd18005ac2cae3cdd1aa058a6306b"