Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leave domain empty in cookies, but account for clients with old cookies. #1102

Merged
merged 15 commits into from
Sep 16, 2020

Conversation

fisx
Copy link
Contributor

@fisx fisx commented May 18, 2020

Fixes https://github.com/zinfra/backend-issues/issues/953

#1076 breaks UX: clients attempting to get new tokens from /access with cookies they got before this change will receive an error, and will have to login again.

This PR does it right.

When multiple cookies are presented to the backend, all of them will be tested against the database. If any of them is valid, then we pick the "first" one and use that for auth purposes.

@fisx
Copy link
Contributor Author

fisx commented May 18, 2020

I've opened this with the changes from the earlier PR. Now we just need to figure out how to do it right.

@fisx
Copy link
Contributor Author

fisx commented May 18, 2020

@mythsunwind writes:

The current issues with our QA environments and former-used accounts are happening, because when /login is accessed, the browsers do not override the old cookie with ".zinfra.io" with the new cookie. Instead they then have two cookie. One cookie with a working token and Domain:"staging-nginz-https.zinfra.io" and one with an outdated cookie and Domain:.zinfra.io. Unfortunately it seems both Firefox and Chrome then send two zuid tokens which results in a 403 on backend.

So is it enough to just allow for the old cookie to be present, but ignore it?

@mythsunwind
Copy link
Collaborator

So is it enough to just allow for the old cookie to be present, but ignore it?

Here is an example of the Cookie header of a request headers done by Firefox when the staging backend had the issue:

zuid=O49aSGfTwRWCjOlIUzJSSI0S2OqQRx0qtj2wjo6YExDrWDKrCN02dd97Pux7PQCmm8bWYoRWTBe_rs1S0mQOBA==.v=1.k=1.d=1593608983.t=u.l=.u=a7adc996-f698-4275-b0e4-1980f7105fba.r=8ac45588; zuid=qqme0VEmQkgR1l6ZIw-o3BO-OBbYsujB5PgTWOXNAFs69ffHrt1sPIiN3ajC1DfBut7l86qi4XHvsgGaP77UDg==.v=1.k=1.d=1594647026.t=u.l=.u=26a193b9-c4de-4671-9140-71470651bf6d.r=1bd7e045

I hope this helps you.

@fisx fisx changed the title Leave domain empty in cookies, but account for clients with old cookies. [WIP] Leave domain empty in cookies, but account for clients with old cookies. May 19, 2020
@fisx
Copy link
Contributor Author

fisx commented May 19, 2020

106816c does this:

            test/integration/API/User/Auth.hs:213:
            every login must issue a new cookie

I'm probably missing something obvious?

@fisx fisx force-pushed the fisx/cookies-the-2nd branch 2 times, most recently from cf34bd0 to 5cf5d6c Compare May 25, 2020 14:37
@fisx fisx self-assigned this May 25, 2020
@fisx fisx force-pushed the fisx/cookies-the-2nd branch 3 times, most recently from ca23b06 to 46a6f79 Compare August 3, 2020 09:41
let Just email = userEmail u
dologin :: HasCallStack => Http ResponseLBS
dologin = login n (defEmailLogin email) PersistentCookie <!! const 200 === statusCode
outdatedCookie <- decodeCookie <$> dologin
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to make the outdated cookie look like a legacy cooikie! ie., different domain.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We just need to send 2 cookies

@@ -69,7 +69,6 @@ import Spar.Scim
import Spar.Scim.Swagger ()
import Spar.Types
import qualified URI.ByteString as URI
import qualified Web.Cookie as Cky
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also test that this behaves as expected!

@@ -135,7 +135,6 @@ optSettings:
setNexmo: test/resources/nexmo-credentials.yaml
# setStomp: test/resources/stomp-credentials.yaml
setUserMaxConnections: 16
setCookieDomain: 127.0.0.1
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this to integration.yaml

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need.

@tiago-loureiro tiago-loureiro changed the title [WIP] Leave domain empty in cookies, but account for clients with old cookies. Leave domain empty in cookies, but account for clients with old cookies. Sep 8, 2020
@tiago-loureiro tiago-loureiro marked this pull request as ready for review September 8, 2020 20:20
@tiago-loureiro
Copy link
Contributor

This is now ready for review. Could someone please run ormolu against it?

@tiago-loureiro
Copy link
Contributor

This is now ready for review. Could someone please run ormolu against it?

Nevermind, all good

@@ -411,9 +411,6 @@ data Settings = Settings
-- | Max. number of permanent clients per user
setUserMaxPermClients :: !(Maybe Int),
-- | The domain to restrict cookies to
setCookieDomain :: !Text,
-- | Whether to allow plain HTTP transmission
-- of cookies (for testing purposes only)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You removed the wrong comment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -1045,7 +1045,7 @@ setProviderCookie t r = do
Cookie.def
{ Cookie.setCookieName = "zprovider",
Cookie.setCookieValue = toByteString' t,
Cookie.setCookieDomain = Just $ Text.encodeUtf8 . setCookieDomain $ s,
Cookie.setCookieDomain = Nothing,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can just leave this line; Cookie.def already contains Cookie.setCookieDomain = Nothing

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

services/brig/src/Brig/User/API/Auth.hs Outdated Show resolved Hide resolved
services/brig/src/Brig/User/Auth.hs Outdated Show resolved Hide resolved
validateTokens [] _ = throwE ZAuth.Invalid
validateTokens (ut : []) at = validateToken ut at
validateTokens uts at = do
tokens <- forM uts $ \ut -> lift $ runExceptT (validateToken ut at)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
tokens <- forM uts $ \ut -> lift $ runExceptT (validateToken ut at)
tokens <- forM uts $ \ut -> (validateToken ut at)

lift . runExceptT is just id I think? No need to runExceptT and lift if validateToken and validateTokens are both already an ExceptT ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed it f2f; the reason is that we don't want to fail right away so the logic is correct. Will try to tackle the previous point as a cleanup.

services/brig/src/Brig/User/Auth/Cookie.hs Outdated Show resolved Hide resolved
services/brig/test/integration/API/User/Auth.hs Outdated Show resolved Hide resolved
services/brig/src/Brig/User/Auth.hs Show resolved Hide resolved
@tiago-loureiro
Copy link
Contributor

This is good to go from my end, all PR feedback was addressed now.

Copy link
Contributor

@mheinzel mheinzel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one small formatting nit, not a blocker. Looks good to me! :)

Copy link
Member

@jschaul jschaul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, too.

@tiago-loureiro tiago-loureiro merged commit 4acab3b into develop Sep 16, 2020
@tiago-loureiro tiago-loureiro deleted the fisx/cookies-the-2nd branch September 16, 2020 07:02
@jschaul jschaul mentioned this pull request Oct 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants