Meteor.loginWithFacebook is failing - facebook-graph-api

I keep getting this error message while trying to implement the Meteor.loginWithFacebook() method. Login used to work for my app now it doesn't anymore and I have no idea why:
I have it set so when the facebook login button is clicked, the Meteor.loginWithFacebook() method is called, like so (client-side):
'click .facebook-login':function(event){
Meteor.loginWithFacebook({requestPermissions:['user_photos', 'user_videos'], loginStyle:"popup"},function(err){
if (err)
throw new Meteor.Error(err, "Facebook Login Failed");
});
}
Server-side:
ServiceConfiguration.configurations.upsert(
{ service: "facebook" },
{
$set:{
// Development
appId: "App-ID-String",
secret: "App-Secret-String"
}
}
);
Oddly enough, this works fine when working in development but when I push my code to my production server, I get the error above. This code also worked for several months and then just stopped working, in production. I've cleared both databases to start from scratch and I still get the error in production but not development.
Before you mention it, I have separate code blocks to handle the different appId and secret based on development versus production, but the code is essentially the same and accounts for both environments.

Turns out that the Facebook SDK is particular about your URL prefix/host (if there is or is not a 'www' in front of your URL) and treats the URLs as separate sites. When going to my site to login, the non-www prefixed URL version of my site could not login to Facebook but the 'www' one could.
I was able to fix this by forcing my app to reload the 'www' prefixed URL if the non-www URL was accessed using the following code. I tried forwarding using the GoDaddy DNS interface but it didn't work.
Meteor.startup(function () {
if (location.host.indexOf('www') === -1) {
location = 'http://www.example.com';
}
});
This instantly fixed my primary issue though it seems this isn't the most ideal way of handling this since it basically loads the application twice if the user visits the non-www URL.

Related

Busting client pwa cache from a 301 redirect

I have been using nuxt and nuxt-pwa for my project and somehow I have come across this problem when I want to launch this product.
https://example.com was originally used to test and show the client on what we have built, but now the client request to do it on https://www.example.com/ instead. I thought it would be easy enough to redirect it with a 301. Little did I know it was not that simple.
PWA has cached the app and api storage data on https://example.com and it refuses to retrieve new app from https://www.example.com
So I tried to catch some api call to inject a script to bust client cache with this code
if ('caches' in window) {
caches.keys().then(function (keyList) {
return Promise.all(
keyList.map(function (key) {
return caches.delete(key)
})
)
})
}
window.open('/', '_self')
And it end up destroying the site and now it is just a blank page.
What can I do to make the PWA follow through with the 301 redirect?

How to get cookies working with Nuxt Apollo and SSR correctly?

We've built a framework around Nuxt to get it to work with WordPress really well. We have been pulling our hair out trying to get post previewing working.
A common setup will be a WordPress install running on a domain like http://api.example.com and then to have Nuxt running on http://www.example.com. There is a WordPress plugin called WP-Graph-QL that creates a GraphQL endpoint like http://api.example.com/graphql, and we wrote a CORS plugin to set the correct CORS headers to work with whatever the frontend origin may be. This is that plugin if you are curious https://github.com/funkhaus/wp-graphql-cors
Our Nuxt Apollo setup is this:
export default function() {
return {
httpEndpoint: process.env.DEFAULT_ENDPOINT,
getAuth: () => process.env.BASIC_API_TOKEN || "",
httpLinkOptions: {
credentials: "include"
}
}
}
FYI sometimes the API will be hidden behind a Basic Auth UN/PW (like when on a staging site for example), that is what the getAuth function is doing.
This all seems to work client side, but it fails on SSR for some reason. It seems the cookies don't get sent in the SSR request, but they do in the client side request. Am I missing something super obvious here?
NOTE: I asked this question here 8 days, but am trying here for more attention

On what domain is my Javascript in my Office Add-In

We have an Outlook Add-In which runs in OWA.
The Manifest sits on https://company.ourdomain.com
The Javascript sits on https://company.ourdomain.com
The Custom Web Service we wrote in-house sits on https://company.ourdomain.com
When I make a call from within JavaScript in response to an Add-In Command, I use the format https://company.ourdomain.com/api/Controller/Action in the ajax call.
I end up getting one of those CORS errors (sometimes it's pre-flight, other times CORB). Why am I getting this if the Javascript is literally sitting on the same domain as the web service?
I'm assuming I'm authenticated since I've logged into my Outlook account.
What gives?
NOTE:
As an experiment I attempted a RESTful call by directly typing in the URL (No OWA involved). This caused the code to Authenticate against Azure AD. Then afterward I logged into OWA in the same browser session and everything worked fine. Do I actually need to authenticate within the Javascript even if the webservice I'm calling is in the same domain?
AJAX CALL WHICH GENERATES ERROR
Remember, it will work just fine after I've made a RESTful call by making a call to my web service directly from the Browser
var apiUri = '/api/People/ShowRecord';
$.ajax({
url: apiUri,
type: 'POST',
data: JSON.stringify(serviceRequest),
contentType: 'application/json; charset=utf-8',
dataType: 'json'
}).done(function (response) {
if (!response.isError) {
// response to successful call
}
else {
// ...
}
}).fail(function (status) {
// some other response
}).always(function () {
console.log("Completed");
});
OBSERVATION
When I call the api from the Address Bar the code below is run. This code never gets invoked by Javascript
[assembly: OwinStartup(typeof(EEWService.AuthStartup))]
namespace EEWService
{
public partial class AuthStartup
{
public void Configuration(IAppBuilder app)
{ app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Notifications = new WsFederationAuthenticationNotifications
{
RedirectToIdentityProvider = (context) =>
{
context.ProtocolMessage.Whr = "ourdomain.com";
return Task.FromResult(0);
}
},
MetadataAddress = ConfigurationManager.AppSettings["ida:MetadataAddress"],
Wtrealm = ConfigurationManager.AppSettings["ida:Audience"],
TokenValidationParameters = new TokenValidationParameters
{
ValidAudiences = new string[] { $"spn:{ConfigurationManager.AppSettings["ida:Audience"]}" }
}
});
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
},
MetadataAddress = ConfigurationManager.AppSettings["ida:MetadataAddress"],
});
}
}
}
There are a few problems with this I think.
The first one is you are trying to serve your static content off the same server you are serving your code from. This is in general considered a bad-practice, purely because no point in wasting those precious server resources for static content. Ideally you should upload your static content to a CDN - and let the users' browser make a request to some super-cached file server. However - I understand this option might not be available to you as of now. This also isn't the root cause.
The second and the real problem is, (you think you are but) you are not authenticated. Authentication in Outlook web-addins doesn't come by default, it's something you need to handle. When Outlook loads your web add-in into the side panel it makes certain methods available to you which you can use and kind-of create a pseudo-identity (as an example Office.context.mailbox.userProfile.emailAddress ) - but if you want real authentication, you will need to do that yourself.
There are three ways of doing that as far as I can tell.
The first one is through the Exchange Identity Token
Second one is through the Single Sign On feature
The third one - which I think is the most convenient and the simplest in logic to implement is using WebSockets. (SignalR might be what you need).
When the user loads your first page, make sure a JS value like window.Unique_ID available to them. This will come in handy.
Have a button in your UI - which reads "Authenticate"
When the user clicks to this button, you pop them out to a url which will redirect to your authentication URL. (Something like https://company.ourdomain.com/redirToAuth). This would save you the trouble of getting blocked in the side-panel, because you are using window.open with a url that's on your domain. Pass that Unique_ID to redirection which then redirects you to OAuth login URL. That should look like https://login.microsoftonline.com/......&state=Unique_ID
Right after popping the user to sign in window, in your main JS (which is client-side), you open a web-socket to your server, again with that Unique_ID and start listening.
When the user completes authentication, the OAuth flow should post back either an access token, or the code. If you get the access token, you can send it through the sockets to front-end (using the Unique_ID which is in the parameters of post-back) or if you had the code, you finish authenticating the user with a server-to-server call and pass the access token the same way afterwards. So you use that unique Id to track the socket that user connected from and relay access token to only that user.

Ember App: Looking for a workaround for Safari bug that ignores the '#' in my url on https redirects by Cloudfront

UPDATE 2:
I found the reason, but not a solution yet. This has to do with how safari browsers deal with the '#' when Cloudfront redirects HTTP to HTTPS. Safari ignores the hashtag, and apparently this is a bug that's existed in Safari for years. I'm not 100% sure this is my issue, but it seems to be. Still looking for a solution.
END UPDATE 2
For some reason I'm having trouble figuring out, Safari browsers (mobile and desktop) act differently from Chrome and Firefox when I refresh a page or try to access a route directly on my app.
I have a playlists route:
Router.map(function() {
...
this.resource("playlists", function () {});
...
});
I can hit the playlists route directly with rooturl.com/playlists on Chrome and Firefox and in the console logs, I see this:
Attempting URL transition to /playlists
When I try to hit the playlists route directly in Safari, I see this:
Attempting URL transition to /
Another strange thing is that when I use my localhost the transition is correct on all browsers including safari (mobile and desktop). This makes me think it has something to do with the production environment. I'm using AWS S3 and Cloudfront, but I'm not fully sure that has anything to do with this.
I can provide more information here if asked.
UPDATE:
When I use the fragment (followed by a '#') in the url, safari redirects correctly. So this redirects correctly:
example.com/#/playlists
But this does not:
example.com/playlists
Again, this problem only occurs in production, on AWS S3/Cloudfront. On localhost, Safari works as expected.
In my case, this was fixed by making sure the protocol is not switched from https to http at any point. Specifically, S3 was issuing a redirect over http while the original request was over https. This leads to Safari stripping the request from any (potentially) sensitive data.
Fixed it by adding https to our S3 redirect setup.

ember cli url not working on server with manual return key (versus link-to)

An ember cli site was deployed onto a server and it works fine. Links via {{link-to}} all work beautifully.
BUT, when a user (me that is) manually enters a url and hits return. then the site is not found.
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
even changing a parameter of a working url (initially navigated to thru link-to)
http://site/start/0/length/30
and simply backspacing, changing the 30 to 20 and hit return
http://site/start/0/length/20
its a no go
localhost:4200 doesn't have this issue.
has anyone observed this vicious behaviour.
i actually need it for a callback redirect for oauth. but then noticed than any manually entered urls dont function.
It is because your server (IIS?) is trying to access the full path requested by your browser (eg /start/0/length/30), and not finding a valid file on disk returns a 404.
So, you need to configure your web server to proxy/rewrite the requests to the proper location. Assuming you are deploying your application in your "root" directory, the proper location is /index.html (the file ember-cli creates).
Unfortunately, I can't help you with IIS, but I can provide you with the proper configuration for nginx:
location / {
try_files $uri $uri/ /index.html;
}
This says "If the requested URI doesn't exist, instead respond with the /index.html file".
When you are using ember server on localhost:4200 you don't have the same problem because it is automatically doing something similar transparently.
If you are serving this up from any web server that isn't the built in Ember, ie non local server, you need to have a wildcard rule that returns your Ember app's index.html file for anything below your websites base url. If you only have your base url return the index.html file, then your webserver is confused by the unrecognized url and thinks it has nothing to return. If your rule, though,
for baseUrl/* returns index.html, your Ember app will then run the correct route hooks to establish the app context
this is a dupe and the question is
How to run emberJS application in IIS?
the easy answer is set locationType: hash in ember-cli's environment.config file (copied from accepted answer)
that will introduce a '#' in the url but doesnt require an IIS change.
var ENV = {
...
locationType: 'hash'
... };