Skip to content

Commit

Permalink
Tidy up and document SameSite cookie workaround
Browse files Browse the repository at this point in the history
  • Loading branch information
kinglozzer committed Aug 11, 2023
1 parent 88704d6 commit 0544347
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 23 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,17 @@ SilverStripe\Core\Injector\Injector:
- '../oauth.log'
- 'error'
```

## SameSite / POST cookies

Some providers, like Apple, will redirect back to your site with a POST request. When this happens, the default browser behaviour is not to send cookies with the request, meaning that it’s not possible to verify the request as the user’s session is lost. There are two ways to work around this:

1. Mark your session cookie as `SameSite=None; Secure` as detailed [here](https://docs.silverstripe.org/en/4/developer_guides/cookies_and_sessions/sessions/#samesite-attribute)
2. Set the following YAML value:

```yml
Bigfork\SilverStripeOAuth\Client\Control\Controller:
enable_samesite_workaround_redirect: true
```

When this is enabled, your site will handle the POST that it receives from your OAuth provider by redirecting the user via a GET request. When this GET request is issued, the site once again has access to the user’s session cookie so the authorisation process can continue as normal.
15 changes: 11 additions & 4 deletions src/Control/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class Controller extends SilverStripeController

private static $url_segment = 'oauth';

private static $enable_samesite_workaround_redirect = false;

/**
* Logic copied from \SilverStripe\Control\Controller::redirectBack()
*
Expand Down Expand Up @@ -140,11 +142,16 @@ public function callback(HTTPRequest $request)
* Apple makes a POST instead of a GET request which leads to CORS problems.
* This intermediate step was introduced to make it a GET request.
*/
if ($request->postVar('state') && $request->postVar('code')) {
// $this->redirect() would not work because the request has to happen on the client side (via JavaScript).
return $this->renderWith('OAuthRedirect', [
'url' => sprintf("/%s?code=%s&state=%s", $request->getURL(), $request->postVar('code'), $request->postVar('state'))
if ($request->isPost() && $this->config()->get('enable_samesite_workaround_redirect')) {
$response = $this->getResponse();
// $this->redirect() would not work because the request has to originate from the browser
$redirectHTML = $this->renderWith('Bigfork\\SilverStripeOAuth\\Client\\OAuthRedirect', [
'URL' => static::join_links($this->AbsoluteLink(), 'callback'),
'Code' => $request->requestVar('code'),
'State' => $request->requestVar('state')
]);
$response->setBody($redirectHTML);
return $response;
}

if (!$this->validateState($request)) {
Expand Down
19 changes: 0 additions & 19 deletions src/templates/OAuthRedirect.ss

This file was deleted.

16 changes: 16 additions & 0 deletions templates/Bigfork/SilverStripeOAuth/Client/OAuthRedirect.ss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>OAuth Redirect</title>
<meta http-equiv="refresh" content="0;url={$URL.RAW}?code={$Code}&state={$State}" />
</head>
<body>
<h1>You are being redirected, please wait</h1>
<p>If you are not automatically redirected, please <a href="{$URL.RAW}?code={$Code}&state={$State}">click here</a>.</p>
<script type="text/javascript">
window.setTimeout(function() {
window.location.href = "{$URL.RAW}?code={$Code}&state={$State}";
});
</script>
</body>
</html>

0 comments on commit 0544347

Please sign in to comment.