Skip to content

Commit

Permalink
Merge pull request #12414 from rtibbles/verboten
Browse files Browse the repository at this point in the history
Properly redirect on authentication failure
  • Loading branch information
rtibbles authored Jul 12, 2024
2 parents 11ed18c + d7608df commit c445798
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 10 deletions.
16 changes: 10 additions & 6 deletions kolibri/core/assets/src/core-app/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,19 @@ baseClient.interceptors.response.use(
// client code is still trying to access data that they would be allowed to see
// if they were logged in.
if (error.response) {
if (error.response.status === 403 || error.response.status === 401) {
if (!store.state.core.session.id) {
// Don't have any session information, so assume that this
// page has just been reopened and the session has expired.
// Redirect now!
if (error.response.status === 403) {
if (store.state.core.session.id && !store.state.core.session.user_id) {
// We have session information but no user_id, which means we are not logged in
// This is a sign that the user has been logged out due to inactivity
heartbeat.signOutDueToInactivity();
} else {
// In this case, we should check right now if they are still logged in
heartbeat.pollSessionEndPoint();
heartbeat.pollSessionEndPoint().then(() => {
// If they are not, we should handle sign out
if (!store.state.core.session.user_id) {
heartbeat.signOutDueToInactivity();
}
});
}
}
// On every error, check to see if the status code is one of our designated
Expand Down
2 changes: 1 addition & 1 deletion kolibri/core/assets/src/heartbeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ export class HeartBeat {
Lockr.set(SIGNED_OUT_DUE_TO_INACTIVITY, true);
// Redirect the user to let the server sort out where they should
// be now
redirectBrowser();
redirectBrowser(null, true);
}
_sessionUrl(id) {
return urls['kolibri:core:session-detail'](id);
Expand Down
9 changes: 7 additions & 2 deletions kolibri/core/assets/src/utils/redirectBrowser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import urls from 'kolibri.urls';

export default function redirectBrowser(url) {
window.location.href = url || urls['kolibri:core:redirect_user']();
export default function redirectBrowser(url, next = false) {
url = url || urls['kolibri:core:redirect_user']();
const urlObject = new URL(url, window.location.origin);
if (next) {
urlObject.searchParams.set('next', encodeURIComponent(window.location.href));
}
window.location.href = urlObject.href;
}
11 changes: 11 additions & 0 deletions kolibri/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from django.urls import reverse
from django.urls import translate_url
from django.utils.decorators import method_decorator
from django.utils.http import url_has_allowed_host_and_scheme
from django.utils.translation import check_for_language
from django.utils.translation import gettext_lazy as _
from django.utils.translation import LANGUAGE_SESSION_KEY
Expand Down Expand Up @@ -179,6 +180,16 @@ def get(self, request):
else:
url = get_url_by_role(user_kinds.ANONYMOUS)
if url:
next_url = request.GET.get("next")
if next_url:
# Step 2: Validate the next_url
if url_has_allowed_host_and_scheme(
next_url,
allowed_hosts={request.get_host()},
require_https=request.is_secure(),
):
# Step 3: Append next_url to the base url if it's valid
url = f"{url}?next={next_url}"
return HttpResponseRedirect(url)
raise Http404(
_(
Expand Down
4 changes: 3 additions & 1 deletion kolibri/deployment/default/settings/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
REST_FRAMEWORK = {
"UNAUTHENTICATED_USER": "kolibri.core.auth.models.KolibriAnonymousUser",
"DEFAULT_AUTHENTICATION_CLASSES": [
# Always keep this first, so that we consistently return 403 responses
# when a request is unauthenticated.
"rest_framework.authentication.SessionAuthentication",
# Activate basic auth for external API testing tools
"rest_framework.authentication.BasicAuthentication",
"rest_framework.authentication.SessionAuthentication",
],
"DEFAULT_RENDERER_CLASSES": (
"rest_framework.renderers.JSONRenderer",
Expand Down

0 comments on commit c445798

Please sign in to comment.