Necessary adjustments when running react app on amplify server instead of local machine - reactjs

I developed a reactjs web app which I want to make accessible via federated login (i.e. logging in with Google credentials). Therefor I created an Amplify project and followed the instructions of the aws tutorial for Social sign-in (OAuth).
It all works fine when I run the app locally. In my amplify project I tried to include the frontend code by linking it to my github repo. I was able to deploy the app successfully before implementing federated login. Once I did that - after logging in to my google account - I get a redirection error. It says "Localhost denied the connection". How can I change the settings such that I get redirected to the correct url? Below you can see the aws-export.js. I tried changing redirectSignin/Signout (comments) I still get same error though. How can I make it work?
const awsmobile = {
"aws_project_region": "us-east-2",
"aws_cognito_identity_pool_id": "us-east-2:203de857-b72c-41e1-a349-e8689e1d7b88",
"aws_cognito_region": "us-east-2",
"aws_user_pools_id": "us-east-2_7Hqae0xMa",
"aws_user_pools_web_client_id": "fmb3jgl1ojmgs9655i2cona66",
"oauth": {
"domain": "cvhfederated23782f2e-23782f2e-dev.auth.us-east-2.amazoncognito.com",
// "domain": "cvhfederated23782f2e-23782f2e-final.auth.us-east-2.amazoncognito.com",
"scope": [
"phone",
"email",
"openid",
"profile",
"aws.cognito.signin.user.admin"
],
"redirectSignIn": "http://localhost:3000/",
"redirectSignOut": "http://localhost:3000/",
// "redirectSignIn": "https://final.dw4tcn2vagyv6.amplifyapp.com/",
// "redirectSignOut": "https://final.dw4tcn2vagyv6.amplifyapp.com/",
"responseType": "code"
},
"federationTarget": "COGNITO_USER_POOLS"
};
export default awsmobile;

I've run into this issue in the past and opted to update the configuration values at runtime.
import awsconfig from '../aws-exports';
awsconfig.oauth.redirectSignIn = `${window.location.origin}/`;
awsconfig.oauth.redirectSignOut = `${window.location.origin}/`;
Amplify.configure(awsconfig);

Refer to https://docs.amplify.aws/lib/auth/social/q/platform/js#amazon-cognito-user-pool-setup
Basically, this kind of configuration needs to be handled in code. Put in both the localhost and production signin/signout redirects separated by a comma (,).
Then, after importing your aws-exports, split the redirect values e.g., awsConfig.oauth.redirectSignIn.split(",")
Finally, use window.location.hostname to conditionally choose the correct redirect urls e.g.,
const isLocalhost = Boolean(
window.location.hostname === "localhost" ||
// [::1] is the IPv6 localhost address.
window.location.hostname === "[::1]" ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);

Related

How to configure a react capacitor app running on mobile by usb to make http request to sendbird as localhost instead of its IP address?

I have a React webapp that I have converted it to native app using Capacitor. For live reloading, I had to edit capacitor.config.json as follows:
const config: CapacitorConfig = {
//
webDir: 'build',
bundledWebRuntime: false,
server: {
url: 'http://192.XXX.XXX:3000',
cleartext: true
},
};
This works just fine until the app makes a request to sendbird for initialization. I get the error message: 'SendBirdCall needs https connection, except for 'localhost' or '127.0.0.1'. I tried to setup an express https server but failed. Later I created two channels using ngrok - one for the server and one for the app. The sendbird request was successful but the graphql websocket was failing as ngrok does not support websocket links, also tried a tcp link but it failed as well.
I have another app that I created using the Sendbird React Native Quickstart project and I did not need to do any configuration for that. What could be done in order to make sendbird request using localhost from mobile connected via usb while also being able to have a ws connection?
Try to change the url:
const config: CapacitorConfig = {
...
server: {
url: 'http://localhost:3000',
cleartext: true
},
};
And after connecting a physical device execute the following:
cd $ANDROID_HOME/platform-tools
./adb reverse tcp:3000 tcp:3000
Where $ANDROID_HOME is the Android SDK directory.

Google Oauth2 giving "redirect_uri_mismatch" error in production when redirect uri setup correctly

