aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.12k forks source link

Hub.listen in react native doesn't work #8141

Closed DeniferSantiago closed 3 years ago

DeniferSantiago commented 3 years ago

Before opening, please confirm:

JavaScript Framework

React Native

Amplify APIs

Authentication, GraphQL API, Storage

Amplify Categories

auth, storage, api

Environment information

``` System: OS: Windows 10 10.0.19041 CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz Memory: 6.77 GB / 15.88 GB Binaries: Node: 14.1.0 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.10 - ~\AppData\Roaming\npm\yarn.CMD npm: 6.14.4 - C:\Program Files\nodejs\npm.CMD Watchman: 20210110.135312.0 - c:\Users\denif\AppData\Local\watchman\watchman.EXE Browsers: Chrome: 89.0.4389.128 Edge: Spartan (44.19041.906.0), Chromium (90.0.818.42) Internet Explorer: 11.0.19041.1 npmPackages: @babel/core: ^7.12.9 => 7.13.15 @babel/runtime: ^7.12.5 => 7.13.10 @gorhom/bottom-sheet: ^2.0.7 => 2.3.0 @react-native-community/async-storage: ^1.11.0 => 1.12.1 @react-native-community/datetimepicker: ^3.0.2 => 3.4.3 @react-native-community/eslint-config: ^2.0.0 => 2.0.0 @react-native-community/masked-view: ^0.1.10 => 0.1.10 @react-native-community/netinfo: ^6.0.0 => 6.0.0 @react-navigation/bottom-tabs: ^5.5.2 => 5.11.9 @react-navigation/native: ^5.7.3 => 5.9.4 @react-navigation/stack: ^5.9.0 => 5.14.4 HelloWorld: 0.0.1 amazon-cognito-identity-js: ^4.6.0 => 4.6.0 aws-amplify: ^3.3.26 => 3.3.26 aws-amplify-react-native: ^4.3.2 => 4.3.2 babel-jest: ^26.6.3 => 26.6.3 eslint: 7.14.0 => 7.14.0 hermes-inspector-msggen: 1.0.0 jest: ^26.6.3 => 26.6.3 metro-react-native-babel-preset: ^0.64.0 => 0.64.0 moment: ^2.29.1 => 2.29.1 react: 17.0.1 => 17.0.1 react-native: 0.64.0 => 0.64.0 react-native-animatable: ^1.3.3 => 1.3.3 react-native-auto-cacheable-image: ^1.1.4 => 1.1.4 react-native-calendars: ^1.403.0 => 1.1255.0 react-native-confirmation-code-input: ^1.0.4 => 1.0.4 react-native-controlled-mentions: github:DeniferSantiago/react-native-controlled-mentions#Deploy => 2.2.5 react-native-draggable-flatlist: ^2.5.4 => 2.6.1 react-native-fs: ^2.16.6 => 2.17.0 react-native-geolocation-service: ^5.2.0 => 5.2.0 react-native-gesture-handler: ^1.6.1 => 1.10.3 react-native-get-random-values: ^1.7.0 => 1.7.0 react-native-haptic-feedback: ^1.11.0 => 1.11.0 react-native-image-picker: ^3.2.1 => 3.3.2 react-native-inappbrowser-reborn: ^3.5.1 => 3.5.1 react-native-indicators: ^0.17.0 => 0.17.0 react-native-maps: 0.27.1 => 0.27.1 react-native-modal-datetime-picker: ^9.1.0 => 9.2.0 react-native-paper: ^4.7.2 => 4.7.2 react-native-permissions: ^3.0.0 => 3.0.1 react-native-photo-editor: ^1.0.10 => 1.0.10 react-native-reanimated: ^1.13.2 => 1.13.3 react-native-redash: ^15.1.0 => 15.11.1 (14.2.4) react-native-safe-area-context: ^3.0.5 => 3.2.0 react-native-screens: ^2.16.1 => 2.18.1 react-native-splash-screen: ^3.2.0 => 3.2.0 react-native-status-bar-height: ^2.6.0 => 2.6.0 react-native-svg: ^12.1.0 => 12.1.0 react-native-vector-icons: ^7.1.0 => 7.1.0 react-redux: ^7.2.3 => 7.2.3 react-test-renderer: 17.0.1 => 17.0.1 redux: ^4.0.5 => 4.0.5 uuid: ^8.3.2 => 8.3.2 (3.4.0, 3.3.2) npmGlobalPackages: @aws-amplify/cli: 4.49.0 @vue/cli: 4.3.1 expo-cli: 4.0.17 typescript: 4.2.3 yarn: 1.22.10 ```

