more than one callback url for twitter app (localhost and live site)? - passport.js

Can i set the more than one call back urls in twitter app just like google app . I have done the twitter authuntication through require('passport-twitter').Strategy;
this allow me only one url . can i set it to two urls one for localhost and one for live site e.g
callbackURL: "site.com/auth/twitter/callback",
and
callbackURL: "http://localhost:3000/auth/twitter/callback"
google allow more than one

I don't know passport.js but the Twitter "oauth/request_token" endpoint allows you to pass an "oauth_callback" parameter with the callback URL. Check this link: https://dev.twitter.com/oauth/reference/post/oauth/request_token
Hope this helps! ;)

Related

Setting up Swagger Ui in Firebase Functions Server

I've developed an API on Firebase Cloud Functions and I want to include a docs path to it.
I'm using swagger and I could successfully test it locally (localhost:PORT/docs) but when I deploy the function to Firebase it's not working, it redirects me to an authorization page.
I think I figured out why this is:
Let's say the name of my Cloud function is cfunc. Then the base url for it is something like https://region-name-project-name.cloudfunctions.net/cfunc. Based on how I included the swagger documentation:
const swaggerDoc = require('./docs/swagger.config.json')
app.use(
'/docs',
allowCors,
swaggerUi.serve,
swaggerUi.setup(swaggerDoc, {
customCssUrl: '/assets/swagger.css',
customSiteTitle: 'My Function Title',
customfavIcon: '/assets/logo.ico',
swaggerOptions: {
supportedSubmitMethods: [] //to disable the "Try it out" button
}
})
)
the docs should be located at https://region-name-project-name.cloudfunctions.net/cfunc/docs. When I try to access that URL, watching "Network" in my browser DevTools, it attempts a GET at that URL with response 304 and then redirects to https://region-name-project-name.cloudfunctions.net/docs and that's what brings up the Google Authentication page, since there's no Cloud Function named "docs" so Google thinks I'm trying to access something else in Firebase Cloud Functions (the same thing happens if I do something like https://region-name-project-name.cloudfunctions.net/tomato)
But I still don't know how to fix this redirect or why it's happening. I tried adding the Cloud Function URL to the host parameter of the swagger.config.json file, and some modifications to CORS, like allowing more Request Methods, adding json as content type, allowing authentication on headers, but nothing seems to be working.
Hope I was clear enought, if not tell me any other info you need (it's one of my first posts here :B)
Found the SOLUTION
After testing a BUNCH of different things, I found out that the redirection was in fact happening always removing one slice of the path after, for example I changed the docs endpoint to '/something/docs' and when accessing the URL that would be https://region-name-project-name.cloudfunctions.net/cfunc/something/docs it redirected to https://region-name-project-name.cloudfunctions.net/cfunc/docs which did not bring up the Google Authentication thing but now wasn't a valid path for my docs so it returned a 'Cannot GET /cfunc/docs'.
For some reason this redirection DOES NOT happen if you add an extra forward slash ('/') at the end of the documentation URL. So, in the first case, where the endpoint for the documentation is only '/docs', accessing the URL https://region-name-project-name.cloudfunctions.net/cfunc/docs/ does it. I do not know why that is, I'm probably posting an Issue on the swagger repo, but if someone has some extra data on why or how to make it work otherwise it would be awesome to hear.
Hope this helps someone else!
EDIT:
Oh and another thing I forgot, it's apparently better if you setup swagger-ui as if you were using express Router, even if you are not (maybe Firebase loads the Cloud Function with something like a router), so instead of app.use('/docs', swagger-ui.serve, swagger-ui.setup(swagger-file)) do app.use('/docs', swagger-ui.serve) and then app.get('/docs', swagger-ui.setup(swagger-file))

Electron + Vue + msal-nodejs + Azure Ad: redirect URL issue

I'm building a desktop app using Electron and Vue as framework.
I also need to authenticate the user using Azure AD and I'm using msal-node.js as library to do that.
I'm able to authenticate with the server in azure and get the user info, but I cannot figure it out how to set the redirect URL.
First I have to say that the behaviour between dev and prod change drastically and I'm going to explain both scenarios and, in both of them I'm going to use history mode or not
DEV - using createWebHistory
Return Url in Azure and .env file: http://localhost:8080/
This is what I've got from the devTools during the normal navigation (no authenticated)
And this is what I've got after the authentication (the call to the API is successful):
Blank page in the app.
DEV - using createWebHashHistory
Return Url in Azure and .env file: http://localhost:8080/#/
After the authentication (failed):
Blank page in the app.
PROD
In prod I must use createWebHasHistory otherwise I've got blank page from the beginning.
The first problem I've got in production is the url itself.
When I create the window I call the following url:
await win.loadURL('app://./index.html')
In azure I cannot use the same url because it's not a valid url.
If I use just:
await win.loadURL('app://index.html')
I've got blank page
Any idea?
Thank you
The solution I've found it's pretty simple. Probably it's not the most "elegant", but it works, at least for prod. In dev I've still got the same weird problem described above.
Basically I'm starting a node server (localhost:3031 for example), within the app itself, then I'm catching the redirect url with it (localhost:3031/redirect) and serving the internal url from it:
expressApp.get('/redirect', async (req, res) => {
await win.loadURL('app://./index.html#about')
})
As I said, it works and I don't see any security issue with that, but, if you have any other idea or suggestion, please let me know.
Thank you
UPDATE
I've found the issue with Dev as well. In order to authenticate I'm using what Microsoft is suggesting in its documentation.
If you look at the file AuthProvider.js there is this portion of code, at the beginning:
const CUSTOM_FILE_PROTOCOL_NAME = process.env.REDIRECT_URI.split(':')[0];
Down below, in the method "getTokenIteractive" there is this other piece of code that applies the new protocol:
protocol.registerFileProtocol(CUSTOM_FILE_PROTOCOL_NAME, (req, callback) => {
const requestUrl = new URL(req.url)
callback(path.normalize(`${__dirname}/${requestUrl.path}`))
})
In Dev my REDIRECT_URI is "http://localhost:3031/redirect", but the app protocol must be "app" (or whatever you have chosen) in order to work with Vue. So, I've just wrapped this last method in a condition based on the environment and now everything works as expected everywhere.
I hope all this can be useful to someone.
I ran into a similar issue and your solution helped me out, thank you! Can I ask how you handled the logout redirect?
Also have you tried onBeforeRequest to handle the redirects, instead of a node server?
It was used as an example in an auth0 blog: https://auth0.com/blog/securing-electron-applications-with-openid-connect-and-oauth-2/

Getting full url in express app running as firebase function -- including the function name?

This seems a bit more challenging than just generally getting the url + path due to express being served from a secondary path.
I'm trying to dynamically create redirect/callback URL's for passport based OpenID integrations.
So far, I've successfully gotten as much using the req.host as directed in other stackoverflow threads:
callbackURL: "https://" + req.get("host") + "/auth/apple/redirect",
I do not need protocol as I'm only dealing with https all the time.
The issue is, my function is being served from:
https://europe-west2-projectname.cloudfunctions.net/MY_FUNCTION_NAME/
and therefore using just host, the url above will not be a valid redirect URL that Oauth can use.
I am doing this as I have 1 single app running off of 2 different functions depending if i'm in staging OR production.
To further add insult to injury -- firebase functions within the same app seem to share their environmental variables so I can't really count on those either.
According to the Google Cloud documentation:
node 6 and 8 offer FUNCTION_NAME as an environment variable that indicates which function is being run.
node 10 offers FUNCTION_TARGET.

In an Express.js server, how can I send an HTML (with style and js) acquired from a HTTP request, as a response?

This is an Express.js server. I'm trying to authenticate my Instagram API.
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const axios = require('axios');
const ejs = require('ejs');
var app = express();
// bodyparser middleware setup
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var instagramClientId = '123123';
app.get('/instagram', (req, res) => {
axios({
method: 'post',
url: `https://api.instagram.com/oauth/authorize/?client_id=${instagramClientId}&redirect_uri=REDIRECT-URI&response_type=code`,
}).then((response) => {
res.send(response.data);
console.log(response.data);
}).catch((e) => {
console.log(e);
});
});
// port set-up
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`app fired up on port ${port}`);
});
This is the error I got. Looks like the html file was sent just fine, but the css and js weren't executed. You can see the error messages were all about style and js not being excuted.
Is this because I need to enable some options in my res.send() code?
I'm going to answer two questions here, the first is what I think you're actually having problems with and the second is what would technically be the answer to this question.
What I think your actual problem is: A misunderstanding of OAuth2.0
Looking at your code, it looks like you're trying to get a user to authenticate with Instagram. This is great, OAuth2.0 is fantastic and a good way to authenticate at the moment, but you've got the wrong end of the stick with how to implement it. OAuth2.0 is about redirects, not proxying HTML to the user. In this case it looks like you're using axios to make a server side call to the instagram OAuth endpoint and then sending the user that HTML. What you should actually be doing is redirecting the user to the Instagram URL you've built.
A high level of the "dance" you go through is the following.
The user requests to login with instagram by pressing a button on your website.
You send the user to an instagram URL, that URL contains your applications token plus an "approved" redirect url. Once the user has logged in with Instagram, Instagram will redirect the user to your approved redirect url.
The users browser has now been redirected to a second endpoint on your server, this endpoint recieves a one-time token from Instagram. You take that token on your server side and use axios (or similar) to make a server side request to fetch some user information such as their profile. Once you have that data, you can then create a user in your the database if needed and issue a new session token to them. Along with the profile call on this, you'll also get a token given directly to you (different from the one the users browser gave you) which will allow you to make requests to the Instagram API for the privileges you requested from the user originally.
This means you have 2 endpoints on your service, the "hello, I'd like to log in with instagram, please redirect me to the instagram login page" and then "hello, instagram said I'm all good and gave me this token to prove it, you can now check with them directly" (this is the callback endpoint).
You can manage this whole process manually which is great for understanding OAuth, or you can use something like Passport.js to abstract this for you. This lets you inject your own logic in a few places and handles a lot of the back and forth dance for you. In this instance, I'd probably suggest handling it yourself to learn how it all works.
Ultimately, you are not sending the user any HTML via res.send or anything similar. Instead your first endpoint simply uses a res.redirect(instagramUrl). You also thus do not make any HTTP requests during this portion, you do that on the "callback" after they've entered their username and password with Instagram.
Technically the correct answer to this question: proxy the JS and CSS calls, but this is really bad for security!
You're sending some HTML from a 3rd party in this case. So you will need to also allow the user access to the HTML and CSS. Security wise, this is quite iffy and you should really consider not doing this as it's bad practice. All of the JS and CSS links in the page are most likely relative links, meaning they're asking you for some JS and CSS which you are not hosting. Your best bet is to find these exact paths (ie: /js/app.min.js) and to then proxy these requests. So you'll create a new endpoint on your service which will make a request to instagrams /js/app.min.js and then send that back down with res.send.
Again, please do not do this, pretending to be another service is a really bad idea. If you need something from instagram, use OAuth2.0 to authenticate the user and then make requests using their tokens and the official instagram API.

Handling redirect code with OAuth2

I am using Instagram's API which requires OAuth2 have some questions regarding best practice for setup. For more details here: https://www.instagram.com/developer/authentication/
So a user clicks on a login button and I give a redirect href.
Log In
They then receive a popup sign in, and they have the option of signing in or not. They are then redirected and '?code=zzzzzzz'is appended to the url: "http://localhost:8080?code=zzzzzzz"
Then the instructions read:
Now you need to exchange the code you have received in the previous step for an access token. In order to make this exchange, you simply have to POST this code, along with some app identification parameters, to our access_token endpoint.
But how should I do this? I'm using Express on the backend. To serve the frontend I use this line:
var static_path = path.join(__dirname, './../build');
It isn't an API route, so I can't use the normal
app.get('/?code=zzzzzzz', function(req, res) {...}).
So how can I use the code that I received in the params?
You must change your redirect_uri on isntagram to something like:
/auth/instagram/callback
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=http://localhost:8080/auth/instagram/callback&response_type=code
Then you can get your code with req.query.code from inside the controller.
For posting the code to isntagrams API use "request" library for nodejs

Resources