Duplicate Cookies in IE / Edge with Laravel 5 (TokenMismatchException) - internet-explorer-11

We have developed a website in Laravel 5.3, but only IE/Edge browsers have problem submitting forms (TokenMismatchException).
I tried some ways to fix it like this:
TokenMismatchException in Edge and IE 11 with Laravel 5 App.
However, P3P policy is no longer supported by IE11/Edge on windows 10.
Reference
I found the problem is that IE11/Edge stores duplicate cookies with the same key name (as string) although $_COOKIE stores only one for each keys (as array).
For example,
$_SERVER['HTTP_COOKIE'] = "laravel_session=aaaaa; laravel_session=bbbb"
$_COOKIE = array('laravel_session' => 'aaaaa')
I used a basic web middlewares such as
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
],
Basically, laravel request tries to use the value in $_COOKIE, but sometimes it is not the right one.
In the case, laravel fails decrypting the value (MAC is invalid error occurs in EncryptCookies middleware), so $request->cookies for the key becomes null, and TokenMismatchException is thrown in VerifyCsrfToken middleware.
Does anyone know when IE11/Edge stores duplicate cookies for the same key and how can we avoid it?
I cannot find a specific way to happen the problem, but it often happens in IE/Edge.
Here is some more references that may be related to this issue:
Subdomain issue?
IE protected mode + SSL?
IE protected mode cookie storage?
Apache issue?

Related

GoogleTokenResponse.getIdToken() returns null

Our server OAuth validation via Google has started throwing NullPointerException within GoogleTokenResponse.parseIdToken():
java.lang.NullPointerException:
at com.google.api.client.json.webtoken.JsonWebSignature$Parser.parse(JsonWebSignature.java:462)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.parse(GoogleIdToken.java:57)
at com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse.parseIdToken(GoogleTokenResponse.java:106)
This is new behavior that started today. There was no change to our server code (it has worked for months). The problem occurs only with credentials from one Android device -- I have another that works fine. Refreshing the client's server access token does not solve the problem.
The GoogleTokenResponse is being created by GoogleAuthorizationCodeTokenRequest(), that call succeeds and when I log the GoogleTokenResponse it looks valid:
{"access_token":"ya29.mwJvM...","expires_in":3600,"token_type":"Bearer"}
UPDATE: tested some more and found tokenResponse.getIdToken() is returning null, so I assume that's what's causing the NPE when I call parseIdToken().
What would cause getIdToken() to return null when GoogleAuthorizationCodeTokenRequest() apparently succeeded and there is an access token?
Final resolution: this issue appears to be triggered intermittently by the Google Play Services update in early 2016 to anonymize PlayerID. We were able to fix our problems by changing our server validation of the access token to a newer method instead of relying on the older getIdToken()/parseIdToken() methods. See the last UPDATE below for details
After two days the Android device with this failure mysteriously started to work again. So the cause may be a transient error in the client's Google Play Services state which self-corrected. The fix occurred after a device reboot.
However I'm not certain that was the cause. There are also Play Services changes rolling out to enable authentication without exposing the G+ user ID -- another explanation is the server was not being given scope to retrieve the ID. (If that was the cause, then again the fix must have been deployed by Google as we have not changed anything)
We'll continue to monitor it, if anyone else runs into this add a comment please.
4/19/16 This problem has occurred on a different device. I am wondering if this is related to the Google Play auth changes described here http://android-developers.blogspot.com/2016/01/play-games-permissions-are-changing-in.html?m=1
That explanation is a bit sparse but it does say "The user_id returned by token info may no longer be present with the new model. And even if it is present, the value won’t be the same as the new player ID"
In this case the problem occurred after
Device had previously authorized with Google Play Services in the old G+-style
App data was cleared so re-auth was necessary
During re-auth GPS prompted for the new GPS-only player ID (not real name), which makes me wonder if it switched that device to the new non-G+ ID
Then server calls to tokenResponse.getIdToken() returned null
I'm not yet sure what's happening but researching two areas of concern:
1) Although the Google docs referenced above say "existing players ... will continue to get their Google+ ID" I'm wondering if this is managed per-client. That would be a big problem because we use that ID to store cloud state for a user across devices, so if a user who originally set up their account before the new player ID then installed the app on a second device, they could sign in with gplay but the two accounts would not match
2) If this is the cause, then either our server code fails to work with the new non-G+ player ID, or there is a google back-end bug when a device transitions between the two. This is still confusing though because our prior problem did self-correct after a couple of days, which implies the server code is fine -- but I'm sure hoping the alternate explanation of a bug with google back-end auth is wrong!
--- UPDATE
I think the issue is related to the new GPS anonymized PlayerID changes. It has been hard to debug because it appears that Google's legacy server auth flow, which requires a non-null GoogleTokenResponse.getIdToken(), fails for a newly created GPS PlayerID, but after 12-24 h the problem seems to self-correct and the legacy Google auth calls begin to succeed including returning a non-null getIdToken().
However I tried implementing the new PlayerID flow in the Step 7 of the google info page above which converts the access token (generated from a server auth code) to a Player ID via www.googleapis.com/games/v1/applications//verify/
This code successfully retrieves a Player ID from the accessToken even when getToken() returns null:
// URL: www.googleapis.com/games/v1/applications/<app_id>/verify/
URL url = new URL("https://www.googleapis.com/games/v1/applications/" + GPlayServicesAppId + "/verify/");
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestProperty("Authorization", "OAuth " + accessToken);
httpConnection.setRequestMethod("GET");
int responseCode = httpConnection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
...
}
BufferedReader reader = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
String responseJson = (read contents of reader)
// Example response: { "kind": "games#applicationVerifyResponse", "player_id": "11520..."}
I ran some tests, far as I can tell the new method works in all cases where the older G+ getToken() method works as well as fixing the cases where it doesn't, so I believe we can just switch to the new method in the code snippet above and hopefully that will be reliable.

