I'm having problems authenticating through Google OAuth api on a website hosted on Heroku.
Everything works in my localhost.
This is my configuration on google dev console.
It works on localhost.
It doesn’t work online. This is the error I got.
I've tried using http as suggested in some old thread on stack overflow, but it didn't work.
I've tried changing the allowed redirect url in the google console to include also the port, and in that case it worked.
The problem is that I don't know which port Heroku is going to use every time the server restart.
Do you know any workaround to a such situation?
Well, at the end I didn't figure out how to configure properly Google... so what I did (and it worked) was to remove the port from the return url:
const strategyConfig = {
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_SECRET_ID,
callbackURL: process.env.NODE_ENV === "production"
? `${HOST}/${RETURN_URL}`
: `${HOST}:${PORT}/${RETURN_URL}`,
passReqToCallback: true,
};
Related
I have a nextjs app I have deployed on vercel. It is paired with a nestjs back-end which is deployed in heroku.
I implemented login via github and, while developing the app, I used the following code to set a jwt header after the user successfully authenticated:
#Get('redirect')
#UseGuards(AuthGuard('github'))
async githubAuthRedirect(#Req() req, #Res() res) {
const accessToken = await this.authService.generateJWT(req.user);
res.cookie('jwt', accessToken);
res.redirect(`http://localhost:3000/dashboard`);
}
That is the endpoint github calls once the user has approved access to their account.
That works while I run everything on localhost, but once I deployed the front-end app to vercel, the back-end app to heroku (and configured a CNAME alias for my api) then it doesn't work.
My server gets the request from github and the user is effectively redirected to the dashboard, but no cookie is set.
Am I doing something wrong? did I miss some vercel/nextjs configuration?
After some digging around and testing all the possible configurations, turns out this is not a problem with next or with nest (or with heroku or vercel).
Cookies are by default set on the same domain which your request originates from, including sub domains.
In my case this meant, my API was responding from api.[DOMAIN].com and the cookie was not reaching [DOMAIN].com.
When setting the cookie I had to explicitely pass the parent domain:
res.cookie('jwt', accessToken, {
domain: 'scripthunt.sh',
sameSite: 'none',
secure: req.secure || req.headers['x-forwarded-proto'] === 'https',
});
You might need to change other settings on express like:
app.enable('trust proxy');
app.enableCors({
origin: 'https://[MY DOMAIN].com',
credentials: true,
});
Which might also be necessary for Heroku, not sure, all I know is my app now correctly sets the cookie.
Cheers!
I have a question regarding Providers.
I'm using Strapi in the docker with Nginx reverse proxy and I set up google provider and service.js I added URL: env("", "https://my-link.com/api"),
in the beginning, everything was working fine till I clear the browser cache. Now I'm getting an error
Grant Missing session or misconfigured provider
so when I call /connect/google/callback its fail with 302
On the Strapi website, I found this but not much clear how to debug the issue
Grant: missing session or misconfigured provider: It may be due to many things.
The redirect URL can't be built: Make sure you have set the backend URL in config/server.js: Setting up the server URL
A session/cookie/cache problem: You can try again in a private tab.
The incorrect use of a domain with ngrok: Check your urls and make sure that you use the ngrok URL instead of http://localhost:1337. Don't forget to check the backend url set in the example app at src/config.js.
Thanks in advance.
Here is my configuration:
SERVER
Laravel 8 application that uses Sanctum to provide access to REST API. It is configured to run on http://b8/
CLIENT
A separate Vue CLI 3.0 SPA that connects to the API using session-based cookie authentication method. I have configured Vue CLI Serve to run it at http://app.b8/.
PROBLEM
Chrome does not allow Set-Cookie operation even when both server and client are on the same domain. After going through several posts and articles, I have successfully run it in Postman, but the real Vue application that runs in the browser can't set Sanctum cookie and thus cannot login.
Here is my configuration:
.env
SESSION_DRIVER=cookie
SESSION_DOMAIN=.b8
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:8080,127.0.0.1,127.0.0.1:8000,::1,b8,app.b8,app.b8:8080
vue.config.js
...
devServer: {
proxy: "http://b8/api/v1",
host: "app.b8"
},
Login function in Vue application
async login(context, credentials) {
axios.get('http://b8/sanctum/csrf-cookie').then(response => {
axios.post('http://b8/login', credentials).then(response2 => {
//successfully logged in.
});
});
},
Error msg
The outer call for /sanctum/csrf-cookie route returns successfully and brings Sanctum cookie. However, Chrome thinks that the cookie is invalid for the current domain and therefore doesn't set it. Here is the Dev Tools pane's Cookies tab after the Sanctum token call returns (tooltip showing Chrome's complaint):
Since the cookie is not set, the following login call fails with a 419 error.
What am I missing here?
Finally got it working. For any future reader, here are the things:
The first mistake that I was doing was to use a single word host name. It looks like Chrome (or Sanctum, not sure) wants you to have at least one period in the host name. So I changed it from b8 to b8.cod.
You should keep same_site attribute set to lax. none is a rather dangerous value. Chrome now shows none as a potential issue.
SESSION_DOMAIN should be set to .b8.cod with a leading period to support front-end subdomain, as correctly suggested by the documentation.
All other things should be done as suggested in the question. axios must use withCredentials set to true.
I've recently set up the exact same thing (Laravel 8 backend with Sanctum + separate Vue Frontend) and it's working.
Your server side setup looks good. Please double-check that the frontend's IP is actually included in your SANCTUM_STATEFUL_DOMAINS - that caused the 419 error for me sometimes.
On the Vue side, make sure to that you enable the withCredentials in your axios instance, e.g.
const baseDomain = "http://localhost"
const baseURL = `${baseDomain}/api`
export default axios.create({
baseURL,
withCredentials: true,
})
If the provided suggestion does not help, I can further extend my answer by showing you more of my working backend code.
I am implementing Passport Facebook Authentication by linking the Facebook Authentication API route to a button using href like:
Facebook Login
When I click on the button, it redirects to the Facebook Authentication page. But on the page, an error message is displayed saying something like "Insecure Login Blocked: You can't get an access token or log in to this app from an insecure page. Try re-loading the page as https://"
How can I fix this issue?
Amazingly I just started trying to do the same thing like an hour ago and have been having the same issue. If you go into the FB developer portal and go to Settings under Facebook Login there's an option to Enforce HTTPS.
Further Investigation Showed:
"Enforce HTTPS. This setting requires HTTPS for OAuth Redirects and pages getting access tokens with the JavaScript SDK. All new apps created as of March 2018 have this setting on by default and you should plan to migrate any existing apps to use only HTTPS URLs by March 2019. Most major cloud application hosts provide free and automatic configuration of TLS certificates for your applications. If you self-host your app or your hosting service doesn't offer HTTPS by default, you can obtain a free certificate for your domain(s) from Let's Encrypt."
Reference: Login Security
Since you're using passport, also check your auth.js settings, or where ever you keep these settings. Even if your website has a certificate, the following code will still fail:
'facebookAuth' : {
'clientID' : '.............', // App ID
'clientSecret' : '............................', // App Secret
'callbackURL' : 'localhost:9999/auth/facebook/callback',
'profileURL' : 'https://graph.facebook.com/v2.5/me?fields=first_name,last_name,email',
'profileFields' : ['id', 'email', 'name']
},
The problem lies with the callbackUrl.
'callbackURL' : '/auth/facebook/callback'
'callbackURL' : 'http://localhost:9999/auth/facebook/callback'
The statements above will both fail. The callbackUrl needs to start with https. The first one will try to load http://localhost and append the callbackUrl. The second one obiviously loads the full url with http, and both fail to connect with FB. So try one of the following. If your site has a certificate, provide the full url. If you're testing this on a localhost, create your own certificate and access it by https like:
'callbackURL' : 'https://example.com/auth/facebook/callback'
'callbackURL' : 'https://localhost:9999/auth/facebook/callback'
Since Facebook have been requiring usage of HTTPS for our redirect URIs we can use ngrok at localhost for start up a local secure HTTP tunnel. It is a clean and fast suggested alternative for now.
Get official ngrok package
Unzip to your preferred directory
unzip /opt/ngrok.zip;
Make your first HTTP tunnel: /opt/ngrok http 3000
See more great use cases in ngrok docs.
There are 2 ways you can solve that:
First:
You can go to your google Passport strategy and add proxy: true
passport.use(
new FacebookStrategy(
{
clientID: facebookID,
clientSecret: facebookSecret,
callbackURL: "/auth/facebook/callback",
proxy: true
}
)
);
What happens most of the time is that, when you deploy or app through Heroku, for example, they have a Proxy that allows Heroku to direct the requests to your specific server and Passport assumes that if your request goes through a proxy it might not be safe (So... No https).
The second way you can solve that is by using a specific path for your callbackURL.
For example, instead of using:
callbackURL: "/auth/facebook/callback"
you would use:
callbackURL: https://mydomain/auth/facebook/callback
Keep in mind that if you are going to use this approach you might need to create environment variables to hold the values of your specific redirectURL for development as well as for production.
To fix, for local development, generate ssl certs on your machine. Run the commands below(tested on Mac High Sierra, you will need the openssl lib installed on your os) to create a cert.pem and a key.pem file in your working directory.
openssl req -x509 -newkey rsa:2048 -keyout keytmp.pem -out cert.pem -days 365
openssl rsa -in keytmp.pem -out key.pem
Change your node http server to use https. You will need to import the https module in place of the http module.
const https = require('https')
const path = require('path')
const fs = require('fs')
const options = {
cert: fs.readFileSync(path.resolve(__dirname, '<path_to_your_cert.pem>')),
key: fs.readFileSync(path.resolve(__dirname, '<path_to_your_key.pem>'))
}
const server = https.createServer(options, <your_handler_or_app_eg_express>)
server.listen(<your_prefered_port_number>)
Go to the app on your facebook developer console and set the Valid OAuth Redirect URIs to the https version of your localhost domain. Do same for the app domain and site url.
In my case, I modified my package.json file.
"start": "node scripts/start.js" =>
"start": "set HTTPS=true&&node scripts/start.js"
I hope help you.
This for php sdk reference
Now https is required for the web-application to login via Facebook.
Following procedure is required get valid authentication from Facebook.
Basic Seetings
set App Domains as your root domain (www.example.com)
Privacy Policy URL (https://www.example.com/privacy-demo/)
Terms of Service URL (https://www.example.com/terms-demo/)
Set Category
Site URL (https://www.example.com/facebook-login/) facebook-login this folder contain my all facebook login files
Advanced
Server IP Whitelist (your host ip address 124.25.48.36)
Products below Facebook login settings
Valid OAuth Redirect URIs (https://www.example.com/facebook-login/fb-callback.php)
Quick start
Select website put site url (https://www.example.com/facebook-login/)
Save all changes and live your app (ie: on your app) Now your app status will live.
You can refer this code https://github.com/facebook/php-graph-sdk
use a vpn worked for me cyber ghost is free try it
In your passport setting change your redirect url to some https://someUrl
'https' is important
I'm developing an application that uses the Youtube Data API from the server (with node.js) so I have my server side credential key already set up but when I try to get data is always refusing my requests with this message.
Access Not Configured. The API is not enabled for your project, or there is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your configuration.
I've my app hosted in Heroku with the add-on Quote Guard Static that gives me two static IP's that I have whitelisted in the Credentials section of the google developers console. I also have the app hosted in modulus.io and whitelisted the IP range 54.0.0.0/8 that is what they gave me for their AWS region... Any of both deployments are working only in my local machine with my home external IP whitelisted.
The funny thing is that yesterday 15 minutes approximately after I whitelisted the 54.0.0.0/8 range, the app API started working in my Heroku host, but today it stopped again (this might be because it has changed to another IP inside their AWS region or something...).
Is there any way to check what IP is doing the requests to the Youtube data api? I can see in the developers console the request reaching the API and been rejected as "errors" at least I know that their are getting the requests...
Any ideas??
Thanks
EDIT:
Partially solved. See my answer below.
There's a simple service I found that returns your public IP:
http://api.ipify.org?format=json
You could add a route to your application that you can hit from your browser. The route handler then makes a request to this service and returns the result. You could then periodically check what your app's actual public IP is and adjust whitelist accordingly.
// Example express + request
app.get('/ip', function(req, res) {
request({ uri: 'http://api.ipify.org?format=json' }, function(err, response, body) {
res.send(body);
});
});
The problem with the app hosted in Modulus.io is solved now. The app was running by default in Joyent servers but I changed it to the Amazon AWS region and with the IP range 54.0.0.0/8 whitelisted google is accepting all my requests to the API.
Nevertheless, the app in heroku still not working but as is working in one service I'm going to stop investigating in the other one.