Describe the bug

I am implementing login with google and facebook in a React-Native application. I want to use a custom domain and also use my own login layout, etc.

I use InAppBrowser and everything is well configured in terms of Intents, redirect paths, etc. Since when I execute Auth.federatedSignIn({provider: "Google"}) it opens me correctly and allows me to choose an account, then I see in cognito that the account has been created (if it's a new account) and my application takes the focus when InAppBrowser closes but Hub.listen does not return any information

Expected behavior

Be able to get response from Hub.listen after having logged in with oauth configured with a domain of your own

Reproduction steps

use amplify as described above

Code Snippet

//index.js
import { Amplify } from "aws-amplify";
import InAppBrowser from "react-native-inappbrowser-reborn";
import { appData } from "./src/Helpers/Consts";
const urlOpener = async (url, redirectUrl) => {
    const available = await InAppBrowser.isAvailable();
    if (!available) {
        Linking.openURL(url);
    } else {
        const { type, url: newUrl } = await InAppBrowser.openAuth(
            url,
            redirectUrl,
            {
                showTitle: false,
                toolbarColor: "#00CCCD",
                enableUrlBarHiding: true,
                enableDefaultShare: false,
                ephemeralWebSession: false
            }
        );
        if (type === "success") {
            Linking.openURL(newUrl);
        }
    }
};
const newConfig = {
    ...config,
    oauth: { ...config.oauth, urlOpener, domain: appData.authDomain }
};
Amplify.configure(newConfig);

//---------------------------------------------------------------------------------------------------
//app.js
import React, { useState, useEffect } from "react";
import { StackAuth } from "./src/Screen/StackApp/StackAuth";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { Hub } from "aws-amplify";
const App = () => {
    useEffect(() => {
        Hub.listen("auth", ({ payload }) => {
            console.log("Hub", payload);
            const { event, data } = payload;
            switch (event) {
                case "signIn":
                    break;
                case "signOut":
                    break;
                case "customOAuthState":
                default:
                    return;
            }
        });
    }, []);
    return (
        <SafeAreaProvider>
            <StackAuth />
            <Alerts />
        </SafeAreaProvider>
    );
};
export default App;

//----------------------------------------------------------------------------------------------
//StackAuth.js
import React, { useEffect, useState } from "react";
import {
    CardStyleInterpolators,
    createStackNavigator
} from "@react-navigation/stack";
import { NavigationContainer } from "@react-navigation/native";
import { TabRoot } from "../TabScreens/TabRoot";
import { StatusBar, StyleSheet, useColorScheme, View } from "react-native";
import { Intro } from "./Intro";
import { asKeys } from "../../Helpers/Keys";
import SignIn from "./SignIn";
import { SignUpRoot } from "../StackSignUp/SignUpRoot";
import { useDispatch } from "react-redux";
import { theme, darkTheme } from "../../Helpers/Theme";
import { useTheme } from "react-native-paper";
import { StackApp } from "../../Helpers/Consts";
import { ForgotPasswordRoot } from "../StackForgotPassword/ForgotPasswordRoot";
import { BarIndicator } from "react-native-indicators";
import { AppActions } from "../../Actions/AppActions";
import { useAuthentication } from "../../Hooks/useAuthentication";
const Stack = createStackNavigator();
var styles = StyleSheet.create({
    container: {
        flex: 1
    },
    containerLoader: {
        flex: 1,
        justifyContent: "center",
        alignItems: "center"
    }
});
export const StackAuth = () => {
    const { colors } = useTheme();
    const isDark = useColorScheme() === "dark";
    const {
        loading,
        logged
    } = useAuthentication();
    const dispatch = useDispatch();
    useEffect(() => {
        dispatch(AppActions.LoadCache());
    }, [dispatch]);
    if (loading) {
        return (
            <View
                style={[
                    styles.containerLoader,
                    { backgroundColor: colors.primary }
                ]}>
                <StatusBar
                    backgroundColor={colors.primary}
                    barStyle={isDark ? "light-content" : "dark-content"}
                />
                <BarIndicator count={4} color={colors.white} size={70} />
            </View>
        );
    }
    return (
        <View style={[styles.container, { backgroundColor: colors.primary }]}>
            <NavigationContainer theme={isDark ? darkTheme : theme}>
                <Stack.Navigator
                    headerMode="none"
                    screenOptions={{
                        gestureEnabled: false,
                        cardStyleInterpolator:
                            CardStyleInterpolators.forScaleFromCenterAndroid
                    }}>
                    {logged ? (
                        <Stack.Screen
                                name={StackApp.TabScreens}
                                component={TabRoot}
                        />
                    ) : (
                        <>
                            <Stack.Screen
                                name={StackApp.SignIn}
                                component={SignIn}
                            />
                            <Stack.Screen
                                name={StackApp.SignUp}
                                component={SignUpRoot}
                            />
                            <Stack.Screen
                                name={StackApp.ForgotPassword}
                                component={ForgotPasswordRoot}
                            />
                        </>
                    )}
                </Stack.Navigator>
            </NavigationContainer>
        </View>
    );
};

//---------------------------------------------------------------------------------------------------
//SignIn.js
import React, { useContext, useState } from "react";
import { StatusBar, TouchableOpacity } from "react-native";
import { View, Image } from "react-native";
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
import * as Animatable from "react-native-animatable";
import { AuthActions } from "../../Actions/AuthActions";
import { Auth } from "aws-amplify";
import { Button, Text, useTheme } from "react-native-paper";
import { getStyles } from "./AuthStyles";
import { StackApp } from "../../Helpers/Consts";
import { GetUser } from "../../Services/User";
import { UserActions } from "../../Actions/UserActions";
import { Resources } from "../../Helpers/Resources";
const SignIn = ({ navigation, SetUser, SetUserData }) => {
    const theme = useTheme();
    var styles = getStyles(theme);
    const [data, setData] = useState({
        userName: "user1",
        password: "testpassword123"
    });
    const [flags, setFlags] = useState({
        loading: false
    });
    const onSignIn = async () => {
        setFlags({ ...flags, loading: true });
        try {
            if (data.password && data.userName) {
                const response = await Auth.signIn(
                    data.userName,
                    data.password
                );
                const userDb = await GetUser(response.attributes.sub);
                SetUserData(userDb);
                SetUser(response);
            }
        } catch (e) {
            console.log(e);
        } finally {
            setFlags({ ...flags, loading: false });
        }
    };
    return (
        <View style={styles.stepContainer}>
            <Animatable.View
                animation="fadeInUpBig"
                useNativeDriver
                style={styles.header}>
                <Text style={styles.stepTextHeader}>¡Bienvenido a MyApp!</Text>
            </Animatable.View>
            <Animatable.View
                animation="fadeInUpBig"
                useNativeDriver
                style={styles.footer}>
                 {//hide my inputs for brevity}
                <Button
                    mode="text"
                    style={styles.forgotPasswordContainer}
                    color={theme.colors.secondary}
                    compact
                    contentStyle={styles.forgotPasswordContent}
                    labelStyle={styles.forgotPasswordText}
                    onPress={() => navigation.navigate(StackApp.ForgotPassword)}
                    uppercase={false}>
                    Olvidé mi contraseña
                </Button>
                <View style={styles.buttonContainer}>
                    <Button
                        mode="contained"
                        onPress={onSignIn}
                        loading={flags.loading}
                        labelStyle={styles.textBtn}
                        disabled={
                            !data.userName || !data.password || flags.loading
                        }>
                        Iniciar Sesión
                    </Button>
                </View>
                <Text style={styles.continueText}>O Continúa con</Text>
                <View style={styles.column}>
                    <Button
                        icon={() => (
                            <MaterialCommunityIcons
                                name="facebook"
                                size={theme.size.icons}
                                color={theme.colors.white}
                            />
                        )}
                        mode="contained"
                        onPress={() => {
                            Auth.federatedSignIn({ provider: "Facebook" })
                                .then(a => console.log("then", a))
                                .catch(e => console.log("catch", e));
                        }}
                        compact
                        labelStyle={styles.fbText}
                        color="#3b5998">
                        Facebook
                    </Button>
                    <Button
                        mode="outlined"
                        icon={() => (
                            <Image
                                style={styles.googleIcon}
                                source={{ uri: Resources.icons.Google }}
                            />
                        )}
                        compact
                        style={styles.googleBtn}
                        onPress={() => {
                            Auth.federatedSignIn({ provider: "Google" })
                                .then(a => console.log("then", a))
                                .catch(e => console.log("catch", e));
                        }}
                        labelStyle={styles.googleText}>
                        Google
                    </Button>
                </View>
                <View style={styles.registerButtonContainer}>
                    <Button
                        onPress={() => navigation.navigate(StackApp.SignUp)}
                        mode="outlined"
                        color={theme.colors.secondary}
                        style={styles.buttonRegisterOutlined}
                        labelStyle={styles.fontBig}>
                        Registrarse
                    </Button>
                </View>
            </Animatable.View>
        </View>
    );
};
export default SignIn;

Log output

``` // Put your logs below this line ```

aws-exports.js

const awsmobile = {
    "aws_project_region": "us-east-1",
    "aws_cognito_identity_pool_id": "us-east-1:00000000-0000-0000-0000-000000000000",
    "aws_cognito_region": "us-east-1",
    "aws_user_pools_id": "us-east-1_AAAAAAA0",
    "aws_user_pools_web_client_id": "aa0a0a0a00aa00a0a0a0a",
    "oauth": {
        "domain": "mydomain-dev.auth.us-east-1.amazoncognito.com",
        "scope": [
            "phone",
            "email",
            "openid",
            "profile"
        ],
        "redirectSignIn": "https://auth.mydomain.com/signin/",
        "redirectSignOut": "https://auth.mydomain.com/signout/",
        "responseType": "token"
    },
    "federationTarget": "COGNITO_USER_POOLS",
    "aws_appsync_graphqlEndpoint": "https://a0a0a0a0aaaaa0a00aa00a.appsync-api.us-east-1.amazonaws.com/graphql",
    "aws_appsync_region": "us-east-1",
    "aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS",
    "aws_appsync_apiKey": "aa0-aaa0a0000aa0a0a0a00a",
    "aws_user_files_s3_bucket": "namea0a0a0aa0000a0a0aaa0-dev",
    "aws_user_files_s3_bucket_region": "us-east-1"
};

export default awsmobile;

Manual configuration

No response

Additional configuration

No response

Mobile Device

LG V50

Mobile Operating System

Android 10

Mobile Browser

Chrome

Mobile Browser Version

No response

Additional information and screenshots

No response

DeniferSantiago commented 3 years ago

I fixed the error, changing redirectSignIn and redirectSignOut to application schemas (myapp://) instead of links. So in AndroidManifest and Info.plist add myapp:// as Intents

github-actions[bot] commented 2 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.