Showing posts with label cross-domain. Show all posts
Showing posts with label cross-domain. Show all posts

Friday, July 27, 2018

CORS policy on cached Image

Leave a Comment

In chrome 22 & safari 6.

Loading images from s3 for usage in a canvas (with extraction as a primary intent) using a CORS enabled S3 bucket, with the following code:

<!-- In the html --> <img src="http://s3....../bob.jpg" />   // In the javascript, executed after the dom is rendered this.img = new Image(); this.img.crossOrigin = 'anonymous'; this.img.src = "http://s3....../bob.jpg"; 

I have observed the following:

  1. Disable caches
  2. Everything works fine, both images load

Then trying it with caches enabled:

  1. Enable caches
  2. DOM image loads, canvas image creates a dom security exception

If I modify the javascript portion of the code to append a query string, like so:

this.img = new Image(); this.img.crossOrigin = 'anonymous'; this.img.src = "http://s3....../bob.jpg?_"; 

Everything works, even with caching enabled fully. I got on to the caching being a problem by using an http proxy and observing that in the failure case, the image isn't actually being requested from the server.

The conclusion I'm forced to draw is that the image cache is saving the original request headers, which are then being used for the subsequent CORS enabled request - and the security exception is being generated due to violation of the same origin policy.

Is this intended behavior?

Edit: Works in firefox.

Edit2: Cors policy on s3 bucket

<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">     <CORSRule>         <AllowedOrigin>*</AllowedOrigin>         <AllowedMethod>GET</AllowedMethod>     </CORSRule> </CORSConfiguration> 

I'm using wide open because I'm just testing from my local box right now. This isn't in production yet.

Edit3: Updated cors policy to specify an origin

<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">     <CORSRule>         <AllowedOrigin>http://localhost:5000</AllowedOrigin>         <AllowedMethod>GET</AllowedMethod>     </CORSRule> </CORSConfiguration> 

Verified outgoing headers:

Origin  http://localhost:5000 Accept  */* Referer http://localhost:5000/builder Accept-Encoding gzip,deflate,sdch Accept-Language en-US,en;q=0.8 Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.3 

Incoming headers:

Access-Control-Allow-Origin http://localhost:5000 Access-Control-Allow-Methods    GET Access-Control-Allow-Credentials    true 

Still fails in chrome if I don't bust the cache when loading into the canvas.

Edit 4:

Just noticed this in the failure case.

Outgoing headers:

