3

I am trying to integrate Coinbase oauth2 to my react-native expo app. I have followed the below guide: https://docs.expo.dev/guides/authentication/#coinbase

Below is my app.json

{
    "expo": {
      "name": "My App",
      "slug": "my-app",
      "privacy": "public",
      "platforms": [
        "ios",
        "android",
        "web"
      ],
      "version": "1.1.13",
      "facebookScheme": "fbxxxxxxxxxxxx",
      "facebookAppId": "xxxxxxxxxxxxxxxxxxxx",
      "facebookDisplayName": "Ubuntu",
      "orientation": "portrait",
      "icon": "./assets/app_logo.png",
      "splash": {
        "image": "./assets/splash.png",
        "resizeMode": "cover",
        "backgroundColor": "#ffffff"
      },
      "updates": {
        "fallbackToCacheTimeout": 0
      },
      "assetBundlePatterns": [
        "**/*"
      ],
      "ios": {
        "supportsTablet": true,
        "bundleIdentifier": "com.package.app",
        "infoPlist": {
          "NSCameraUsageDescription": "This app uses the camera to upload documents."
        },
        "googleServicesFile": "./GoogleService-Info.plist",
        "usesIcloudStorage": true
      },
      "android": {
        "package": "com.package.app",
        "useNextNotificationsApi": true
      },
      "web": {
        "build": {
          "babel": {
            "include": [
              "static-container"
            ]
          }
        }
      },
      "scheme": "com.package.app"
    }
  }

App.native.js

import {
    exchangeCodeAsync,
    makeRedirectUri,
    TokenResponse,
    useAuthRequest
  } from "expo-auth-session";
  import * as WebBrowser from "expo-web-browser";
  import * as React from "react";
  import { Button, View } from "react-native";
  
  WebBrowser.maybeCompleteAuthSession();
  
  // Endpoint
  const discovery = {
    authorizationEndpoint: "https://www.coinbase.com/oauth/authorize",
    tokenEndpoint: "https://api.coinbase.com/oauth/token",
    revocationEndpoint: "https://api.coinbase.com/oauth/revoke",
  };
  
  const redirectUri = makeRedirectUri({
    // scheme: 'com.package.app',
    // path: 'redirect',
    native: 'com.package.app://redirect',
    useProxy: false
  });
  
  const CLIENT_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
  const CLIENT_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
  
  export default function App() {
    const [request, response, promptAsync] = useAuthRequest(
      {
        clientId: CLIENT_ID,
        scopes: ["wallet:accounts:read"],
        redirectUri    // -> tried this as well redirectUri: 'urn:ietf:wg:oauth:2.0:oob'
      },
      discovery
    );
    const {
      // The token will be auto exchanged after auth completes.
      token,
      exchangeError,
      } = useAutoExchange(
      response?.type === "success" ? response.params.code : null
      );
  
    React.useEffect(() => {
      if (token) {
        console.log("My Token:", token.accessToken);
        }
    }, [token]);
  
    return (
      <View style={{ marginTop: 300,}}>
        <Button
        disabled={!request}
        title="Login"
        onPress={() => {
          promptAsync();
          }}
        />
      </View>
    );
  }
  
  // A hook to automatically exchange the auth token for an access token.
  // this should be performed in a server and not here in the application.
  // For educational purposes only:
  function useAutoExchange(code) {
    const [state, setState] = React.useReducer(
      (state, action) => ({ ...state, ...action }),
      { token: null, exchangeError: null }
    );
    const isMounted = useMounted();
  
    React.useEffect(() => {
      if (!code) {
        setState({ token: null, exchangeError: null });
        return;
      }
  
      exchangeCodeAsync(
        {
          clientId: CLIENT_ID,
          clientSecret: CLIENT_SECRET,
          code,
          redirectUri,
        },
        discovery
      )
        .then((token) => {
          if (isMounted.current) {
            setState({ token, exchangeError: null });
          }
        })
        .catch((exchangeError) => {
          if (isMounted.current) {
            setState({ exchangeError, token: null });
          }
        });
    }, [code]);
  
    return state;
  }
  
  function useMounted() {
    const isMounted = React.useRef(true);
    React.useEffect(() => {
      return () => {
        isMounted.current = false;
      };
    }, []);
    return isMounted;
  }

I have added com.package.app to the permitted redirect URL as well.

Does anyone help me find why am I still getting 'The redirect URI included is not valid'?

Expo SDK version: 43

Developing platform: Windows

Packages used:

"expo-auth-session": "~3.4.2"
"expo-web-browser": "~10.0.3"
"react": "17.0.0"
"react-native": "0.64.3"

Thank you.

Pankti Shah
  • 337
  • 6
  • 20

0 Answers0