G'day! Further to 40781534, for which the accepted answer is to set SameSite=Lax
:
How can I set SameSite=Strict
cookies on a redirection to myself in such a way that I'll get the cookie back from Chrome 56.0.2924.87
, even if the user's request was itself a redirection from a login page on my OAUTH2 provider?
The full request chain is:
POST https://provider.com/callback
→ 302 FOUND
with:
Location: https://me/login?code=xxx&state=yyy
GET https://example.com/login?code=xxx&state=yyy
→ 302 FOUND
or 303 SEE OTHER
(doesn't seem to matter) with:
Location: https://example.com/destination Set-Cookie: sid=zzzz; Secure; HttpOnly; SameSite=Strict; Path=/
GET https://example.com/destination
→ 401 GET OFF MY LAWN
because the browser didn't present the sid
cookie
GET https://example.com/destination
→ 200 OK
if I refresh, because then the site is the same and my browser presents the sid
cookie
I appreciate the CSRF potential of presenting sid
to /destination
for the general case of the user's last loaded page not being on example.com
, but I only just set it from /login
, and I'm the one now redirecting to /destination
.
Sure, I could set SameSite=Lax
, but then wouldn't there be some potential for click-jacking if someone could find some way to trigger redirection of their choice from my site by mal-forming a URL?
Cookies are not sent after redirect (even on same origin) #1404.
Fixing common warnings The warning appears because any cookie that requests SameSite=None but is not marked Secure will be rejected. To fix this, you will have to add the Secure attribute to your SameSite=None cookies. A Secure cookie is only sent to the server with an encrypted request over the HTTPS protocol.
A redirect URI, or reply URL, is the location where the authorization server sends the user once the app has been successfully authorized and granted an authorization code or access token.
To prepare, Android allows native apps to set cookies directly through the CookieManager API. You must declare first party cookies as SameSite=Lax or SameSite=Strict , as appropriate. You must declare third party cookies as SameSite=None; Secure .
I don't think that this can be done for security reasons. SameSite=Strict
means that if user has been redirected or just clicked on link to your site (from other host), cookie shouldn't be send. And redirecting is like 'chaining' requests. So if your server redirects to another and this server redirects back immediately with 3xx code, cookie will be sent, because your server is 'on top' of this chain.
However if you redirect to oauth provider and user has to allow there you to access his account it means that this 'chain' is broken, and cookie will no longer be sent even if your site sets it (it is set however not sent). Your redirect is just 'extension' of clicked 'allow' link.
If you want to prevent others from click-jacking your site, just use nonce in link if you think, that you have to prevent that kind of behavior, and it can be dangerous if you don't. But consider that most providers are checking for you if redirect url was previously defined and allowed by your app.
Here are other solutions (use only if you know what you're doing and can get on yourself 100% responsibility).
I have used second while developing, now I am using same site lax (this was default in Hapi up to maybe 15 ver, so it isn't so bad).
HTTP OK with HTML redirect ensures the redirected request actually sends the SameSite=Strict
cookie.
Solution is simple. Instead of a 302, send a 200 with the following body:
<html> <head> <meta http-equiv="refresh" content="0;URL='https://example.com/destination'"/> </head> <body><p>Moved to <a href="https://example.com/destination">https://example.com/destination</a>.</p></body> </html>
Using meta refresh to create an instant client-side redirect
My OIDC scenario involved:
Normally we would 302 redirect to the target on the OIDC POST, but, this doesn't work with SameSite=Strict
. The browser refuses to send the cookie, even though it stored it. If you close the browser and re-open, it will send the cookie. By adding an additional HTML redirect, the browser sends the cookie when it requests the final URL.
In .NET Core, I was able to use SameSite=Strict cookies by replacing the Response.Redirect
with the HTML redirect solution:
public sealed class OpenIdConnectHtmlRedirectHandler : OpenIdConnectHandler { public OpenIdConnectHtmlRedirectHandler(IOptionsMonitor<OpenIdConnectOptions> options, ILoggerFactory logger, HtmlEncoder htmlEncoder, UrlEncoder encoder, ISystemClock clock) : base(options, logger, htmlEncoder, encoder, clock) { } public override async Task<bool> HandleRequestAsync() { if (!await base.HandleRequestAsync()) return false; var headers = Response.GetTypedHeaders(); if (null == headers.Location) return true; Response.ContentType = "text/html"; Response.StatusCode = 200; headers.Location = null; await Response.WriteAsync($"<html><head><meta http-equiv=\"refresh\" content=\"0; URL='{location}'\"/></head></html>", Encoding.UTF8, Context.RequestAborted); return true; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With