GET /373c88b12c7ba7c513081c333d914e8cbd2cf318b713d5fb993ec1e7 HTTP/1.1 Host    amir.s3.amazonaws.com User-Agent  Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.91 Safari/537.4 Accept  */* Referer http://localhost:5000/builder Accept-Encoding gzip,deflate,sdch Accept-Language en-US,en;q=0.8 Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.3 If-None-Match   "99c958e2196c60aa8db385b4be562a92" If-Modified-Since   Sat, 29 Sep 2012 13:53:34 GMT 

Incoming headers:

HTTP/1.1 304 Not Modified x-amz-id-2  3bzllzox/vZPGSn45Y21/vh1Gm/GiCEoIWdDxbhlfXAD7kWIhMKqiSEVG/Q5HqQi x-amz-request-id    48DBC4559B5B840D Date    Sat, 29 Sep 2012 13:55:21 GMT Last-Modified   Sat, 29 Sep 2012 13:53:34 GMT ETag    "99c958e2196c60aa8db385b4be562a92" Server  AmazonS3 

I think this is the first request, triggered by the dom. I don't know that it isn't the javascript request though.

3 Answers

Answers 1

The problem is that the image is cached from a former request, without the required CORS headers.Thus, when you ask for it again, for the canvas, with the 'crossorigin' specified, the browser uses the cached version, doesn't see the necessary headers, and raises a CORS error. When you add the '?_' to the url, the browser ignores the cache, as this is another URL. Take a look at this thread: https://bugs.chromium.org/p/chromium/issues/detail?id=409090

Firefox and other browsers do no have that problem.

Answers 2

What CORS settings are you applying? This post suggests that wildcards in AllowedOrigin are parsed (rather then being sent verbatim, this appears to be undocumented behaviour); and the Access-Control-Allow-Origin header value is then cached for subsequent requests, causing issues similar to what you're reporting.

Answers 3

I had a very similar problem and solved it by adding the following header to the response from the server.

'Vary': 'Origin' 

After adding the header all my requests got cached.

Read More

Wednesday, July 18, 2018

Firefox does not keep cookies sent by cross-domain even with all CORS allow

Leave a Comment

I experience a problem with Firefox while Chrome works fine. Here is the situation:

  • Website1.com returns an html page in SSL.
  • This page makes a request to Website2.com in SSL either via img tag or XMLHttpRequest (same issue).
  • Website2.com returns a cookie to be set for itself
  • Firefox ignores this cookie. It is never stored even though it shows in the console.
  • The console doesn't complain about anything.

Client sends:

Origin: https://website1.com 

Server returns:

Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: * Access-Control-Allow-Methods: * Access-Control-Allow-Origin: https://website1.com Access-Control-Expose-Headers: * Set-Cookie: ... 

What else am I missing about CORS?

Thanks!

1 Answers

Answers 1

Access-Control-Allow-Credentials: true 

Is a special flag. If one side declares it other also have to declare it or else it's security failure and browser will not accept data.

So add the same header to client request. (Or if you control server, consider doing without cookies and passing data with other mechanism)

Read More

Sunday, June 17, 2018

Google API + PHP + Ajax Call - Access-Control-Allow-Origin' header is present on the requested resource

Leave a Comment

I'm using the google API to access my calendar entries via OAuth. Unfortunately I'm getting the following error (server is a local raspi):

Failed to load https://accounts.google.com/o/oauth2/auth?response_type=code&access_type=online&client_id=****-****.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Fopenhabianpi..%2Fsmarthome%2Fphp%2Fscripts%2Fscript.oauth2callback.php&state&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly&approval_prompt=auto: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://openhabianpi..' is therefore not allowed access. The response had HTTP status code 405.

My scripts:

Ajax Request

var termine = function (){      $.ajax({         type: "POST",         url: "php/ajax/ajax.termine.php",         data: {             action: 'get_termine'         },n         success: function(response) {             console.log(response);         }     }); } 

ajax.termine.php

require dirname(dirname(__FILE__)).'/vendor/autoload.php';  $client = new Google_Client(); $client->setAuthConfig(dirname(dirname(__FILE__)).'/config/client_secret.json'); $client->addScope(Google_Service_Calendar::CALENDAR_READONLY); if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {   $client->setAccessToken($_SESSION['access_token']);   $calendarId = 'primary';   $optParams = array(     'maxResults' => 10,     'orderBy' => 'startTime',     'singleEvents' => TRUE,     'timeMin' => date('c'),   );    $service = new Google_Service_Calendar($client);   $results = $service->events->listEvents($calendarId, $optParams);   if (count($results->getItems()) == 0) {     print "No upcoming events found.\n";   } else {     print "Upcoming events:\n";     foreach ($results->getItems() as $event) {       $start = $event->start->dateTime;       if (empty($start)) {         $start = $event->start->date;       }       printf("%s (%s)\n", $event->getSummary(), $start);         echo date('c');     }   } } else {   $redirect_uri = 'http://openhabianpi.***.***/smarthome/php/scripts/script.oauth2callback.php';   header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); } 

script.oauth2callback