I have google oauth set up in a react project. It was working fine in development, locally. Once i promoted the oauth client to "production" and modified the JS origin and redirect URIs to production values, yet it gives this error
Error 400: redirect_uri_mismatch
You can't sign in to this app because it doesn't comply with Google's
OAuth 2.0 policy.
If you're the app developer, register the redirect URI in the Google
Cloud Console. Request details:
redirect_uri=http://super-server.herokuapp.com/v1/auth/google/callback
Related developer documentation
These are the authorized redirect URIs within google cloud console:
https://super-server.herokuapp.com/v1/auth/google/callback
https://super-server.herokuapp.com/v1/auth/google/callback/
https://www.super-server.herokuapp.com/v1/auth/google/callback
https://www.super-server.herokuapp.com/v1/auth/google/callback/
As you can see, there are no authorized uri's with an HTTP schema. Theyre not even allowed in production mode. So im not sure where this is coming from, because the server is HTTPS
server:
Any advice?
the redirect uri must exactly match the one you are adding to Google developer console
If you check the error message your app is running with
http://super-server.herokuapp.com/v1/auth/google/callback
All the ones you have added are https
May i suggest fixing your app so that it runs https. I dont think that you will be able to add http as a production redirect uri endpoint.
documentation
Obtaining OAuth 2.0 access tokens
authorization-errors-redirect-uri-mismatch
Node.js
I dont know enough about react.js but with node you should be able to do something like this
const http = require('http');
const https = require('https');
In my case (MERN + passport.js), i had a configuration that looked like:
const googleOptions = {
clientID: config.google.id,
clientSecret: config.google.secret,
passReqToCallback: true,
callbackURL: '/v1/auth/google/callback',
scope: ['profile', 'email']
};
Even though the server, the client && the configuration of the oauth client within google api console were all in production with everything setup for https, for some reason, the callbackURL kept firing with google oauth as http://my-domain.com/v1/auth/google/callback
so this fix may be hacky, but it did fix my oauth issues:
//Google Strategy
const googleOptions = {
clientID: config.google.id,
clientSecret: config.google.secret,
passReqToCallback: true,
callbackURL: config.environment == 'production' ? 'https://super-server.herokuapp.com/v1/auth/google/callback' : '/v1/auth/google/callback',
scope: ['profile', 'email']
};
Looks like the redirect_uri on the client side (React side) is set to http://super-server.herokuapp.com/v1/auth/google/callback
Change the redirect_uri on the client side from (http) http://super-server.herokuapp.com/v1/auth/google/callback to (https) https://super-server.herokuapp.com/v1/auth/google/callback.

How to change the `frontend_domain` port in `GRAPHQL_AUTH` in the verification mail?

I'm working on a Docker-Django-Graphene-React stack where Django is the backend which receive GraphQL queries through Graphene from React which acts as the frontend. Everything runs in docker containers. Django on port 8000 and React on 3000.
I'm currently working on the authentication with the python's django-graqhql-auth package.
When a user register itself on the frontend form, the register mutation is correctly made to the backend and the account is created.
A mail is sent at the same time to the user's registered mail address containing a verification link with a token that must be used with the veryifyToken mutation in order to flag the account as verified.
Here is an example of the link:
http://localhost:8000/activate/eyJ1c2VybmFtZSI6IkpvaG5zb2ZuZiIsImFjdGlvbiI6ImFjdGl2YXRpb24ifQ:1mQr0R:Wh25LJ6A1PRVCQT730kXXIk4i2QJgz1a4aNDe7RoZM0
The problem is that the port on the link is 8000, which redirects to the backend (Django). I would like to redirect the user on port 3000 which is the frontend (React).
According to the documentation, I should be able to change the frontend_domain which I did. I also changed the path and the protocol values to see if it works:
Here is what I put in my backend's settings.py file:
GRAPHQL_AUTH = {
"EMAIL_TEMPLATE_VARIABLES": {
"protocol": "https",
"frontend_domain": "localhost:3000",
"path": "verify",
}
}
And I end up with this link:
https://localhost:8000/verify/eyJ1c2VybmFtZSI6IkpvaG5zZmdvZmdzbmRmIiwiYWN0aW9uIjoiYWN0aXZhdGlvbiJ9:1mQrIr:2o818drqPP8oVTE4E6fg2F6vMu2zITOjkF96z5K1whY
The protocol and path variables were correctly changed but not the frontend_domain. The problem is that I cannot redirect the user directly to the frontend.
Is there a way to fix this? Or do I have to create a route on the backend which will redirect the user to the frontend with the token so that I can use the verifyToken mutation?
I might be answering this late, but replace frontend_domain with domain and it will work.
you just have to update to latest version.
pip install --upgrade django-graphql-auth
I noticed that you used in protocol: "https" , but should probably be protocol: "http".
I'm in the same project using Django and Graphql Auth and for me worked to send the email to the frontend to Next.js by using protocol: "http".
GRAPHQL_AUTH = {
"EMAIL_TEMPLATE_VARIABLES": {
"protocol": "http",
"frontend_domain": "localhost:3000",
"path": "verify",
}
}

How can I implement Firebase authentication in a Capacitor app on Android and iOS?

I'm using Capacitor to create Android and iOS versions of my React webapp and now I'm trying to get firebase authentication working on Android and iOS.
I have allowed navigation inside the app to all domains and am using the redirect strategy for Firebase auth.
I have enabled the required authentication methods and they work fine in the web version.
The problem: instead of showing the authentication website, I only get a blank screen.
For reference: the code used for authentication:
const auth = firebase.auth()
const provider = new firebase.auth.GoogleAuthProvider()
auth.signInWithRedirect(provider)
And the capacitor.config.json:
{
"appId": "APP_ID",
"appName": "APP_NAME",
"bundledWebRuntime": false,
"npmClient": "yarn",
"webDir": "build",
"cordova": {},
"server": {
"hostname": "HOSTNAME_KNOWN_TO_FIREBASE",
"allowNavigation": ["*"]
},
"android": {
"allowMixedContent": true
}
}
Am I missing something? Any tips would be greatly appreciated!
Web-based firebase social authentication won't work with the capacitor. It is because the app tries to open the popup or redirect and it fails. In the case of phone authentication, it fails because the window object is not available in the app which is needed for ReCaptcha.
In order to authenticate in the mobile app, you will have to use a capacitor plugin.
capacitor-firebase-auth
Any chance you are getting an error 400 on your console? Likely you need to enable permissions for your sign-in provider (Google).
To do this, go to Firebase, click on Authentication, then Sign-in method, and change the status of your selected provider to be "Enabled".
Sign-in Provider Permissions

After deploying React/Express app to Heroku unable to start passport.js flow (page reloads instead) [duplicate]

I'm building a node + express server, with create-react-app to the frontend.
I used passportjs for auth routes handling, and all the stuff totally working on localhost ( backend on port 5000 and frontend on port 3000, with a proxy ).
When I deploy to Heroku, seems like the server can't recognize my auth routes and so heroku serve up static index.html.
If I test my APIs with Postman all seems to work ( I can see the html page for google oauth ), but with an anchor tag in my react app or manually writing the endpoint in the url, I can see only the same page reloading.
My server index.js:
const express = require('express')
const passport = require('passport')
const mongoose = require('mongoose')
const path = require('path')
// KEYS
const keys = require('./config/keys')
// MONGOOSE MODELS
require('./models/User')
mongoose.connect(keys.mongoURI)
// PASSPORT SETUP
require('./config/passport')
// CREATE THE SERVER
const app = express()
// EXTERNAL MIDDLEWARES
require('./middlewares/external')(app)
// ROUTE HANDLERS
require('./routes/authRoutes')(app)
// PRODUCTION SETUP
if (process.env.NODE_ENV === 'production') {
// express serve up production assets ( main.js, main.css )
app.use(express.static('client/build'))
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'))
})
}
// START THE SERVER
const PORT = process.env.PORT || 5000
app.listen(PORT)
Flow:
LOCALHOST:
react app starts -> I click 'Google Login' -> GET request to "/auth/google" -> google oauth flow -> redirect to "/" and my react app reappears, the user is logged in.
HEROKU:
react app on my-app.herokuapp.com/ -> click on "Google Login" -> the page reloads, nothing happens. the user is not logged in.
Please guys, help me.
Thanks
This is a result of the service worker being installed by default to make your app a Progressive Web App
To determine if this is an issue for you, test your heroku production mode app in incognito mode. The request for /auth/google should now reach the server and behave as it does in development.
Once you determine it is an issue, you can remove the
import registerServiceWorker from "./registerServiceWorker";
from your /client/src/index.js file.
You browser cache may already contain an installed service worker so you may have to
clear browser cache on a user browsers
uninstall the server worker programmatically
import { unregister } from './registerServiceWorker';
....
unregister();
I had the same issues with same symptoms exactly.
For me the cause was a typo in the keys: in server/config/prod.js I had a line reading cookieKey: process.env.COOKIE_KEY but in Heroku Config Variables that variable was named cookieKey. Renaming it to COOKIE_KEY inside Heroku solved the issue.
If you've followed the Stephen Grider tutorial one thing I'm wondering: Is your passport.js file in config or services? I see you've written in index.js: require('./config/passport')
whereas mine in index.js is require('./services/passport')
may not be your solution to the google oauth flow hanging in production but may help.

Resources