Skip to content
New issue

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

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

Already on GitHub? # to your account

Fix EZP-26179: REST session refresh must throw a 404 if session has expired #1769

Merged
merged 4 commits into from
Sep 16, 2016

Conversation

bdunogier
Copy link
Member

@bdunogier bdunogier commented Sep 7, 2016

Relates to EZP-26179 / ezsystems/platform-ui-bundle#668
Implements EZP-26720 (use session auth in REST functional tests)
Fixes EZP-25038 (error when logging in with REST if a session was started before)

According to the specifications, /api/ezp/v2/user/sessions/<id>/refresh must throw a 404 if the session doesn't exist / has expired.

Because of the CSRF token check in the CsrfListener, a 401 is thrown because the csrf token verification fails, as the session has expired, and we don't have a stored token anymore.

This changes the CsrfListener to skip this route, and explicitly checks in the refresh controller action if the token has expired using the Csrf TokenStorage.

@bdunogier bdunogier force-pushed the ezp26179-rest_session_refresh_404-6.4 branch 2 times, most recently from d619cf8 to 1888fcd Compare September 7, 2016 15:59
@andrerom
Copy link
Contributor

andrerom commented Sep 8, 2016

Some questions:

  • what is going on in catch (SessionUnavailableException $e) => it seems RestNotFoundException is not thrown anymore => and is logout safe not matter what? (session id change, session deleted, ..)
  • is there any possibility of get login to reuse the new abstract methods?
  • we also talked about doing similar things to DELETE, still on the agenda or not relevant?

:)

@dpobel
Copy link
Contributor

dpobel commented Sep 8, 2016

it seems to work :)

we also talked about doing similar things to DELETE, still on the agenda or not relevant?

As far as I can tell, that's not strictly needed to fix the original issue but IMHO, it would make sense to have the same behavior when deleting the session through REST.

@@ -136,7 +136,8 @@ protected function isMethodSafe($method)
*/
protected function isLoginRequest($route)
Copy link
Contributor

Choose a reason for hiding this comment

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

now it does more than just checking if we try to login the user

Copy link
Member Author

Choose a reason for hiding this comment

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

Deprecated in favour of isSessionRoute($route)

@dpobel
Copy link
Contributor

dpobel commented Sep 8, 2016

in addition to the previous comments, it would also be nice to complete https://github.com/ezsystems/ezpublish-kernel/blob/master/doc/specifications/rest/REST-API-V2.rst#refresh-session-get-sessions-user-information (and potentially the DELETE part as well) to precise that the session cookie is also deleted in error cases.

@bdunogier bdunogier force-pushed the ezp26179-rest_session_refresh_404-6.4 branch 3 times, most recently from 19cb458 to f00ed9d Compare September 8, 2016 14:34
@bdunogier
Copy link
Member Author

bdunogier commented Sep 8, 2016

we also talked about doing similar things to DELETE, still on the agenda or not relevant?

Changed to use the same behaviour (ignored in CsrfListener, check if we have a token in the controller).

what is going on in catch (SessionUnavailableException $e) => it seems RestNotFoundException is not thrown anymore => and is logout safe not matter what? (session id change, session deleted, ..)

Yes. I've decided to take a shortcut and return a response here. RestNotFoundException implies that visitors are able to do that. The DeletedUserSession one does it by passing the Response object returned by logout(), and have the visitor copy the headers. I found it a bit heavy, and not that useful, since we don't even have a response body, and chose to return a response directly, since we have one.

@bdunogier
Copy link
Member Author

But now I'm thinking that the csrf check in refresh and delete session are a bit wrong: the actual value of the csrf token won't be checked, since we only use the TokenStorage to check if there is a token.

I guess that we should first check if there is a token, and if there isn't, throw a 404. Then if we have a token, check that the token that was provided as input is correct.

@bdunogier
Copy link
Member Author

Added csrf-token value check in both refresh and delete session. Also reorganized the code a little bit.

*/
protected function isLoginRequest($route)
{
return $route === 'ezpublish_rest_createSession';
return $route === 'ezpublish_rest_createSession' ||
$route === 'ezpublish_rest_refreshSession';
Copy link
Contributor

Choose a reason for hiding this comment

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

given it is deprecated and not used this change should be removed I guess.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point :-)

@bdunogier
Copy link
Member Author

Updated createSession() to use the newly added methods, improves readability a lot.

Will consider fixing the case where a session exists without a csrf token fixed (reported in JIRA), preventing from logging into PlatformUI if a frontend session was previously created.

@bdunogier bdunogier force-pushed the ezp26179-rest_session_refresh_404-6.4 branch 2 times, most recently from 1fdd788 to 72494a4 Compare September 10, 2016 08:36
@andrerom
Copy link
Contributor

andrerom commented Sep 12, 2016

Will consider fixing the case where a session exists without a csrf token fixed (reported in JIRA), preventing from logging into PlatformUI if a frontend session was previously created.

Did you think about how we can do that?
Also note that issue was reported on 1.3.

Otherwise PR looks good :)

@bdunogier bdunogier force-pushed the ezp26179-rest_session_refresh_404-6.4 branch from b20337e to d0f758b Compare September 12, 2016 12:31
@bdunogier
Copy link
Member Author

