zf-fr / zfr-cors

A Zend Framework 2 module that helps you to deal with Cross-Origin Resource Sharing (CORS)
MIT License
60 stars 39 forks source link

iOS Phonegap Origin Request Header crashes zf2... #18

Closed basz closed 8 years ago

basz commented 10 years ago

I'm not sure if I am at the correct place - my understanding of this whole CORS is quite limited as I am starting out with this, but I thought you might have some insights in this.

But let me explain - I appreciate your advice. I have an phonegap application written with emberjs and https://github.com/simplabs/ember-simple-auth.

Everything works correctly when I run this project in the browser on my Mac. Whenever I create it into an iOS app (thus running as phonegap application) the Origin header is specified as 'file://'. This is a problem as this line https://github.com/zf-fr/zfr-cors/blob/master/src/ZfrCors/Service/CorsService.php#L65 will throw an exception because file:// wil not parse as a valid url.

I validated this issue by doing the following. Now my result will pass. I know this is not really secure and that any further (defined after the Origin) headers are not lazy loaded and thus not available in the header object.

        try {
            $originUri = UriFactory::factory($headers->get('Origin')->getFieldValue());
        } catch (InvalidArgumentException $e) {
            return true;
        }

Alternatively I tried to set the Origin header via jQuery.

      jqXHR.setRequestHeader("Origin", "https://app.example.com");

However this throws an in browser error as the Origin header is restricted to be modified.

[Error] Refused to set unsafe header "Origin"
    setRequestHeader ([native code], line 0)
    send (jquery-1.10.2.min.js, line 25)
    ajax (jquery-1.10.2.min.js, line 25)
    login (ember-simple-auth.js, line 460)
    send (ember-1.1.2.js, line 14740)
    submit (app-user.min.js, line 1)
    send (ember-1.1.2.js, line 14740)
    (anonymous function) (ember-1.1.2.js, line 33233)
    run (ember-1.1.2.js, line 5609)
    run (ember-1.1.2.js, line 5974)
    handler (ember-1.1.2.js, line 33231)
    (anonymous function) (ember-fastclick.js, line 126)
    dispatch (jquery-1.10.2.min.js, line 25)
    handle (jquery-1.10.2.min.js, line 25)
Ocramius commented 10 years ago

See #14

bakura10 commented 10 years ago

Actually file:// looks like a strange schema for CORS no? :o

basz commented 10 years ago

It's what iOS sends when its an phonegap (cordova) app.

bakura10 commented 10 years ago

Anway, as said in other topic, you have to tweak the Uri (see the last part in the doc). I didn't do it myself so I cannot indicate it for sure, but ZfrCors cannot do specific cases for each schemes :).

basz commented 10 years ago

Actually, file:// is already an registered sceme... I am following your suggestion to override the method onCorsRequest in the listener. The only problem I can think of is that the rest of any headers can't be accessed... Not sure it that will be a problem...

bakura10 commented 10 years ago

By the way, thanks for the link of this Ember Auth module, didn't know it. did yu try Ember-Auth (https://github.com/heartsentwined/ember-auth) too ?

basz commented 10 years ago

for about 3 minutes... i liked the 'simple' of simple-auth

bakura10 commented 10 years ago

And it's not written in CoffeeeScript :D

intellix commented 10 years ago

Also ran into this. It's an issue for both iOS and Android applications to use ZfrCors because they both send file:// as the Origin header. It seems the only ways around this are: 1) Overwriting Origin header from file:// to file:/// before ZF2 processes it 2) Wrapping $headers->get('Origin') in try/catch so it doesn't fail. As it is, it's impossible to use ZfrCors in Native app APIs :) What do you think is the best solution?

bakura10 commented 10 years ago

I'm not an expert of iOS development but do you need CORS for iOS ? Does ios perform this verification as a browser does?

If iOS does not populate properly the origin header, I have no idea about how to solve that ;(.

Envoyé de mon iPhone

Le 18 nov. 2014 à 13:11, Dominic Watson notifications@github.com a écrit :

Also ran into this. It's an issue for both iOS and Android applications to use ZfrCors because they both send file:// as the Origin header. It seems the only ways around this are: 1) Overwriting Origin header from file:// to file:/// before ZF2 processes it 2) Wrapping $headers->get('Origin') in try/catch so it doesn't fail. As it is, it's impossible to use ZfrCors in Native app APIs :) What do you think is the best solution?

— Reply to this email directly or view it on GitHub.

basz commented 10 years ago

It’s been a while… But I would think/guess/assume/kindofremember that web 'views' in iOS are done with webkit, which does CORS yes.=

fabiopaiva commented 9 years ago

The uri "file://" return an invalid uri, then my solution was:

public function onBootstrap(MvcEvent $e)
{
    $eventManager        = $e->getApplication()->getEventManager();
    $headers = $e->getRequest()->getHeaders();
    if ($headers->has('Origin')) {
        //convert to array because get method throw an exception
        $headersArray = $headers->toArray();
        $origin = $headersArray['Origin'];
        if ($origin === 'file://') {
            unset($headersArray['Origin']);
            $headers->clearHeaders();
            $headers->addHeaders($headersArray);
            //this is a valid uri
            $headers->addHeaderLine('Origin', 'file://mobile');
        }
    }
}

in zfr-cors.local.php add

return array(
    'zfr_cors' => array(
     /**
      * Set the list of allowed origins domain with protocol.
      */
    'allowed_origins' => array(
        'file://mobile',
    )
    //...//
);
fabiopaiva commented 9 years ago

Same above with double check

public function onBootstrap(MvcEvent $e)
{
    $eventManager        = $e->getApplication()->getEventManager();
    $headers = $e->getRequest()->getHeaders();
    if ($headers->has('Origin') &&
        $headers->has('X-Requested-With') &&
        $headers->get('X-Requested-With')->getFieldValue() === 'com.domainname.mycordovapackagename') {
        //convert to array because get method throw an exception
        $headersArray = $headers->toArray();
        $origin = $headersArray['Origin'];
        if ($origin === 'file://') {
            unset($headersArray['Origin']);
            $headers->clearHeaders();
            $headers->addHeaders($headersArray);
            //this is a valid uri
            $headers->addHeaderLine('Origin', 'file://mobile');
        }
    }
}

in zfr-cors.local.php add

return array(
    'zfr_cors' => array(
     /**
      * Set the list of allowed origins domain with protocol.
      */
    'allowed_origins' => array(
        'file://mobile',
    )
    //...//
);
solcre commented 8 years ago

This is issue is so old, what are the plans for this problem ?

fabiopaiva commented 8 years ago

@solcre the problem isn't in zfr-cors

fabiopaiva commented 8 years ago

Imho this issue must be closed.