1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-15 09:34:13 +00:00

Merge branch '3449-secured-file-access-not-working-when-authenticated-with-sso' into 'develop'

Secured file access not working when authenticated with SSO

Closes 

See merge request 
This commit is contained in:
Przemyslaw Kukulski 2025-03-04 08:52:27 +00:00
commit 3295fb30c2
5 changed files with 59 additions and 9 deletions
changelog/entries/unreleased/bug
enterprise/backend
src/baserow_enterprise/api/sso
tests/baserow_enterprise_tests
web-frontend/modules/core/middleware

View file

@ -0,0 +1,7 @@
{
"type": "bug",
"message": "Fix for Secure File Serve with SSO SAML/OIDC authentication",
"issue_number": 3449,
"bullet_points": [],
"created_at": "2025-02-27"
}

View file

@ -11,7 +11,7 @@ from django.shortcuts import redirect
from requests.models import PreparedRequest
from baserow.core.user.utils import generate_session_tokens_for_user
from baserow.core.user.utils import generate_session_tokens_for_user, sign_user_session
# please keep this in sync with baserow_enterprise/locales/en.json
@ -179,10 +179,10 @@ def get_valid_frontend_url(
return requested_url_parsed.geturl()
def urlencode_user_token(frontend_url: str, user: AbstractUser) -> str:
def urlencode_user_tokens(frontend_url: str, user: AbstractUser) -> str:
"""
Adds the token as a query parameter to the provided frontend url. Please
ensure to call the get_url_for_frontend_page_if_valid_or_default() method
Adds the token and user_session as a query parameters to the provided frontend url.
Please ensure to call the get_url_for_frontend_page_if_valid_or_default() method
before calling this method, so to be sure to encode the refresh token in a
valid Baserow frontend url.
@ -190,11 +190,19 @@ def urlencode_user_token(frontend_url: str, user: AbstractUser) -> str:
redirected after a successful login.
:param user: The user that sign in with an external provider and is going to
start a new session in Baserow.
:return: The url with the token as a query parameter.
:return: The url with the token and user_session as query parameters.
"""
user_tokens = generate_session_tokens_for_user(user, include_refresh_token=True)
return urlencode_query_params(frontend_url, {"token": user_tokens["refresh_token"]})
refresh_token = user_tokens["refresh_token"]
user_session = sign_user_session(user.id, refresh_token)
return urlencode_query_params(
frontend_url,
{
"token": refresh_token,
"user_session": user_session,
},
)
def redirect_user_on_success(
@ -214,7 +222,7 @@ def redirect_user_on_success(
"""
valid_frontend_url = get_valid_frontend_url(requested_original_url)
redirect_url = urlencode_user_token(valid_frontend_url, user)
redirect_url = urlencode_user_tokens(valid_frontend_url, user)
return redirect(redirect_url)

View file

@ -303,7 +303,11 @@ def test_saml_assertion_consumer_service(api_client, enterprise_data_fixture):
assert response.headers["Location"].startswith(
f"{get_frontend_default_redirect_url()}?token="
)
token = response.headers["Location"].split("=")[1]
# Extract the token from the URL, handling the new format with user_session
redirect_url = response.headers["Location"]
query_params = dict(parse_qsl(urlparse(redirect_url).query))
token = query_params.get("token")
# ensure the token is valid and a user has been created
response = api_client.post(
reverse("api:user:token_verify"),

View file

@ -1,4 +1,10 @@
from baserow_enterprise.api.sso.utils import get_valid_frontend_url
import pytest
from baserow_enterprise.api.sso.utils import (
get_valid_frontend_url,
redirect_user_on_success,
urlencode_user_tokens,
)
def test_get_valid_front_url():
@ -98,3 +104,22 @@ def test_get_valid_front_url_w_params():
)
== "http://localhost:3000/dashboard?test=value"
)
@pytest.mark.django_db()
def test_urlencode_user_tokens(enterprise_data_fixture):
user = enterprise_data_fixture.create_user()
url = urlencode_user_tokens("http://localhost:3000/dashboard", user)
assert "token=" in url
assert "user_session=" in url
@pytest.mark.django_db()
def test_redirect_user_on_success(enterprise_data_fixture):
user = enterprise_data_fixture.create_user()
response = redirect_user_on_success(user)
assert response.status_code == 302
assert response.has_header("Location")
location = response.headers["Location"]
assert "token=" in location
assert "user_session=" in location

View file

@ -1,12 +1,18 @@
import {
getTokenIfEnoughTimeLeft,
setToken,
setUserSessionCookie,
} from '@baserow/modules/core/utils/auth'
export default function ({ store, req, app, route, redirect }) {
// If nuxt generate or already authenticated, pass this middleware
if ((process.server && !req) || store.getters['auth/isAuthenticated']) return
const userSession = route.query.user_session
if (userSession) {
setUserSessionCookie(app, userSession)
}
// token can be in the query string (SSO) or in the cookies (previous session)
let refreshToken = route.query.token
if (refreshToken) {