Why isn't a client-side HTTP.get() call working in Cordova (Meteor 0.9.3)?

UPDATED QUESTION:
A simple client-side HTTP.get() call is not working on the iOS emulator. The same call is fetching data and its displaying perfectly in my templates in the browser (localhost:3000)
Earlier I thought this got to do with local collections, but the problem is actually with the HTTP.get call which is not returning any data within cordova (ios emulator or device).
Please note that my entire code is only on the client if (Meteor.isClient) {} and nothing in if (Meteor.isCordova) {}.
ORIGINAL QUESTION: Is it possible to define a local collection in Cordova (Meteor 0.9.3)?
I have a local(client-only) collection in my app as shown:
Items = new Meteor.Collection(null);
This local collection temporarily gets data from an external API ( by adding 'meteor add http' and using HTTP.get() ) and this content is pushed to the templates. This is appearing perfectly in the browser templates on localhost:3000 through the helpers ( return Items.find() ), but when I run 'meteor run ios', the data is not loading up in the iOS simulator.
First of all, is it even possible to expect a local collection to work within Cordova?
Should this be defined inside:
Meteor.isCordova({ })?
Does it require a cordova-specific package to be added?
I believe a local collection is necessary in this case because the data is retrieved based on the user's device location and its relevant only for the current session.
Any thoughts would be appreciated.
(meteor noob here, sorry if this sounds stupid!)
EDIT: Collections defined both on the server and client are working in the browser as well as on iOS emulator. So the problem is only with local collections.
#imslavko
You're indeed right! Its the CORS issue on the server to which I was making the API call.
After a couple of days of breaking my head, I eventually figured out the server did not have Access-Control-Allow-Origin: * for simple GET/POST requests.
Thanks for your help in figuring this out.
So it turns out Cordova has nothing to do with this. All HTTP.get() calls are working perfectly from within Cordova too including local collections.
There's one more trick to be aware of.
HTTP.get('/route') will likely end up in the phones local server instead of the remote server the data comes from - so you wont be receiving the data you'd expect.
Instead use
HTTP.get(__meteor_runtime_config__.ROOT_URL + '/route')
Because the ROOT_URL variable points to the correct server in both Cordova apps and normal browsers.

Laravel 4: when using Config::set to change auth.model then Auth::user() not work

My laravel project has two login system.
1) Using user_name and Password
2) Using secret code
my 1st login system work properly. because auth.model has 'User' model.
so I use 'Config::set' in 'tempSing' method to obtain 2nd login as bellow.
Config::set('auth.model', 'TempUser')
Config::set('auth.table', 'temp_user')
After that code I use bellow code
$user= TempUser::where('secret_code','=',Input::get('code'))->first();
Auth::login($user,true);
if(Auth::check())
return Redirect::route('getTemp');
then that code work properly and redirect to the 'getTemp' and after routing it make 'temp.php'. but their include
if(Auth::check())
so my problem is above logic not become true. that problem is occurred when using 'Config::set' but I Configured 'auth.model' and 'auth.table' manualy in 'auth.php' not happen any error. Please help me.
I would assume Laravel initializes the Auth service once when the application is started, so later edits to configuration don't affect it anymore. A solution would be to initialize an instance yourself, and use that.