<?php require_once dirname(dirname(__FILE__)).'/vendor/autoload.php'; session_start();  $client = new Google_Client(); $client->setAuthConfigFile(dirname(dirname(__FILE__)).'/config/client_secret.json'); $client->setRedirectUri('http://openhabianpi.***.***/smarthome/php/scripts/script.oauth2callback.php'); $client->addScope(Google_Service_Calendar::CALENDAR_READONLY); if (! isset($_GET['code'])) {   $auth_url = $client->createAuthUrl();   header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL)); } else {   $client->authenticate($_GET['code']);   $_SESSION['access_token'] = $client->getAccessToken();   $redirect_uri = 'http://openhabianpi.***.***/smarthome/';   header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); } 

I've tried the following, unfortunately without success:

  1. dataType: 'jsonp',

  2. header("Access-Control-Allow-Origin: *");

  3. Setting in .htaccess or apache.conf

Access-Control-Allow-Origin "*"

Thanks in advance for your help!

3 Answers

Answers 1

    if (isset($_SERVER['HTTP_ORIGIN'])){         header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");         header('Access-Control-Allow-Credentials: true');         header('Access-Control-Max-Age: 86400');    // cache for 1 day     }     // Access-Control headers are received during OPTIONS requests     if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS')      {         if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))             header("Access-Control-Allow-Methods: GET, POST,OPTIONS");                  if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))             header("Access-Control-Allow-Headers:        {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");         exit(0);     } 

Answers 2

You can't use AJAX do do an OAuth authentication as the URL returned by $client->createAuthUrl() will show a login page.

You can still stay on the same page by following this steps:

  • Open ajax.termine.php in a new tab.

window.open('php/ajax/ajax.termine.php', '_blank');

  • Set the redirect uri to a blank page that only contains Javascript.
  • Use this javascript to change the parent page URL.

window.top.location.href = 'http://openhabianpi.***.***/smarthome/';

Answers 3

You simply need to visit your google developer account and under API credentials add your web server address or IP address.

Visit console.developers.google.com

Then select your project. Then select credentials. Then select your API key. Then select Application restrictions then select HTTP referrers address and add your address.

enter image description here

Hope it solves your issue.

Read More

Sunday, February 25, 2018

Edge cross-domain request via HTTPS

Leave a Comment

I'm trying to make an Edge extension, which would communicate with another server than origin of the web page. However the communication seems to fail.

I read about issues with cross-domain requests when origin is external and cross-domain request target is in intranet. So I've exposed the intranet server to the internet. But this didn't help.

I tried to run as simplest fetch() as possible and got this result:

fetch("https://fake.domain.info/api/browser/authenticate/").then((response) => {console.log(response);}).catch((error) => {console.log(error);})

[object Promise]: {}

[object Error]: {description: "Failed to fetch", message: "Failed to fetch", number: -2147418113}

I checked network traffic in debug window and found out strange record:

Name Protocol Method Result Content type Received Time Initiator https://fake.domain.info/api/browser/authenticate/ HTTPS GET 200 (from cache) 0 s

I don't really understand why "(from cache)" appears. So inspected request with WireShark. What I've found out is this:

61 3.004629 xxx.xxx.xxx.xxx 192.168.124.144 TLSv1.2 501 Server Hello, Certificate, Server Key Exchange, Server Hello Done

62 3.004666 192.168.124.144 xxx.xxx.xxx.xxx TCP 54 51965 → 443 [ACK] Seq=207 Ack=1908 Win=261632 Len=0

...

86 3.010645 192.168.124.144 xxx.xxx.xxx.xxx TCP 54 51965 → 443 [FIN, ACK] Seq=207 Ack=1908 Win=261632 Len=0

87 3.011785 xxx.xxx.xxx.xxx 192.168.124.144 TCP 60 443 → 51965 [ACK] Seq=1908 Ack=208 Win=65536 Len=0

...

89 3.012215 xxx.xxx.xxx.xxx 192.168.124.144 TCP 60 443 → 51965 [RST, ACK] Seq=1908 Ack=208 Win=0 Len=0

I don't understand why the connection is reset right after the TLS handshake. Opening the web page works fine. I've checked it with WireShark and found out first connection is closed same way right after the TLS handshake but new one is created immediately and traffic goes via this one without problems.

I checked server side logs - no issues where registered. As well as no HTTP requests were logged.

When I tried to run same request via plain HTTP it worked fine:

fetch("http://fake.domain.info/api/browser/authenticate/").then((response) => {console.log(response);}).catch((error) => {console.log(error);})

[object Promise]: {}

[object Response]: {body: Object, bodyUsed: false, headers: Object, ok: false, redirected: false...}

HTTP 404 is returned as expected

So I see the problem is related to TLS connection.

Another thing: the problem occurs only when doing it in Edge. When doing it in Firefox, it works fine:

fetch("https://fake.domain.info/api/browser/authenticate/").then((response) => {console.log(response);}).catch((error) => {console.log(error);})

Promise { : "pending" }

Response { type: "basic", url: "https://fake.domain.info/api/brows…", redirected: false, status: 404, ok: false, statusText: "[{"errors":[{"message":"Invalid API…", headers: Headers, bodyUsed: false }

And I checked traffic in WireShark when running request from Firefox - the connection after the TLS handshake isn't closed but the application data is sent right away.

Is it some known Edge behavior and is there any way to fix it? Could it be some server misconfiguration?

0 Answers

Read More

Friday, December 1, 2017

Is this cross-domain, auto-login OAuth2 SSO design correct, simple and secure?

Leave a Comment

I need to implement a cross-domain SSO solution. Let's assume I have a-site.com, b-site.com and sso-site.com.

The requirements are as follows:

  • Unlogged user clicking "Login" on a-site.com is shown a login screen hosted on sso-site.com.
  • If the user logged in as above, and subsequently visits b-site.com, they will be immediately logged in. I.e. instead of a "Login" link, we want to display their username, etc - without the need to click anything, or a quick redirect of the entire page to sso-site.com and back.

It seems to me the following scheme, using OAuth2 / OpenID Connect, with a small modification should do it:

  1. User is unlogged to a-site.com, b-site.com and sso-site.com.
  2. User goes to a-site.com, clicks "Login".
  3. Browser is redirected to sso-site.com, with return URL on a-site.com as a query string param.
  4. sso-site.com server produces a login form, sends to user's browser. User provides credentials. sso-site.com server checks credentials against DB, decides they are OK. sso-site.com responds with a redirect to the URL indicated in param in step 3. The URL has an authorization code attached as param. The redirect response also sets a session cookie (on domain sso-site.com of course).
  5. Browser receives redirect response, sends it to a-site.com. a-site.com server queries sso-site.com in the backend (not through user's browser) with the authorization code from the redirect URL. sso-site.com recognizes the authorization code, gives back an access token. If this is OpenID Connect, a-site.com also gets user info on that response. If not (plain OAuth2), it needs to make another backend call to sso-site.com to get them. a-site.com creates a user session, and on the page sent to the browser includes a session cookie (for domain a-site.com).
  6. From now on, user is obviously logged into a-site.com.
  7. User goes to b-site.com.
  8. This is where we stray from the standard OAuth2 flow. There's some Javascript in the page, which silently sends a CORS query to sso-site.com. Obviously, we have a session cookie on this request. sso-site.com recognizes the cookie and returns a new authorization code in the payload.
  9. On receiving the response, Javascript recognizes that it got an authorization code (and therefore the user is logged into SSO), so it forces a page reload, attaching the authorization code as a query string param.
  10. b-site.com server sees the authorization code in a param, so in the backend it does the same thing as a-site.com did above. This results in user being logged into b-site.com.

I should add to this that if a user is not logged into SSO, when we make the silent JS call, sso-site.com returns some payload indicating that. Then, the JS receiving that payload sets a cookie on b-site.com, whose presence means not to query sso-site.com via JS on subsequent page views.

Questions:

  • should this work (any incorrect assumptions?)
  • can it be simplified anywhere (iframes?)
  • is this secure (especially in the JS part, departing from OAuth browser redirect model)?

Many thanks! There's a lot of examples on the web for SSO, especially with OAuth2 and CAS (which has a similar flow) - but I could not find a recipe for these specific requirements: cross-domain, and with automatic login without entire page redirect (bad for latency and crawlers) on b-site.com. The closest is the Stackoverflow SSO guide (here), but they have some extra requirements I don't have.

0 Answers

Read More

Monday, July 3, 2017

Font not loading - CORS says header contains no Access Control but there is

Leave a Comment

The problem: I am using html generated from one site that is being pushed to another site (different domains). All is working well except the font (used mainly for icons) is not showing up. I am receiving a CORS error as described further below.

I have added the following code to my .htaccess file on the site where the fonts are stored that allows fonts to be access across any domain:

<FilesMatch ".(eot|ttf|otf|woff)">     Header set Access-Control-Allow-Origin "*" </FilesMatch> 

I checked the header using cUrl:

curl -I https://mywebsite.com/fonts/flatpack.woff?tzy7cr HTTP/1.1 200 OK Server: nginx Date: Fri, 23 Jun 2017 18:33:58 GMT Content-Type: text/plain Content-Length: 142020 Connection: keep-alive X-Accel-Version: 0.01 Last-Modified: Fri, 23 Jun 2017 17:49:02 GMT ETag: "1a474c-22ac4-552a4378235b7" Accept-Ranges: bytes X-Powered-By: PleskLin Access-Control-Allow-Origin: * 

The Access Origin response tells me that the font should be readable but I'm still getting this error from the requesting website:

Access to Font at https://mywebsite/fonts/flatpack.woff?tzy7cr' from origin 'http://anotherwebsite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://anotherwebsite.com' is therefore not allowed access.

Thoughts or suggestions???

Edit: Here is a live link to a test page that fails to load the icon fonts.

2 Answers

Answers 1

Almost got it right:

Header add Access-Control-Allow-Origin "*" Header add Access-Control-Allow-Methods: "GET" 

You need to add the header not set. I'd also add the method to be sure.

Answers 2

Premium font purchased by some other website can be abused another site. That is the reason of complication at browser level coding. Image will not suffer such issue. Font related CORS is complicated by types of fonts, browsers and bugs. Unless you are using paid origin pull CDN or known font provider (free or paid), it is practical to serve font from own server for the sake of making sure that font loads on all browsers, all devices. It is worthy to read :

  1. official W3 doc about CORS,
  2. Mozilla doc,
  3. MaxCDN's guide,
  4. W3's CSS font doc,
  5. this old bug report
  6. this pull request

There are three options from the above resources for giving you a correct answer. You need to test from webpagetest dot org from different user agents & devices and try to watch the video of screenshot.

One :

SetEnvIf Origin "https?://(.*\.(mozilla|allizom)\.(com|org|net))" CORS=$0 Header set Access-Control-Allow-Origin %{CORS}e env=CORS  <FilesMatch "\.(ttf|woff|eot)$">     Header append vary "Origin"     ExpiresActive On     ExpiresDefault "access plus 1 year" </FilesMatch> 

Two (Single domain, HTTPS) :

<FilesMatch "\.(ttf|otf|eot|woff)$">         SetEnvIf Origin "^http(s)?://(.+\.)?anotherwebsite\.com$" AccessControlAllowOrigin=$0         Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin </FilesMatch> 

Three (Multiple domains) :

<FilesMatch "\.(ttf|otf|eot|woff)$">     <IfModule mod_headers.c>         SetEnvIf Origin "http(s)?://(www\.)?(anotherwebsite.com|cdn.anotherwebsite.com|blahblah.anotherwebsite.com)$" AccessControlAllowOrigin=$0         Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin     </IfModule> </FilesMatch> 

Also make sure that proper MIME types are present :

AddType application/vnd.ms-fontobject    .eot AddType application/x-font-opentype      .otf AddType image/svg+xml                    .svg AddType application/x-font-ttf           .ttf AddType application/font-woff            .woff AddType application/font-woff2           .woff2 

Make sure to run Apache configtest before restarting. You may need to activate some module.

Read More

Tuesday, April 4, 2017

FB.login() fails with “Unsafe JavaScript attempt to initiate navigation for frame” on Android Chrome but not desktop Chrome

Leave a Comment

I have a Facebook JS SDK login flow here: https://web.triller.co/#/user/login

When the user taps the Facebook button, the following function is executed:

loginFacebook() {     const fbPromise = new Promise((resolve, reject) => {         FB.login(resp => {             if (resp.authResponse)             {                 resolve(resp.authResponse.accessToken);             }             else             {                 console.log(resp);                 reject(new Error('Facebook login canceled or failed.'));             }         });     });      return fbPromise         .then(accessToken => api.postJson('user/login_facebook', { accessToken }))         .then(this._handleLogin.bind(this)); } 

Basically, it calls FB.login(), and expects to receive a valid resp.authResponse. Unfortunately, it doesn't, even after successfully authenticating on the Facebook popup/tab. Instead, we receive { authResponse: undefined, status: undefined } and the following error from the browser:

Unsafe JavaScript attempt to initiate navigation for frame with URL 'https://m.facebook.com/v2.8/dialog/oauth?foo=bar' from frame with URL 'https://web.triller.co/#/user/login?_k=cmzdb6'. The frame attempting navigation is neither same-origin with the target, nor is it the target's parent or opener.

The error occurs immediately after authenticating within the Facebook popup/tab, and it only occurs on Android Chrome. Desktop Chrome (on a Mac) does not show the same error. Safari on iOS does not show the error, either.

Any thoughts on what's going on? Why the difference between Android Chrome and desktop Chrome? Could it have something to do with the hash in the URL?

4 Answers

Answers 1

In desktop this issue can be caused by XFINITY Constant Guard Protection Suite Chrome extension. Disble it and problem will be solved.

In Android, try removing XFINITY or similar security extensions or applications (Norton security antivirus).

https://developer.salesforce.com/forums/?id=906F00000008qKnIAI

Answers 2

I think it fails because of the m.facebook.com/... based on this https://en.wikipedia.org/wiki/Same-origin_policy#Origin_determination_rules (see the case for http://en.example.com/dir/other.html and why it fails). Although it shouldn't based on what I've done with the fb api this is weird, try making a cors request instead as a workaround?

Answers 3

This is a known issue here https://code.google.com/p/android/issues/detail?id=20254.

When the window.open is called without proper arguments, it will not be opened as expected.

It can be overcome by either updating the browser (for client, check the browser version and if old one, force them to update it).

Otherwise (not applicable for you since you can't change the FB function), pass the correct arguments to window.open

Answers 4

You can also have this implemented this way. This worked for me for all devices. Please read comments to understand the flow and code.

// THIS IS JS FILE YOU NEDD TO USE <script></scriipt> Tag on html page to include js code.        /*  1. Javascript SDK init ******************************************************************************************************* 1  */       window.fbAsyncInit = function () {         FB.init({             appId: '*****yorAPP-ID****',             xfbml: true,             version: 'v2.4'         });     };       (function (d, s, id) {         var js, fjs = d.getElementsByTagName(s)[0];         if (d.getElementById(id)) {             return;         }         js = d.createElement(s);         js.id = id;         js.src = "//connect.facebook.net/en_US/sdk.js";         fjs.parentNode.insertBefore(js, fjs);     }(document, 'script', 'facebook-jssdk'));      window.fbAsyncInit = function () {     FB.init({         appId: 'enteYourAppIDHere',         cookie: true,  // enable cookies to allow the server to access                        // the session         xfbml: true,  // parse social plugins on this page         version: 'v2.2' // use version 2.2     });       // Now that we've initialized the JavaScript SDK, we call     // FB.getLoginStatus().  This function gets the state of the     // person visiting this page and can return one of three states to     // the callback you provide.  They can be:     //     // 1. Logged into your app ('connected')     // 2. Logged into Facebook, but not your app ('not_authorized')     // 3. Not logged into Facebook and can't tell if they are logged into     //    your app or not.     //     // These three cases are handled in the callback function.       // FB.getLoginStatus(function(response) {     //   statusChangeCallback(response);     // });    };    // Load the SDK asynchronously  (function (d, s, id) {     var js, fjs = d.getElementsByTagName(s)[0];     if (d.getElementById(id)) return;     js = d.createElement(s);     js.id = id;     js.src = "//connect.facebook.net/en_US/sdk.js";     fjs.parentNode.insertBefore(js, fjs);  }(document, 'script', 'facebook-jssdk'));          /*     2. HTML FB Button     USE THIS HTML CODE ON YOUR PAGE ********************************************************************************************* 2  */    // ADD Button to HTML       /*      3. When User CLICK on FB LOGIN button it will call this function after you get response from fb ***************************** 3.1  */  // This function is called when someone finishes with the Login  // Button.  See the onlogin handler attached to it in the sample  // code below.  function checkLoginState() {     FB.getLoginStatus(function (response) {         statusChangeCallback(response);     });  }    //Above function is calling below function and passing response in it.  // According to response we check login was success or not ******************************************************************* 3.2    // This is called with the results from from FB.getLoginStatus().  function statusChangeCallback(response) {     console.log('statusChangeCallback');     console.log(response);     // The response object is returned with a status field that lets the     // app know the current login status of the person.     // Full docs on the response object can be found in the documentation     // for FB.getLoginStatus().     if (response.status === 'connected') {         // Logged into your app and Facebook.         // So Login was success so you can do your stuff here... I am calling this below function on success         testAPI();     } else if (response.status === 'not_authorized') {         // The person is logged into Facebook, but not your app.         document.getElementById('status').innerHTML = 'Please log ' +             'into this app.';     } else {         // The person is not logged into Facebook, so we're not sure if         // they are logged into this app or not.         document.getElementById('status').innerHTML = 'Please log ' +             'into Facebook.';     }  }      /*  So if success logged in we call this functiom  Here we use FB graph API to get user's data...  ***************************************************************************** 3.3  */    // Here we run a very simple test of the Graph API after login is  // successful.  See statusChangeCallback() for when this call is made.    // Here we run a very simple test of the Graph API after login is  // successful.  See statusChangeCallback() for when this call is made.  function testAPI() {     console.log('Welcome!  Fetching your information.... ');     FB.api('/me', function (response) {         console.log(JSON.stringify(response));         var uname = response.name;         var fbid = response.id;         console.log(response.email);     });  }
<fb:login-button scope="public_profile,email" onlogin="checkLoginState();" login_text="Sign in with Facebook" data-size="xlarge">  </fb:login-button>

Read More

Tuesday, September 6, 2016

Internet Explorer set cross domain cookies for authorization

Leave a Comment

I have two application on next domains: www.bar.com and www.foo.bar.com. Second application makes authorization via first application (using cross domain request) After this I sets cookies to browser, and in the Internet Explorer it doesn't work:

$.cookie("SESSION_KEY", loginResult.sessionKey, {         expires: 365,         path: "/",         domain: ".bar.com" }); 

The code works in all browsers excepti Internet Explorer v.9 The cookie doen't set. How can I fix it?

2 Answers

Answers 1

This is due to IE settings. From the Tools menu, select Internet Options. Navigate to Security tab. Select Internet web content zone and click Custom Level to open the Security Settings.

Locate Miscellaneous settings. Try enabling Access data sources across domains. You might need to restart IE for the settings to take effect.

Answers 2

IE, as only one web browser in the market, implements partialy P3P standart (which is about acceptance cookies in CORS)

So you can set cookies using server response - to do this you must set this header in server response (which set cookies) (I copy-paste below line from my PHP symfony project) :

$response->headers->set('P3P', 'CP="random_text"'); 

You must also remember about add flag 'withCredentials=true' to your CORS request (in other case, any cookies will be add to response).

Read More

Tuesday, June 21, 2016

How to implement Https on web facing nginx and several microservices behind it

Leave a Comment

I'm just starting to develop a SPA, with java(dropwizard) REST backend. I'm kinda new to 'web' development, but I did internal web apps before, so security was not a big concern before. Right now I'm using nginx as my public facing web server, and I just discovered whole slew of complications that arise as we're splitting actual servers: static web server serving my SPA's files, and java microservices behind it.

I'm used to apache talking to tomcat with mod_jk, but now I had to implement CORS in dev because my SPA is deployed on a lite-server serving at different port than the REST Api served by dropwizard.

Now I got to my minimum viable product and wanted to deploy it on prod, but I have no idea how do I do it.

  1. Do I still need the CORS header? Dropwizard will be run separately on a different port only available to local processes, then I configure nginx to route incoming request from, e.g. /api/ to that port. Does that counts as cross-origin?
  2. I'd like to serve full https. Dropwizard can serve to https, but I don't want to update SSL cert on multiple microservices. I read about nginx ssl termination, will this enable me to use plain http in local and https on nginx?
  3. Any other caveats to watch out on deploying with this architecture?

Thank you!

1 Answers

Answers 1

Yes, you can certainly do it!

You can terminate https with nginx, and still have the backend operate on either plain http or even https still. The proxy_pass directive does support both access schemes for the upstream content. You can also use the newer TCP stream proxying, if necessary.

There are not that many caveats, really. It usually just works.

Read More

Wednesday, June 15, 2016

Download a file cross-domain in CasperJS

Leave a Comment

I'm unable to download a file stream from a web server using CasperJS:

  • a form is posted to a url
  • url returns a file stream

So far I have validated that the correct form values are posted.

var casper = require('casper').create({     verbose: true,      logLevel: 'debug',     viewportSize: {width: 1440, height: 800},     pageSettings: {         userName: '****',         password: '****',         webSecurityEnabled: false     },     waitTimeout: 200000 });  casper.start("***");  casper.then(function() {     var exportForm = this.evaluate(function() {         return $("#export_pdf_form").serialize();     });      var exportAction = this.evaluate(function() {         return $("#export_pdf_form").attr('action');     });      var url, file;     url = '***' + exportAction; (eg. https://webserver/export)     file = "export.pdf";     casper.page.settings.webSecurityEnabled = false;     casper.download(url, fs.workingDirectory + '/' + file, "POST", exportForm); }); 

Casper error "Unfortunately casperjs cannot make cross domain ajax requests" followed by "XMLHttpRequest Exception 101". After searching it states that settings the web security variable to false should make this work...but it doesn't. Anything else I should look into?

casperjs - v1.1.1 phantomjs - v2.0.0

3 Answers

Answers 1

Turns out nothing is wrong with my code, simply updating PhantomJS from 2.0.0 to 2.1.1 has solved the issue.

Answers 2

Alternative answer: You could implement a proxy, via an API interface through your site. Caveat: Best done only with resources that you control, as it requires your site to be responsible for the content, and could compromise your certificate if you allowed malware or insecure content.

Answers 3

There is a lot of AJAX cross-domain and same-origin security policy material written out there, take a look. As far as i know, there is only two alternatives to the one John proposed (setting up a proxy on the server side):

  1. Using W3C CORS standard technique and HTTP headers.

    https://en.wikipedia.org/wiki/Cross-origin_resource_sharing

  2. JSONP mechanism.

    https://en.wikipedia.org/wiki/JSONP

I really don´t know if it is the real problem you are experiencing, but i hope this is helpfull for you.

Read More