Skip to content
This repository has been archived by the owner on Jan 4, 2022. It is now read-only.

IE 11 not getting interceptor #147

Closed
figuerres opened this issue May 23, 2017 · 24 comments
Closed

IE 11 not getting interceptor #147

figuerres opened this issue May 23, 2017 · 24 comments

Comments

@figuerres
Copy link

this may not be an issue with the code in this package but i am putting a message here in case anyone knows what this is and how to fix it.

i have an app that is working 100% in chrome and Edge.
basic page load works in IE 11

web service calls that need a JWT fail.

IE 11 is not giving any errors during the app load.

the app is using the current angualr 4.xxx packages and is built with angualr-cli into packed scripts.

i am trying to determine the cause but right now i have no idea what the real problem is.

@gund
Copy link
Owner

gund commented May 23, 2017

I guess to have a better idea of why and where it is happening is to put some console logging down the Observable chain (before appending headers).

You might also look into .catch() observable operators used along the way - maybe somewhere you suppressing an error and so it not visible.

Also if you can provide a plunkr that would be great because I've used this lib in IE11 as well and it was working fine so maybe you have some special use case.

@figuerres
Copy link
Author

what i have found so far is this:

the script runs that is adding the header in the browser.
Fiddler trace shows that the header is not present.
happens (as far as i can tell) when the code is from localhost / debug or my loading the app from a server.

i have code in app.component constructor that sets up the interceptor

constructor( private route: ActivatedRoute, private router: Router, private authService: AuthService, private menuService: MenuDataService , private http: Http, private httpInterceptor: HttpInterceptorService, ) { httpInterceptor.request().addInterceptor((data, method) => { const headers = getHttpHeadersOrInit(data, method); // Get or create header and set back ondata console.log("AppComponent this.authService ", this.authService ); console.log("AppComponent this.authService.loggedIn ", this.authService.loggedIn ); if( this.authService.loggedIn ){ console.log("AppComponent this.authService ", this.authService ); console.log("AppComponent this.authService.currentUser ", this.authService.currentUser); if( this.authService.currentUser ){ headers.append('Authorization', this.authService.currentUser.token_type + " " + this.authService.currentUser.access_token); console.log("token " , this.authService.currentUser.token_type + " " + this.authService.currentUser.access_token ); } } console.log(method, data); return data; }); }

the console.log calls all look normal in IE 11, no error other than the 401 result.

I will take a second look tomrrow and see if i can get more details.

@figuerres
Copy link
Author

I may have this figured out, will need to setup a test today and see what happens.
has to do with how chrome and edge do the OPTIONS call.
but IE 11 I do not see that call.

then i got to thinking about old web sites and that i have seen the header "WWW-Authenticate" in the past.

possibly IE 11 is looking for that stuff before it will send the token to the server ??

@figuerres
Copy link
Author

i added the www-auth header and no change.
i thought that my not sending that header was the problem but it does not seem to make a difference.

@gund
Copy link
Owner

gund commented May 24, 2017

Well I can only suggest you to create a plunkr so I can have a look.

@figuerres
Copy link
Author

will see what i can do, my app has multiple servers and is inside a private network, so a little complicated for me to replicate.
is there a token server that i can test against ?? i will see if i can find one...

@gund
Copy link
Owner

gund commented May 24, 2017

Maybe if you have different servers most probably they are on other domain and if so you have to deal with CORS policy where server should tell which headers it allows client to send.
I'm not sure how exactly CORS are implemented in IE11 but it might just remove some headers silently...

@figuerres
Copy link
Author

that is part of what i suspect is happening..... i am checking for what is going on and making a small test case, i did find an oath test server i may be able to use and test with. will let you know when i have more info.

@figuerres
Copy link
Author

i am trying to make a working plunk for IE but having some issues.
it works in chrome but hangs in IE due to some missing poly fill or something.
https://plnkr.co/edit/MX7j8Brm0tzQEVKzMCAs

i hard coded a token that works right now and pointed the code to my service.

if you can make this work in IE 11 try any service that needs a token....

@figuerres
Copy link
Author

ok so i am fail at plunker ....
here is a link:
https://github.com/figuerres/ie11test

angualr cli - current packages.

i can update the token a few times if you want to test with my service....

the project loads and runs in chrome and in IE 11 , but in IE 11 it fails to get the data with a 401 status as the token is never sent to the web service.

almost no code; just trying to add the auth header.

@figuerres
Copy link
Author

simple jquery works, so something in the angular / typescript seems to be failing.
kind of thought so but just tested to see what happens.
i wonder if there is a change in the angular http that breaks on IE 11 ?

@gund
Copy link
Owner

gund commented May 25, 2017

I will have a look to your plukr later. Regarding angular's http library it's unlikely that something is breaking in IE because they are testing angular in saucelabs in IE as well so...

@figuerres
Copy link
Author

thanks, i am going to try and see if i can figure out any more, i saw that the code to add the header was called in IE in my angular cli project so possibly the proxy ??
or in IE 11 something is not initialized right ??

@figuerres
Copy link
Author

i did a test of some code and i found this, not much but it might help:

if i use your library to watch the traffic but not modify the headers and i make an http post and add my own RequestOptions object with the header that works.

when i add a header with the ..... i think i found something .....

@figuerres
Copy link
Author

wow ok this is nuts and now i have to figure out how to bet handle this.....

IE 11 seems to need to have the http request options set or it fails.
this has not been a problem with chrome or with edge!

in my githhub code i added

var options = new RequestOptions({ withCredentials:true });
and then
this.http.post( 'https://devwebservice.adldelivery.com/api/SSRS/ListItemTypes','',options).subscribe(r => this.res = r.text());

and it works!!
i will take a look at your code and see if i can do that in the interceptor setup.... or if some other thing needs to be done.

@figuerres
Copy link
Author

works in a test case but not in my actual app code.... no idea why that is happening now.

@gund
Copy link
Owner

gund commented May 25, 2017

Ah, of course you have to set that flag, because you trying to send authorization headers. According to MDN:
The XMLHttpRequest.withCredentials property is a Boolean that indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates. Setting withCredentials has no effect on same-site requests.

So it shouldn't had been working even in chrome... A bug?!

Anyway you can set withCredentials flag from the interceptor, you can use some helper function to get Options from data and then set the flag.

@figuerres
Copy link
Author

you may be right!
i just knew that the app had been working for me with chrome and we have been testing IE 11 to get ready for a limited test release to dogfood some of the work we have so far....

and then i started down this rabbit hole ....

right now the main app is not working and i am going between the test code and the main app code and checking them.
there may be a package having a side effect in the main app code.... more fun to trace down.

@figuerres
Copy link
Author

@gund

Hey I think i have found a very odd bug but i am not 100% sure if this is with the code or with the way IE11 handles javascript data or what.

only in IE11 do i see this happening.

if the http call starts without an Options Arg then the token is not sent to the server even though the code seems to be creating the headers collection and adding them to the options .
if i initialize the http call with an empty request options arg with nothing set then it works like it does in chrome.
something about the data[] array / collection and modifying it going wrong on IE 11

i am looking at your code that gets the options from the array and playing with it to see if i can make it work on IE 11 .

seems odd, possibly some side effect of angualr cli ? i do not know for sure but it is happening and it is related to the options being in the http call before the interceptor gets into it.

@figuerres
Copy link
Author

ok more details ....
if the http.post . does not have options args set then the
data arguments has a size of 2 with arg 0 and arg 1 but no arg 2 for the options
in IE 11 the line that tried to set the options is setting data[2] but there is not data[2] in the arguments collection and arguments is not a true array and does not support slice/push/pop
on chrome it seems to allow adding an argument on the fly but on in IE 11
so the local variables are there but not added to the actual arguments that get passed back up the chain to the final call to http / ajax.

what i am doing in my code that is working in y test app and i will test this next in my main app
is to do an Array.from(data)

then i can call temp.splice(idx,0,options);
and then
data = temp

now the new options and headers are added and the call works.

so possibly this code:
https://github.com/gund/ng-http-interceptor/blob/master/src/http/helpers/getHttpHeadersOrInit.ts

// Set Options back
data[idx] = options;

should be changed to work that way ??

@gund
Copy link
Owner

gund commented May 26, 2017

Interesting finding, I don't remember that I checked the type of the arguments...

They are actually coming from the Proxy here.

Can you try to log the type of arguments in request interceptor in IE?

@gund
Copy link
Owner

gund commented May 26, 2017

Alright I just checked in IE and can confirm that Proxy polyfill returns Arguments Object instead of Array.
As a quick fix you can add in your request interceptor next line:

httpInterceptor.request().addInterceptor(data => Array.prototype.slice.call(data));

This will ensure that data is always Array no matter what.

This is only required if you ever going to use Proxy polyfill, so I'm not sure if I will add this piece of code to this library.
It should probably be in polyfill itself...

@figuerres
Copy link
Author

Crazy little detail for sure, took a bunch of tries to fully get at what was going on. At least now we know and can at least put a note in the docs for anyone who has to support ie. Also I let some folks at Microsoft know so they can also document the issue from the ie quirks side of things.
My boss was glad I was able to get it to work as we have customers still on ie 11 and Windows 7 along with some older pc in our warehouses.

@gund
Copy link
Owner

gund commented May 26, 2017

Yes, I just added a note to the readme page with link to this issue.
I also forked polyfill, patched it and submitted PR back so hopefully they will merge it.

Will close this as we sort of resolved it =)

@gund gund closed this as completed May 26, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants