diff --git a/.gitignore b/.gitignore index 6dd8367..b0c9a06 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules +.expo/ .pnp.* .yarn/* !.yarn/patches diff --git a/package.json b/package.json index b9cfd5f..88846b6 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,9 @@ ], "scripts": { "start": "yarn workspace b2c-sample start", - "android": "yarn workspace b2c-sample start --android", - "ios": "yarn workspace b2c-sample start --ios", - "web": "yarn workspace b2c-sample start --web", + "android": "yarn workspace b2c-sample android", + "ios": "yarn workspace b2c-sample ios", + "web": "yarn workspace b2c-sample web", "test": "jest", "watch": "jest --watch", "compile": "yarn workspace ad-b2c-react-native compile", @@ -28,9 +28,13 @@ "@babel/preset-typescript": "^7.16.5", "@testing-library/jest-native": "^4.0.4", "@testing-library/react-native": "^9.0.0", + "@types/babel__core": "^7.1.19", "@types/jest": "^27.0.3", "babel-jest": "^27.4.5", "jest": "^27.4.7", "metro-react-native-babel-preset": "^0.66.2" + }, + "resolutions": { + "@types/react": "17.0.21" } } diff --git a/packages/b2c-sample/App.tsx b/packages/b2c-sample/App.tsx index 6501fca..c63aa87 100644 --- a/packages/b2c-sample/App.tsx +++ b/packages/b2c-sample/App.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React from "react"; import { Text } from "react-native"; import { NavigationContainer } from "@react-navigation/native"; import { createNativeStackNavigator } from "@react-navigation/native-stack"; @@ -29,6 +29,8 @@ export default function App() { passwordResetPolicy="B2C_1_PwdReset" profileEditPolicy="B2C_1_ProfleEdit" redirectURI={Linking.createURL("redirect")} + createNewTask={Constants.appOwnership === "expo"} + showInRecents={Constants.appOwnership === "expo"} > diff --git a/packages/b2c-sample/app.json b/packages/b2c-sample/app.json index a124c92..bbc7a73 100644 --- a/packages/b2c-sample/app.json +++ b/packages/b2c-sample/app.json @@ -29,7 +29,8 @@ "package": "ad.b2c.react.native.sample" }, "web": { - "favicon": "./assets/favicon.png" + "favicon": "./assets/favicon.png", + "build": { "babel": { "include": [ "ad-b2c-react-native" ] }} }, "sdkVersion": "45.0.0" }, diff --git a/packages/b2c-sample/package.json b/packages/b2c-sample/package.json index fe9dd24..4968108 100644 --- a/packages/b2c-sample/package.json +++ b/packages/b2c-sample/package.json @@ -3,10 +3,10 @@ "name": "b2c-sample", "version": "1.0.0", "scripts": { - "start": "expo start", - "android": "expo start --android", - "ios": "expo start --ios", - "web": "expo start --web", + "start": "expo start --https --localhost", + "android": "expo start -a --localhost", + "ios": "expo start -i --localhost", + "web": "expo start -w --https --localhost", "eject": "expo eject", "cpToBin": "shx cp ../../node_modules/.bin/react-native* ./node_modules/.bin/", "postinstall": "expo-yarn-workspaces postinstall & yarn cpToBin" @@ -19,16 +19,16 @@ ] }, "dependencies": { - "@react-navigation/native": "^6.0.6", - "@react-navigation/native-stack": "^6.2.5", + "@react-navigation/native": "^6.0.11", + "@react-navigation/native-stack": "^6.7.0", "ad-b2c-react-native": "2.0.0", "expo": "^45.0.0", "expo-constants": "~13.1.1", - "expo-dev-client": "~0.9.6", + "expo-dev-client": "~1.0.1", "expo-linking": "~3.1.0", "expo-modules-core": "~0.9.2", "expo-status-bar": "~1.3.0", - "expo-web-browser": "~10.2.0", + "expo-web-browser": "~10.2.1", "react": "17.0.2", "react-dom": "17.0.2", "react-native": "0.68.2", @@ -38,11 +38,15 @@ }, "devDependencies": { "@babel/core": "^7.12.9", + "@types/babel__core": "^7.1.19", "@types/react": "~17.0.21", "@types/react-native": "~0.67.6", - "expo-yarn-workspaces": "^1.6.0", + "expo-yarn-workspaces": "^2.0.0", "shx": "^0.3.4", "typescript": "~4.3.5" }, + "resolutions": { + "@types/react": "17.0.21" + }, "private": true } diff --git a/packages/b2c-sample/src/Protected.tsx b/packages/b2c-sample/src/Protected.tsx index fca95bf..43e9302 100644 --- a/packages/b2c-sample/src/Protected.tsx +++ b/packages/b2c-sample/src/Protected.tsx @@ -1,7 +1,9 @@ import { useNavigation } from "@react-navigation/core"; +import { useFocusEffect, useNavigationState } from "@react-navigation/native"; import { useAuth, useToken } from "ad-b2c-react-native"; -import React, { useEffect, useState } from "react"; -import { Button, Text, StyleSheet, View } from "react-native"; +import { WebBrowserAuthSessionResult } from "expo-web-browser"; +import React, { useCallback, useEffect, useState } from "react"; +import { Button, Text, StyleSheet, View, Platform } from "react-native"; import { RootStackNavigationProp, RouteNames } from "./navTypes"; const styles = StyleSheet.create({ @@ -17,25 +19,85 @@ export default function () { const { getTokensAsync, isLoading, error, isAuthentic } = useToken(); const { logOutAsync, editProfileAsync, resetPasswordAsync } = useAuth(); const nav = useNavigation(); - const [tokenRes, setTokenRes] = useState({ + const [newUrl, setNewUrl] = useState(""); + const [tokenRes, setTokenRes] = useState< + Awaited> + >({ access: "", id: "", expiresOn: 0, + url: "", + error: "", + isAuthentic: false, + }); + const routesLength = useNavigationState((state) => { + return state.routes.length; }); - useEffect(() => { - getTokensAsync().then((x) => { - setTokenRes(x); - }); - }, [isAuthentic]); + useFocusEffect( + useCallback(() => { + setResetPasswordError(""); + setNewUrl(""); + getTokensAsync().then((x) => { + if (x.error) { + nav.replace(RouteNames.home); + } + setTokenRes(x); + if (x.url) { + setNewUrl(x.url); + } + }); + }, [isAuthentic, routesLength]) + ); + + function browserResultHandler(x: WebBrowserAuthSessionResult) { + if (x.type === "success") { + setNewUrl(x.url); + } + } + const [resetPasswordError, setResetPasswordError] = useState(""); useEffect(() => { - if (error.includes("AADB2C90118")) { - setTimeout(() => { - resetPasswordAsync(); - }, 1); + if (newUrl) { + if (newUrl.includes("AADB2C90118")) { + setTimeout(() => { + resetPasswordAsync().catch((ex) => { + setResetPasswordError(ex.toString()); + }); + }, 1); + } + + if (Platform.OS === "web") { + const url = new URL(newUrl); + const searchParams = url.searchParams; + const code = searchParams.get("code"); + if (code) { + nav.navigate(RouteNames.redirect, { + code: code, + state: searchParams.get("state") || "", + error: "", + error_description: "", + }); + } + } } - }, [error]); + }, [newUrl]); + + if (resetPasswordError) { + return ( + + Please manually press reset password +