SQL Network Interfaces, error: 26 only on solution rebuild

I have a site built using MVC4 which is getting content out of a database and it all works fine.
If I then rebuild the solution and try to refresh the page to check my changes, I will always get the SQL Network Interfaces, error: 26 saying that I cannot connect to the server.
However, if I then browse to my homepage and then back to the page I was looking at it will work fine.
Does anyone know what could cause this problem as it is really annoying
EDIT
Further to this I have found it is when the AuthorizationContext filterContext is being loaded after the rebuild that it cannot connect to the db
EDIT 2
As with neil below I have found that I only get the problem if I try to access a page that has had a role assigned to it
I'm seeing the exact same problem and can trace it to the .ASPXAUTH session cookie in the browser. Delete that cookie and the database error goes away until the next rebuild.
The error occurs regularly if you are authenticated and then rebuild the project and try to browse any page that either:
Requires authentication
Makes a call to the User object (e.g. #if (User.IsInRole("Administrators")))
If you have the AuthorizeAttribute filter set in App_Start/FilterConfig.cs you'll get this on every page.
This seems to be new behavior following the most recent Patch Tuesday updates. Previously, I was seeing weird behavior where I would remain logged in but I would loose my roll membership. After the most recent patches, it seems Simple Membership chokes when it gets a bad .ASPXAUTH cookie (invalid because of the rebuild).
I've got the correct connection string in InitializeSimpleMembershipAttribute.cs but it's like Simple Membership is defaulting to something else in this one instance.
Note that I've moved the Simple Membership databases from the original (localDb) to a full-fledged (local) SQL Server instance. Don't know why that would matter, and it works fine in all other cases.
Update:
I've also tried making the connection string name the same as the EF context name (e.g. "ProjectContext") on the theory that it is defaulting to the standard convention, but that made no difference. I am explicitly identifying the connection string name in all my context class constructors (using the : base("connectionString") syntax) and Simple Membership is able to find the right connection string all other times.
Update 2:
The problem only occurs after rebuild when accessing a page protected by role. A simple [Authorize] won't trigger it. You need something like [Authorize(Role="Admin")]. I've replicated this on a new MVC 4 project with no other modifications, using the default (localDb) database. Clear the cookie and that same user can access the protected content w/o any problems. I believe this is a core .NET or MVC bug and needs to be reported as such.
This happened to me while rebuilding the application when I was logged in the browser.
Deleting cookies fixed the problem for me.
When using SimpleMembership, this bug occurs with any use of Roles-not just in the controller, but also when I use:
if(Roles.IsUserInRole(rolename){...
I am late to the game with this answer, but I added [InitializeSimpleMembership] to my home controller and I think that fixed it.

Using java servlet store doesn't work in my Jruby on Rails application running in Tomcat

I'm trying to use the java servlet store instead of the :cookie_store when running in Tomcat. My application runs fine with the :cookie_store, but when using the :java_servlet_store, nothing gets stored no longer...
This seems to work, however, when I store something in the servlet_request.session, later on, I can't seem to get the value again... It seems to be gone...
In my session_store.rb:
require 'action_controller/session/java_servlet_store'
NameApplication::Application.config.session_store :java_servlet_store
In my application_controller.rb:
servlet_request.session.putValue(PROXYBRIDGEKEY, proxy_bridge)
seems to be working
But later on I'm trying to get the value and I'm getting nil...
servlet_request.session.getValue(PROXYBRIDGEKEY)
Any ideas as what could be the problem here?
To be clear, putting the value in the session does work (tested that). With a new html request, getting the value doesn't work anymore. So, there must be a problem with getting the cookie I guess...
One thing that you could try is defining your store as:
require 'action_controller/session/java_servlet_store'
NameApplication::Application.config.session_store :java_servlet_store, :key => "MyKey"
I'm not sure it's relevant, but it was necessary for the :cookie_store. It could make sense that you need to identify your servlet key in the java_servlet_store as well. This key will be the key of the cookie sent to the browser for subsequent requests.
Hope this helps.
If that didn't work for you, also make sure that you set the java_servlet_store key to "JSESSIONID" to use the standard JVM session.
From there in Ruby, all you need to do to read and write session (this will be accessing the JVM session object):
session.id
session[:yoursessionvariable]
Note: If you have not initialized session (assign a session variable value), session will be nil (making session.id undefined) until you do so.