@andrerom : see d0f758b :)

Do we need to fix it in 1.3 ?

@bdunogier bdunogier force-pushed the ezp26179-rest_session_refresh_404-6.4 branch from d0f758b to 9206e22 Compare September 12, 2016 13:24
@bdunogier
Copy link
Member Author

We should be good for review, everything's in.

@@ -490,7 +490,7 @@ public function testUnassignRoleFromUser($roleAssignmentHref)
*
* @return string role assignment href
*/
public function testAssignRoleToUserGroup($roleHref)
public function _testAssignRoleToUserGroup($roleHref)
Copy link
Contributor

Choose a reason for hiding this comment

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

temp change?

Copy link
Member Author

Choose a reason for hiding this comment

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

I need to rephrase that a bit. This particular test breaks roles in the database, and prevents further tests from working.

Copy link
Member Author

Choose a reason for hiding this comment

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

Marked the test as skipped with the reason.

@andrerom
Copy link
Contributor

andrerom commented Sep 13, 2016

Besides comment, +1

Do we need to fix it in 1.3 ?

Not a must, stay with current target.

@bdunogier bdunogier force-pushed the ezp26179-rest_session_refresh_404-6.4 branch from 9206e22 to 6e6e432 Compare September 13, 2016 15:15
@bdunogier
Copy link
Member Author

bdunogier commented Sep 13, 2016

@pcardiga : this is ready for QA. There are several fixes / changes in there. They must be tested on 1.4.x. A new version will be issued for master:

EZP-25038

If a session was started from the frontend (just use /#, it is impossible to log into PlatformUI without clearing the session cookie first. When it happens, REST will respond with a 401 because of a missing csrf token.

EZP-26179

This is the main issue fixed by this PR. It changes the behaviour of both refresh and delete session.

From a REST perspective, if either is used while a session has expired, they will now throw a 404, and delete the session cookie, instead of a 401 because of a missing csrf token.

From the UI, without this patch, if the session expires while on PlatformUI, it will be impossible to login again to the UI without deleting the session cookie. This can be tested together with ezsystems/platform-ui-bundle#668 on PlatformUI. Set sessions to expire quickly (session.gc_divisor = 1 + session.gc_maxlifetime = 10 will get sessions to expire after 10 seconds, and be garbage collected right away). Wait for the session to expire while logged into PlatformUI, and click on anything. Without the patches, you will get an error, and you will be unable to login again. With the patch, you will be redirected to the login screen, and be able to login again.

@pcardiga
Copy link

@bdunogier:
@miguelcleverti, on behalf of QA, is on it.
Meamwhile, following the new procedures, QA should also have a jira ticket in his kanban column and I see that both EZP-25038 and EZP-26179 are on development column. Can the main related issue be moved to QA?

@bdunogier bdunogier force-pushed the ezp26179-rest_session_refresh_404-6.4 branch from 6e6e432 to 4065815 Compare September 13, 2016 16:30
@miguelcleverti
Copy link

@bdunogier

I was not able to reproduce the issue EZP-25038 only using the /# route but using the EventHandler provided in the jira issue I reproduced and tested it. Everything ok.

The issue EZP-26179 was tested using the ezsystems/platform-ui-bundle#668 as well and everything was ok. The only issue I had was not being able to make the garbage collector work after 10s, so I manually deleted the sessions. Doing this the response status return was a 404 instead of 401 and the PlatformUI redirected to the login.

These issues were tested on 1.4.x

@bdunogier
Copy link
Member Author

I was not able to reproduce the issue EZP-25038 only using the /# route

Odd, this is how I trigger this case in the REST functional tests.

Bertrand Dunogier added 4 commits September 16, 2016 11:14
…n has expired

According to the specifications, /api/ezp/v2/user/sessions/<id>/refresh must
throw a 404 if the session doesn't exist / has expired.

Because of the CSRF token check in the CsrfListener, a 401 is thrown because
the csrf token verification fails, as the session has expired, and we don't
have a stored token anymore.

This changes the CsrfListener to skip this route, and explicitly checks in
the refresh controller action if the token has expired.
@bdunogier bdunogier force-pushed the ezp26179-rest_session_refresh_404-6.4 branch from 4065815 to 01865fa Compare September 16, 2016 09:14
@bdunogier
Copy link
Member Author

The error is a 1.4 related one. Composer didn't install the tested branch, but 5.4.2-rc1. This means that platform wasn't set to basic auth, and tests try to run with basic auth, hence the failure on everything that requires permissions other than anonymous.

Tested locally, with a 1.4 install frm scratch and the PR's branch, and it works as expected.

@bdunogier bdunogier merged commit 37e75da into 6.4 Sep 16, 2016
@bdunogier bdunogier deleted the ezp26179-rest_session_refresh_404-6.4 branch September 16, 2016 10:32
andrerom added a commit to ezsystems/ezplatform that referenced this pull request Sep 22, 2016
andrerom added a commit to ezsystems/ezplatform that referenced this pull request Sep 27, 2016
# for free to join this conversation on GitHub. Already have an account? # to comment
Development

Successfully merging this pull request may close these issues.

5 participants