Bug 188165 - iOS 12 Safari breaks ASP.NET Core 2.1 OIDC authentication
Summary: iOS 12 Safari breaks ASP.NET Core 2.1 OIDC authentication
Status: RESOLVED INVALID
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore Misc. (show other bugs)
Version: Safari Technology Preview
Hardware: iPhone / iPad Other
: P2 Critical
Assignee: Daniel Bates
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2018-07-30 06:39 PDT by Jan Hajek
Modified: 2021-09-13 10:10 PDT (History)
31 users (show)

See Also:


Attachments
curl.log (2.51 KB, text/x-log)
2018-10-03 02:48 PDT, Lode Claassen
no flags Details
same_site_cookie.rb (2.10 KB, text/x-ruby-script)
2018-12-12 14:38 PST, Daniel Bates
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Hajek 2018-07-30 06:39:52 PDT
When authenticating with ASP.NET Core 2.0 with OpenID Connect, the Identity cookie doesn't seem to be set when returning back from IdP which results in redirect loop. This same process works with iOS 11.

1. Visit site, access some protected resource
2. Set nonce, dedirect to IdP
3. Authenticate at IdP
4. Return back with POST request
5. Validate id_token, set identity cookie with samesite=lax policy
6. Redirect to the protected resource
7. Check for identity cookie - missing, return to step 2

I tested the same flow on PC (Edge, Firefox, Chrome) everything works fine (they all implement samesite policy - https://caniuse.com/#feat=same-site-cookie-attribute). Any idea why Safari treats this case different?

This is probably going to affect quite a lot of users accessing Microsoft's own services as well (for example https://admin.teams.microsoft.com) - once again, this site works just fine on Chrome or Edge.
Comment 1 Radar WebKit Bug Importer 2018-07-30 08:13:23 PDT
<rdar://problem/42732352>
Comment 2 David Cowden 2018-09-24 17:33:04 PDT
I'm chiming in to let people know this affects our own SSO infrastructure as well. We have an internal service that handles OIDC with an Okta instance (which, in turn, does upstream identity management--aka SAML--with the providers we support). The flow is essentially:

1. our internal service sets a CSRF token on the first request and redirects us with an enriched URL containing OIDC arguments to our Okta instance, 
2. we OIDC->SAML bounce through Okta to the upstream IDP (a POST request is made during the SAML process), 
3. IDP authenticates user (possibly a second POST request is made if the user (re)authenticates upstream),
4. on the return trip when we are redirected to our internal service, we check the CSRF token set on the initial request, and handle the nonce provided by Okta,
5. ...internal service completes OIDC and redirects us to our desired final location...

The flow works on iOS < 12. On iOS 12 we don't see the CSRF token on the return trip, and step 4 fails. Interestingly, if the user actively refreshes the browser window, the cookie is sent which results in successful completion of the flow.

So this lead us to [RFC6265 §5.3.7](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.3.7) which describes the mechanics of the `SameSite` cookie policy. Our CSRF cookie SameSite policy is set to `lax`. According to §5.3.7.1:

>  developers may set the "SameSite" attribute in a "Lax"
   enforcement mode that carves out an exception which sends same-site
   cookies along with cross-site requests if and only if they are top-
   level navigations which use a "safe" (in the [RFC7231] sense) HTTP
   method.

According to RFC7231, "safe" methods are only those methods which are idempotent. Specifically, a POST request is not "safe". Because our "top-level navigation" in the flow does not consist of strictly "safe" methods, WebKit is, as far as we understand, correctly interpreting RFC6265--which explains why the user-agent does not send our CSRF token and consequently step 4 fails. It also explains why refreshing the browser causes the cookie to be sent.

As stated, there is a discrepancy between previous WebKits and the version shipped with iOS 12. And indeed, other major non-webkit browsers claiming to support the `SameSite` attribute operate similar to the WebKit shipped with iOS < 12. However,  [RFC6265 §8.8.3](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-8.8.3) states:

>  Likewise, some forms of Single-Sign-On might require cookie-based
   authentication in a cross-site context; these mechanisms will not
   function as intended with same-site cookies.

Removing the `SameSite` policy from our CSRF cookie resolves the issue and appears to be the intended solution. But, it feels weird that we're removing the `SameSite` policy from a cookie intended to defend against cross-site attacks...
Comment 3 John Wilander 2018-09-25 10:30:55 PDT
(In reply to David Cowden from comment #2)
> I'm chiming in to let people know this affects our own SSO infrastructure as
> well. We have an internal service that handles OIDC with an Okta instance
> (which, in turn, does upstream identity management--aka SAML--with the
> providers we support). The flow is essentially:
> 
> 1. our internal service sets a CSRF token on the first request and redirects
> us with an enriched URL containing OIDC arguments to our Okta instance, 
> 2. we OIDC->SAML bounce through Okta to the upstream IDP (a POST request is
> made during the SAML process), 
> 3. IDP authenticates user (possibly a second POST request is made if the
> user (re)authenticates upstream),
> 4. on the return trip when we are redirected to our internal service, we
> check the CSRF token set on the initial request, and handle the nonce
> provided by Okta,
> 5. ...internal service completes OIDC and redirects us to our desired final
> location...
> 
> The flow works on iOS < 12. On iOS 12 we don't see the CSRF token on the
> return trip, and step 4 fails. Interestingly, if the user actively refreshes
> the browser window, the cookie is sent which results in successful
> completion of the flow.
> 
> So this lead us to [RFC6265
> §5.3.7](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-
> 5.3.7) which describes the mechanics of the `SameSite` cookie policy. Our
> CSRF cookie SameSite policy is set to `lax`. According to §5.3.7.1:
> 
> >  developers may set the "SameSite" attribute in a "Lax"
>    enforcement mode that carves out an exception which sends same-site
>    cookies along with cross-site requests if and only if they are top-
>    level navigations which use a "safe" (in the [RFC7231] sense) HTTP
>    method.
> 
> According to RFC7231, "safe" methods are only those methods which are
> idempotent. Specifically, a POST request is not "safe". Because our
> "top-level navigation" in the flow does not consist of strictly "safe"
> methods, WebKit is, as far as we understand, correctly interpreting
> RFC6265--which explains why the user-agent does not send our CSRF token and
> consequently step 4 fails. It also explains why refreshing the browser
> causes the cookie to be sent.
> 
> As stated, there is a discrepancy between previous WebKits and the version
> shipped with iOS 12. And indeed, other major non-webkit browsers claiming to
> support the `SameSite` attribute operate similar to the WebKit shipped with
> iOS < 12. However,  [RFC6265
> §8.8.3](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-
> 8.8.3) states:
> 
> >  Likewise, some forms of Single-Sign-On might require cookie-based
>    authentication in a cross-site context; these mechanisms will not
>    function as intended with same-site cookies.
> 
> Removing the `SameSite` policy from our CSRF cookie resolves the issue and
> appears to be the intended solution. But, it feels weird that we're removing
> the `SameSite` policy from a cookie intended to defend against cross-site
> attacks...

It sounds like this should be resolved as Behaves Correctly then. And bugs should be opened for the other browsers.
Comment 4 David Cowden 2018-09-25 16:40:22 PDT
(In reply to John Wilander from comment #3)
> It sounds like this should be resolved as Behaves Correctly then. And bugs
> should be opened for the other browsers.

Keep in mind RFC6265 is a draft and it appears to be expired. I'm not sure what WebKit's policy is with respect to IETF draft proposals. I did a quick search of the archives but couldn't find any discussion about revising or extending the draft so this may explain why other vendors don't seem to have implemented it yet. Here is the link to the document in the ITEF datatracker for convenience: https://datatracker.ietf.org/doc/draft-ietf-httpbis-rfc6265bis/
Comment 5 David Cowden 2018-09-25 16:58:00 PDT
(In reply to David Cowden from comment #4)
> (In reply to John Wilander from comment #3)
> > It sounds like this should be resolved as Behaves Correctly then. And bugs
> > should be opened for the other browsers.
> 
> Keep in mind RFC6265 is a draft and it appears to be expired. I'm not sure
> what WebKit's policy is with respect to IETF draft proposals. I did a quick
> search of the archives but couldn't find any discussion about revising or
> extending the draft so this may explain why other vendors don't seem to have
> implemented it yet. ...

Let me clarify. If another vendor /claims/ to support the `SameSite` attribute, and their implementations exhibits the behavior of WebKit < 12, and they are working off RFC6265, then I believe a bug should be filed against their project. 

If WebKit is okay with an implementation guided by a draft proposal, then I believe the implementation Behaves Correctly.
Comment 6 Nicolás Sabena 2018-09-28 03:50:19 PDT
A quick note to those using ASP.Net Core 2.0: you can work around this limitation by changing the response mode from the identity provider to be a GET instead of a POST:

.AddOpenIdConnect("Auth0", options => {
    [...] // other options
    // Set response type to code and response type to query
    // to avoid the default response_mode=form_post
    // which causes issues with WebKit's handling of samesite=lax for the session cookie
    options.ResponseType = "code";
    options.ResponseMode = "query";
};

This should work as long as the IdP supports a query response mode (which most do). The middleware won't send response_mode=query in this case as it is the default one.
Another workaround would be removing the samesite=lax policy for the session cookie, but that would be a bad idea overall in terms of security.
Comment 7 Tim Powell 2018-10-01 11:17:59 PDT
The bug appears to be that it is applying SameSite restrictions to redirects if the initial request was not considered "safe"  The two hosts in this flow are Target and IDP

In the original repro given:

1. Visit site, access some protected resource  (SameSite applies none->Target, but we aren't sending cookies)
2. Set nonce, redirect to IdP (SameSite applies Target->IDP, do not send cookies if IDP's cookies are strict, but ok if lax because GET is considered safe)
3. Authenticate at IdP (SameSite doe not apply, IDP->IDP)
4. Return back with POST request (SameSite applies IDP->Target do not send cookies because POST is considered unsafe)
5. Validate id_token, set identity cookie with samesite=lax policy (Still part of step 4...)
6. Redirect to the protected resource (SameSite does not apply, Target->Target should send cookies set in step4/5 **THIS DOES NOT HAPPEN**)
7. Check for identity cookie - missing, return to step 2
Comment 8 John Wilander 2018-10-01 12:29:31 PDT
Cc:ing Dan Bates. Dan, do you mind having a look to see if you want our behavior to be what the various reporters say above? If so, you can resolve the bug.
Comment 9 Lode Claassen 2018-10-03 02:48:09 PDT
Created attachment 351498 [details]
curl.log

I'm having the same issue w/o POST requests but has a redirect from a MailChimp tracking link. Else said: a link from a MailChimp campaign redirects to our domain which doesn't receive SameSite=Lax cookies in iOS 12 + Safari.

Is this because the browser thinks the request is anyway not safe because it contains query parameters?

Attached is a combined log of the curl command I used, curl's output, and nginx logs from our domain (to show it is indeed GET requests).

(I was doubting between commenting here or opening a new report, I chose to comment as other comments also mention GET requests, but I'm willing to open a new report if that is easier to handle.)
Comment 10 Matt W 2018-10-03 16:00:47 PDT
Just like Lode has reported, we see this problem with OpenIDC flows through Nginx (effectively using this example https://github.com/zmartzone/lua-resty-openidc#sample-configuration-for-passing-bearer-oauth-20-access-tokens-as-cookie) using Okta as our authentication provider.

The flow is using request_type=code and request_mode=query (so a GET request with query parameters) and it seems that Safari on iOS12/Mojave decides the site is insecure and will not pass the session cookie back to the Nginx server. Per all the other comments, removing Samesite entirely from our cookie does solve the problem - but obviously that is not a realistic solution.

It seems to me that while blocking the cookie on POST (request_mode=form_post) to the client server makes sense, blocking on the GET doesn't at all.. this completely breaks OpenIDC flows pretty much all around.
Comment 11 David Cowden 2018-10-03 16:44:39 PDT
(In reply to Matt W from comment #10)
> 
> ... Per all the other comments, removing Samesite entirely from our
> cookie does solve the problem - but obviously that is not a realistic
> solution.
>

Isn't an OIDC flow technically just a "benevolent cross-site transfer"? It's the exact attack the SameSite attribute (applied to a CSRF cookie) is trying to defend against. How does the browser distinguish an intended redirect from a malicious one?

Of course if the behavior is broken even for RFC7231 "safe" flows, that's a problem.
Comment 12 Matt W 2018-10-03 17:41:23 PDT
David,
  You're right - OIDC is indeed a benevolent cross-site transfer. I see this issue has having two parts.

First, Webkit went off and probably did the "right" thing by following the RFC explicitly and when Samesite=Lax, they go ahead and block the passing of the cookie to the original server on unsafe request types (request_mode=form_post). This is really just a more "RFC-correct" way of enforcing this behavior, which it seems like other browsers may have been more flexible on.

Second, and this is really the bug I think, it seems that WebKit is also blocking SAFE [1] web requests like GETs which are used when request_mode=query. The RFC [2] clearly specifies that these "safe" methods should be allowed to pass the cookie along even in a cross-site pattern: 

  "In the
   interests of providing a drop-in mechanism that mitigates the risk of
   CSRF attacks, developers may set the "SameSite" attribute in a "Lax"
   enforcement mode that carves out an exception which sends same-site
   cookies along with cross-site requests if and only if they are top-
   level navigations which use a "safe" (in the [RFC7231] sense) HTTP
   method."


It seems to me that this is the crux of the bug - that the Samesite:Lax attribute cannot be used with this new version of Webkit, even though the RFC says it should be fine.

1: https://tools.ietf.org/html/rfc7231#section-4.2.1
2: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.3.7
Comment 13 Lode Claassen 2018-10-04 03:32:20 PDT
A tricky part of the https://tools.ietf.org/html/rfc7231#section-4.2.1 spec is this:

> When a resource is constructed such that parameters within the
> effective request URI have the effect of selecting an action, it is
> the resource owner's responsibility to ensure that the action is
> consistent with the request method semantics.  For example, it is
> common for Web-based content editing software to use actions within
> query parameters, such as "page?do=delete".  If the purpose of such a
> resource is to perform an unsafe action, then the resource owner MUST
> disable or disallow that action when it is accessed using a safe
> request method.  Failure to do so will result in unfortunate side
> effects when automated processes perform a GET on every URI reference
> for the sake of link maintenance, pre-fetching, building a search
> index, etc.

To me (but I'm not a professional reading specs :)) sounds like browsers are free to determine whether a request is unsafe even though it is a GET request, e.g. based on query parameters.

What we see after more testing is that this is even an issue without query parameters, it seems just because we redirect from a different domain. So `bit.ly/x` > `example.org/` won't send SameSite=Lax cookies.

What I find weird, is that Safari 12 on MacOS desktop doesn't have this issue. So iOS 12 Safari is behaving differently here.

So if this is not a bug but a feature, it would be nice if both browsers behave the same. Than we can expect other browsers to follow and can adjust our flows. Now it feels like a bug.
Comment 14 Matt W 2018-10-04 09:40:20 PDT
Lode,
  In your Safari 12 testing - are you on Mojave or High Sierra? We can reliably reproduce the failure (on a response_mode=query GET call) on Mojave with Safari 12 and 12.1 Preview. On High Sierra with Safari 11, or Safari 12.1 Preview, it works fine. It seems to be some underlying OS-level library giving fits?
Comment 15 Matt W 2018-10-04 10:17:58 PDT
Here's the code that explains why Safari 12 behaves differently on iOS 12 and Mac OS X 14: https://github.com/WebKit/webkit/blob/a71803450aa3a7aac8b0a986219dd75353183cb1/Source/WebCore/platform/network/cocoa/CookieCocoa.mm#L87-L98
Comment 16 Matt W 2018-10-04 10:29:56 PDT
Digging through the primary commits that added SameSite support (https://github.com/WebKit/webkit/commit/91ac5b831f84731aad164b48d53007f6e82d60d2#diff-ffea2dff562d822fbb0d8096d94ead16), I haven't found any references to validating whether or not a cookie should be seen based on its HTTP Method, or even based on whether SameSite is Lax or Strict. Can any of the developers point us to the code where this decision is made, so that we can see how its implemented?
Comment 17 Daniel Bates 2018-10-04 22:13:25 PDT
I am reading through this thread. I appreciate all the detailed steps. Can someone save me some time and put together a test case and/or provide an example site that exhibits the issues?
Comment 18 Daniel Bates 2018-10-04 22:17:23 PDT
(In reply to Matt W from comment #16)
> Digging through the primary commits that added SameSite support
> (https://github.com/WebKit/webkit/commit/
> 91ac5b831f84731aad164b48d53007f6e82d60d2#diff-
> ffea2dff562d822fbb0d8096d94ead16), I haven't found any references to
> validating whether or not a cookie should be seen based on its HTTP Method,
> or even based on whether SameSite is Lax or Strict. Can any of the
> developers point us to the code where this decision is made, so that we can
> see how its implemented?

This logic is in CFNetwork. Its source is not public.
Comment 19 Lode Claassen 2018-10-05 13:55:40 PDT
Matt, thanks for my blind spot, I'll see if I can test that (will become next week).

Daniel, you can use the website I used although it is in Dutch.

- I've setup an account for you to use. You can go to https://decorrespondent.nl/account/wachtwoord-herstellen en fill in your email address. You'll then receive an email with a link to reset your password.
- The page asks for a new password. After that you're redirected to our logged-in homepage, noticeable by your name in the top right. Later, you can login (with a two-step process first email address then password) via https://decorrespondent.nl/inloggen.
- You should have a cookie called 'session' which has the SameSite attribute set to Lax.
- You can use the MailChimp link in the curl.log attachment, or you can make a bit.ly link to for example https://decorrespondent.nl/instellingen if you don't want to send your data to MailChimp :)
- When you open one of those pages you should see your name in the top right, and in a private window you shouldn't be able to access it and get redirected to the login page.
- When logged in to the website and using iOS 12 + Safari, you should be able to open the direct links, but the MailChimp/bit.ly redirect will show the login page.

Hope this is clear and can help debugging!
Otherwise I could setup a simple example case next week.
Comment 20 Matt Roberts 2018-12-03 02:08:39 PST
CC:  Nicolás Sabena

Hi - you mentioned a workaround for asp.net core that allows GET requests to work. The trouble for me is that by removing "id_token" from the response type, I'm unable to find out the email address of the user once they've completed the flow - all I can get is a access code.

Do you know how I can get the emaail address too, using this workaround you posted?

Cheers.

Matt
Comment 21 Nicolás Sabena 2018-12-04 12:20:51 PST
Hi Matt Roberts. 
Just to clarify, my change means that the response from the authorization server to the application happens in a GET (as opposed to a POST), which seems to play nicer with WebKit's restrictions.

By changing the response_type to "code", you force the use of the "authorization code flow" (as opposed to the default "hybrid flow"), which means that authorization server returns a code through a GET (redirect). From the application perspective, there needs to be a request to the token endpoint, to exchange the received code for the access token and ID token (assuming that the scope included "openid"). This is of course not ideal (an extra request is needed, plus you need to manage the client secret to authorize the request to the token endpoint).

But, at least in my tests, this token exchange was done automatically by the .Net Core OIDC middleware, so I get the claims from the ID Token transparently (i.e. no other changes in code needed).
Comment 22 Dominik Fijas 2018-12-05 19:35:06 PST
Hi, is WebKit team gonna handle this issue any time soon?

I'm asking as it causes the redirect loop even if I'm using GET redirect (which as I understand should be perfectly safe).

Just to confirm: the flow works when I remove the 'SameSite=Lax' cookie attribute.
Comment 23 Dominik Fijas 2018-12-07 03:02:42 PST
Hi Daniel Bates,

Is there any reason why this bug has not been assigned to you? :)

According to https://webkit.org/bug-life-cycle/ I would expect it to be assigned to someone from the WebKit team who would verify it and change the status from 'NEW' to 'ASSIGNED' (and then proceed further).

Now, after almost half a year, this bug looks kind of forgotten which is quite surprising if we consider how serious it is.

I hope it is not forgotten :)
Comment 24 Dominik Fijas 2018-12-11 03:46:56 PST
Thanks for assigning the issue, Daniel :)

Together with one of my coworkers we prepared sample app which gives ability to reproduce the bug easily.

Here is the code: https://gist.github.com/domininik/06e7dfa0fa0daf30d5584ed5740b1ce9

You can simply run the server with `ruby same_site_cookie.rb`, visit http://a.lvh.me:3000, click the button and see if cookie is set or not.

As we already discussed here it is set properly in Safari 12 running on High Sierra OS and it's not in the same, latest Safari running on Mojave OS.

Obviously it also works when you remove `SameSite=Lax` attribute from the code.

I hope it'll help with further steps :)
Comment 25 Daniel Bates 2018-12-12 14:38:43 PST
Created attachment 357167 [details]
same_site_cookie.rb

For historical preservation, a copy of same_site_cookie.rb as it was downloaded from <https://gist.github.com/domininik/06e7dfa0fa0daf30d5584ed5740b1ce9> on 12/12/2018.
Comment 26 Nicolás Sabena 2018-12-15 03:48:16 PST
(In reply to Nicolás Sabena from comment #6)
> A quick note to those using ASP.Net Core 2.0: you can work around this
> limitation by changing the response mode from the identity provider to be a
> GET instead of a POST:
> 
> .AddOpenIdConnect("Auth0", options => {
>     [...] // other options
>     // Set response type to code and response type to query
>     // to avoid the default response_mode=form_post
>     // which causes issues with WebKit's handling of samesite=lax for the
> session cookie
>     options.ResponseType = "code";
>     options.ResponseMode = "query";
> };
> 
> This should work as long as the IdP supports a query response mode (which
> most do). The middleware won't send response_mode=query in this case as it
> is the default one.
> Another workaround would be removing the samesite=lax policy for the session
> cookie, but that would be a bad idea overall in terms of security.

CC: Matt Roberts

Found out that just preventing response_mode=form_post won't help if there's any other POST involved in the authentication flow.

Take a look at https://community.auth0.com/t/authentication-broken-on-asp-net-core-and-safari-on-ios-12-mojave-take-2/19104 for a different workaround, which involves ending the authentication flow (after the OIDc callback processing) in an intermediate page (unauthenticated, because the session cookie is blocked here). That intermediate page simply does a GET to the final destination (ReturnURL), and the GET now includes the cookie.
Comment 27 Daniel Bates 2018-12-17 13:29:02 PST
Thanks Dominik Fijas for the test case. Using that test case I have confirmed that the issue reproduces and is in CFNetwork. CFNetwork does not appear to be saving Same-Site Lax cookies included in the response to a cross-site, top-level navigation. Moving this bug to Resolved Moved as this bug is not in WebKit and <rdar://problem/42732352> is tracking the fix.
Comment 28 Daniel Bates 2018-12-17 13:30:42 PST
Re-opening this bug to track adding tests once <rdar://problem/42732352> is fixed to identify a future regression to the fix.
Comment 29 Dominik Fijas 2018-12-17 18:47:43 PST
Thanks.

Is there any way we can track what is going on with rdar://problem/42732352?
I tried https://openradar.appspot.com and https://bugreport.apple.com/web/ with no luck.
Comment 30 Dominik Fijas 2019-01-03 03:55:30 PST
Hi and Happy New Year! :) 
Any updates from Safari team?
I'm not sure if I can track it myself.
Comment 31 Matt Roberts 2019-01-03 06:43:13 PST
cc: Nicolás Sabena

Hey there, thanks for the info here ;) I've got it working but I'm currently using your GET hack to force a get rather than a post. I guess that since there aren't any additional POST requests going on, I'm good. But I'll bear your other suggestion in mind. TBH, I'm hopefull that this get's resoved before soon, there must be a fair few sites out there in the wild that are affected by this.
Comment 32 snekbaev 2019-01-04 03:31:13 PST
Hi,

this might be related to the LAX cookie setting too.
I'm using the Shibboleth https://en.wikipedia.org/wiki/Shibboleth_(Shibboleth_Consortium) software to do the authentication. Path is: my public site does a POST to my SP (service provider) site. SP site creates a cookie with the value passed from the initial POST and then starts the WAYF (authentication process, where user selects his university/school, then is redirected to the IdP (identity provider) of that organisation where authentication via school credentials is done. After that the remote IdP does a GET back to my SP). At this moment as the first operation my SP tries to read the cookie that it has previously created, but cookie doesn't seem to be there, thus it can't continue. Implementation and configuration was done about 3 month ago and it seemed to be ok. However, recently I'm getting reports from users who can't complete the process because of this. Judging from the screenshots it seems to be an iPhone Safari, probably more reports to follow soon. As the solution for now I'm advising them to use Chrome.

How exactly this is planned to be addressed in the end, i.e. will work like in, say, Chrome?

Thank you!

P.S.: meanwhile I'll try to get a mac book to test this
Comment 33 Dominik Fijas 2019-01-14 04:23:01 PST
Hi Daniel Bates,

what is the status of this issue?
do you know if Safari team looked at it?
it would be awesome if they shared updates via http://openradar.appspot.com/ or any other open tool.

Best,
Dominik
Comment 34 John Wilander 2019-01-14 07:32:15 PST
CFNetwork and WebKit are two different frameworks. The bug is in CFNetwork, tracked by the radar number Dan provided above. This open source bug only tracks adding a regression test once the CFNetwork bug is fixed. I hope that helps.
Comment 35 Dominik Fijas 2019-01-14 19:55:01 PST
Hi John Wilander,

Yes, I know it's a CFNetwork and not WebKit issue
(it's been confirmed by Daniel Bates on 2018-12-17).

My question is (still unanswered): is there any way we could track what's going on with rdar://problem/42732352?

Current situation is very inconvenient as we completely lost visibility of this issue and we don't even know if it's been acknowledged and what are next steps :(
Comment 36 John Wilander 2019-01-14 20:32:40 PST
Open source projects like WebKit have open source issue tracking. Closed source projects like CFNetwork have closed issue tracking. Communication about radars is typically handled by Apple Developer Relations and afaik only goes to the original reporter of the radar.
Comment 37 Daniel Bates 2019-01-14 22:16:53 PST
(In reply to Dominik Fijas from comment #33)
> Hi Daniel Bates,
> 
> what is the status of this issue?
> do you know if Safari team looked at it?
> it would be awesome if they shared updates via http://openradar.appspot.com/
> or any other open tool.
> 
> Best,
> Dominik

Hi Dominik,

CFNetwork has acknowledged this bug and has a fix that has been confirmed using your test case. Thanks again for the test case! That is all I can say at this time. I will update this bug with any additional details, as applicable. Test cases to follow.

Dan
Comment 38 RAD 2019-01-17 04:06:26 PST
(In reply to Jan Hajek from comment #0)
> When authenticating with ASP.NET Core 2.0 with OpenID Connect, the Identity
> cookie doesn't seem to be set when returning back from IdP which results in
> redirect loop. This same process works with iOS 11.
> 
> 1. Visit site, access some protected resource
> 2. Set nonce, dedirect to IdP
> 3. Authenticate at IdP
> 4. Return back with POST request
> 5. Validate id_token, set identity cookie with samesite=lax policy
> 6. Redirect to the protected resource
> 7. Check for identity cookie - missing, return to step 2
> 
> I tested the same flow on PC (Edge, Firefox, Chrome) everything works fine
> (they all implement samesite policy -
> https://caniuse.com/#feat=same-site-cookie-attribute). Any idea why Safari
> treats this case different?
> 
> This is probably going to affect quite a lot of users accessing Microsoft's
> own services as well (for example https://admin.teams.microsoft.com) - once
> again, this site works just fine on Chrome or Edge.

The behaviour in comment0 will also present on iOS12 12.1.1 (16C50) even when same site is set to none in the oidc middleware setup (core 2.1) and is reproducible with Firefox/Chrome/Safari.  

The problem i encountered was that my app registration in AzureAD was set to return SecurityGroup information (alter manifest line "groupMembershipClaims": "SecurityGroup").  It would appear from the testing that this pushed the id_token size (and therefore the size of the cookie being written by the browser) over some Apple 'preset cookie size limit' and so the cookie was not written.  When i set groupMembershipClaims back to null the information returned is reduced and the cookie is written and all works fine.  

As there are alternative ways to obtaining claim information other than within the id_token i thought this post may help other developers not waste 3 days of their time.
Comment 39 Jan Hajek 2019-01-18 09:03:06 PST
A simple fix for ASP.NET Core is described in here: https://brockallen.com/2019/01/11/same-site-cookies-asp-net-core-and-external-authentication-providers/
Comment 40 Adam Hamilton 2019-01-30 14:16:42 PST
To give another serious example of how this behavior breaks things, and is outside of a site's control to fix:

1. We send a password reset link to a user.  The link contains a nonce to verify that the user had access to the email as a first step in a multi-step verification process.
2. The user happens to use Gmail, which wraps all links in emails with a redirect through a Google URL so they can track what you click (ex: https://www.google.com/url?q=https://originalurl.com )
3. Because of the redirect chain through google.com to our domain, this implementation of SameSite=lax prevents our landing page setting the session cookie
4. When the user proceeds through the password reset flow to the next step, their nonce from the first step, which should have been attached to their session, is lost because the session cookie didn't follow with them
5. The user is now in a loop of having to restart the password reset flow with a new email validation, which also won't work.

The problem here is that there is nothing we can do as the site developer except to stop using SameSite at all, which defeats its usefulness.  We can't stop Google putting in that redirect link, and we can't stop the browser from prohibiting the cookie, so we are pretty much forced to avoid SameSite at all.  For browsers that interpret lax as not applying to GET requests, we can use SameSite=lax since these redirects are all GET requests.  We are currently in the process of rolling off our use of SameSite for WebKit browsers as a result of this interpretation of the spec, which doesn't match what other browsers were already doing.

Thanks for reading! I hope this illustrates why the behavior that other browsers have is important to support and why this issue can have widespread effect.  I suspect there would be even more reports on this, except that the root cause of our problem being this issue was very hard to track down, and SameSite isn't super widely used yet.  However, I think this workflow is common on the web for password resets, and this issue would affect the common case.
Comment 42 Flávio Juvenal (fjsj) 2019-03-13 13:14:35 PDT
Reproduced wrong samesite=lax behavior on Mac Mojave 10.14.3 (18D109).
Available as a Django project at: https://github.com/vintasoftware/safari-samesite-cookie-issue

TL;DR:
If user comes from a cross-site redirection, samesite=lax cookies won't be sent. That's critical for Django, because it causes all POST requests to fail due to the default CSRF protection. An issue has been created on Django too: https://code.djangoproject.com/ticket/30250
Comment 43 Alexey Proskuryakov 2019-03-13 15:02:25 PDT
This was found to be an issue in an underlying framework below WebKit, so closing as INVALID.

Thank you for the report! Please check if this still happens with iOS 12.2 beta, and/or macOS 10.14.4 beta, I believe that it should be fixed there.
Comment 44 Flávio Juvenal (fjsj) 2019-03-18 14:08:59 PDT
Thanks Alexey. Issue seems solved in Safari Technology Preview: Release 77 (Safari 12.2, WebKit 14608.1.7.3). At least the instance of this issue described at https://github.com/vintasoftware/safari-samesite-cookie-issue
Comment 45 John Wilander 2019-03-18 14:11:57 PDT
(In reply to Flávio Juvenal (fjsj) from comment #44)
> Thanks Alexey. Issue seems solved in Safari Technology Preview: Release 77
> (Safari 12.2, WebKit 14608.1.7.3). At least the instance of this issue
> described at https://github.com/vintasoftware/safari-samesite-cookie-issue

Which version of macOS are you on? As mentioned above, most of Safari's cookie behavior is part of Apple's platform-wide framework "CFNetwork." Updating Safari Technology Preview does not update CFNetwork.
Comment 46 Flávio Juvenal (fjsj) 2019-03-18 14:25:16 PDT
Hi John, that's strange then.

I'm using Mac Mojave 10.14.3 (18D109)

Issue happens on Safari Version 12.0.3 (14606.4.5).
Issue fixed on Safari Technology Preview Release 77 (Safari 12.2, WebKit 14608.1.7.3).

Tested with https://github.com/vintasoftware/safari-samesite-cookie-issue
(I can deploy this, if it's helpful)
Comment 47 Flávio Juvenal (fjsj) 2019-03-28 08:54:33 PDT
Alexey, John, can you please check if this issue is really in CFNetwork?
I've just tested the new iOS/MacOS versions launched at March 25, and *the bug still happens*.

- BROKEN on MacOS 10.14.4 (18E226), Safari 12.1 (14607.1.40.1.4)
- BROKEN on iOS 12.2
- FIXED on Safari Technology Preview Release 77 (Safari 12.2, WebKit 14608.1.7.3) - as stated before
- FIXED on Safari Technology Preview Release 78 (Safari 12.2, WebKit 14608.1.9.1)

It's strange that John mentioned Safari Technology Preview shouldn't fix the issue, but on its release notes there's a "Fixed Same-Site Lax cookies to be sent with cross-site redirect from a client-initiated load" at Release 77: https://developer.apple.com/safari/technology-preview/release-notes/

I kindly ask you folks to please double-check this. It's a serious issue affecting many common user flows, including the flow of visiting a website coming from a GMail link. If the user comes from GMail, it reaches the destination website without any cookies, thereby breaking functionalities that depend on session/login cookie and CSRF cookie. Only fix for now seems to be removing the Lax flag from cookies.
Comment 48 Alexey Proskuryakov 2019-03-28 11:28:17 PDT
Could you please file a new bug, with complete steps to reproduce? A live website to test against would definitely help.
Comment 49 Flávio Juvenal (fjsj) 2019-03-28 15:11:33 PDT
Alexey, done: https://bugs.webkit.org/show_bug.cgi?id=196375