Hey guys, It looks like there might be a sneaky bu...
# general
e
Hey guys, It looks like there might be a sneaky bug in the
verify_session()
wrapper in
supertokens-python@dev-v0.8.2
. I am using
Django==4.0
and `djangorestframework==3.13.1`:
Copy code
python
from django.utils.decorators import method_decorator
from rest_framework import viewsets, mixins, status
from supertokens_python.recipe.session.framework.django.syncio import verify_session


@method_decorator(verify_session(), name='dispatch')
class WorkplaceCreateListViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
    def create(self, request, *args, **kwargs):
        return super().create(request, *args, **kwargs)
The thing is that this
create()
function works really fine until it returns a result. It creates an object in the database, but the response is always 401
Fun part is -- this happens only for a single user. After we deleted that user from supertokens backend, he signed up again and tried to trigger this API endpoint once more -- the bug disappeared.
I mean most probably this bug is related to the
verify_session()
wrapper. It does something with the response before it reaches the client, right?
The problem disappeared after we re-created the user (we are using passwordless recipe btw). And it does not happen for any other users in the system.
r
hmmm. Hard to debug now since the issue disappeared.
What do you think was unique about that one user?
e
in my opinion there was nothing unique with that user all we did to fix the issue was to delete that user from supertokens backend and login again with that phone number (which triggers creating user on supertokens backend)
looks like a random-uuid-generator or some other random-generator related bug
idk πŸ˜… that was weird
r
that's strange...
e
Hey @rp , I have an update on this issue
this is happening again
r
hmm. Is there any pattern you noticed?
e
once again, I don't know what is causing the issue -- maybe you can guide me through some actions that can help you extract some useful information? I cannot identify any pattern here -- the request is being processed, model instances are created -- but the response is 401
r
can you enable debug logs on the frontend and backend and show me the output?
e
on the backend: request cookies:
Copy code
Cookie: sAccessToken="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInZlcnNpb24iOiIyIn0%3D.eyJzZXNzaW9uSGFuZGxlIjoiM2ZjNDExOTYtNzZhMS00NGVkLWIzMzEtYTcyN2IxNjA3N2Y3IiwidXNlcklkIjoiZjVlZTg3MjAtZDFjNy00MzRlLWFmZWEtNDk5YWE4OTVkMTYxIiwicmVmcmVzaFRva2VuSGFzaDEiOiIwYjhmNDE2Njc4ZDRmYTAxYThjZmY2MzY3MTg2NzhlOTk0NTcyZGQ0OWUzNmQzNmVjNDQzMjc2MjVjN2ViNGEyIiwidXNlckRhdGEiOnsicm9sZXMiOnsiMTljZDEwMDgtNDEzNi00ZDJhLWE3NTUtNjkwNWE0YTRkZTYwIjpbIm1lZGh1Yl9hZG1pbiJdLCJlZDgxNWFjNi1kMjk3LTRlMjMtYTk3ZS0xMzI1MmU1ZGVlZjgiOlsicGhhcm1hY2lzdCJdfX0sImV4cGlyeVRpbWUiOjE2NTQ1MTczNjIwNTYsInRpbWVDcmVhdGVkIjoxNjU0NTE2NDYyMDU2LCJsbXJ0IjoxNjU0NTE2NDYyMDU2fQ%3D%3D.FH7Z23BLURZwU2QFTK8FDWiCZ24qOiKottGWiqYcYYcb8yxZAW1yeQ2HHRjtS%2Bb%2Bx0jwm0t/WEWzAVAZC1MCQMTMhPOZiJcASml/zpke00lIgxOAIePMRuJ7xuJlYWnsF9K7V255C8iV8Kk7jhj38GkK1IIFiOVrAXBB/vWemMCbLONIpfpovnTzwjPZr33RPtFQRNmgGtssw66pXqvTQMGhhVpozaiumPo7nwu0L9cWU69Hkq0B8ecRFZtG7GNd9xCTH9%2BBIm/3xiDc8bRR9C7KVH%2BgafdndjBk0Tao6yqLr6/4kOQl8PizTH/7TVhailWI7w%2BTlbOpvISXfG9szw%3D%3D"; sFrontToken=eyJhdGUiOjE2NTQ1MTczNjIwNTYsInVpZCI6ImY1ZWU4NzIwLWQxYzctNDM0ZS1hZmVhLTQ5OWFhODk1ZDE2MSIsInVwIjp7InJvbGVzIjp7IjE5Y2QxMDA4LTQxMzYtNGQyYS1hNzU1LTY5MDVhNGE0ZGU2MCI6WyJtZWRodWJfYWRtaW4iXSwiZWQ4MTVhYzYtZDI5Ny00ZTIzLWE5N2UtMTMyNTJlNWRlZWY4IjpbInBoYXJtYWNpc3QiXX19fQ==; sIRTFrontend=e9b69c00-e083-4a67-a7d0-8a4c25444859; sIdRefreshToken=e9b69c00-e083-4a67-a7d0-8a4c25444859; csrftoken=lSdQnNKX69dARz0PrKY51MBD6D3i16VwlfgruhRQaTysXjzdZvhfudxDoWc4v2KO; sessionid=fvyyl9i32lvgt85ysq1y2ehl8e1xl28l
rid: anti-csrf
logs have nothing unusual, just a json object with
"message": "unauthorised"
on the backend it just says
Unauthorized
I can see on the backend it also says:
WARNING:root:something went wrong when creating a role: Session does not exist.
let me see where it is logging from...
Copy code
python
instance = Workplace.objects.create(
            organization=validated_data['organization'],
            user_profile=validated_data['user_profile'],
            role=validated_data['role'],
            role_specialization=validated_data['role_specialization'],
        )
        if 'job_order_document' in validated_data and validated_data['job_order_document'] is not None and \
                len(validated_data['job_order_document']) > 0:
            instance.job_order_document = validated_data['job_order_document']
            instance.save()

        try:
            ProfileRole.create_role(instance.user_profile_id, instance.role_id, instance.organization_id,
                                    instance.role_specialization_id)
        except Exception as e:
            logging.warning(f"something went wrong when creating a role: {e}")
            instance.delete()
            raise e

        return instance
Copy code
python
def update_user_roles(profile_id):
    # we first get all the session_handles (List[string]) for a user
    prof = Profile.objects.get(pk=profile_id)
    supertokens_user_id = prof.supertokens_user_id
    session_handles = get_all_session_handles_for_user(supertokens_user_id)

    for handle in session_handles:
        current_session_info = get_session_information(handle)
        current_access_token_payload = current_session_info.access_token_payload
        profile_roles = ProfileRole.objects.filter(profile=prof, is_active=True)
        for profile_role in profile_roles:
            org_id = str(profile_role.at_id)
            if org_id not in current_access_token_payload["roles"]:
                current_access_token_payload["roles"][org_id] = [profile_role.role]
            else:
                current_access_token_payload["roles"][org_id].append(profile_role.role)
        update_access_token_payload(handle, current_access_token_payload)
Copy code
python
@classmethod
    def create_role(cls, profile_id, role_id, organization_id, specialization_id):
        cls.objects.create(
            profile_id=profile_id,
            role=cls.get_profile_role(role_id),
            at_id=organization_id,
            specialization_id=specialization_id,
        )
        update_user_roles(profile_id)
okay, so probably this is happening on
get_all_session_handles_for_user
, right?
Copy code
python
from supertokens_python.recipe.session.syncio import get_all_session_handles_for_user, update_access_token_payload, get_session_information
the fun thing is that session cannot be non-existent, I am trying to add a role for myself πŸ™‚
r
Can you enable debug logs and send the API request which returns 401?
Check out the troubleshooting section in the docs
it would be very helpful to see those logs
e
you mean to enable debug logs on the supertokens backend side?
e
I have a suspicion that something inside
update_user_roles
call from above is causing the error that says
Session does not exist
maybe
get_all_session_handles_for_user(supertokens_user_id)
? or
get_session_information(handle)
?
r
thanks. Seeing now
Hmm. So the session verification is actually successful. And then something later says that the session doesn't exist
(like you were saying)
in which function above are you calling
verify_session
?
e
Copy code
python
@method_decorator(verify_session(), name='dispatch')
class WorkplaceCreateListViewSet(mixins.ListModelMixin, mixins.CreateModelMixin,
                                 viewsets.GenericViewSet):
it happens when I am trying to create a workplace for myself so basically for
get_all_session_handles_for_user(supertokens_user_id)
call the
user_id
is the
id
of the current user
r
and the value of
supertokens_user_id
that is being passed to it is correct?
e
I am quite sure it is correct, but let me check again
r
If it is correct, you should get back at least one session handle from that function call - is that happening?
thanks.
e
okay, so the issue was that some sessions that are returned from
get_all_session_handles_for_user
are non existent for
get_session_information
thank you too πŸ™‚ now I know how to fix my code
r
well, it could be a bug in the SDK
checking there too
e
meanwhile, I'll just put a try-except block in my code to fix this let me know if you find a bug in SDK πŸ™‚
r
thanks
Is the list of session handles returned correct?
hmm there doens't seem to be any obvious bug in the SDK related to this.
e
well, it should be correct...idkπŸ˜… I am sure that the user id is passed correctly
either way, try-except block does its job just fine
r
yea.. it;'s weird. Im not sure how this is even happening
unless there is some race condition where you revoke a session whilst looping through the sessions
e
nope, I don't revoke sessions anywhere manually
r
hmm
e
only via frontend call
i mean, via a standard flow where user clicks on "logout" button
r
can we get on a call now and debug this?
e
let's schedule a call for tomorrow? I have gym in 20 minutesπŸ˜…
r
cool. Feel free to pick a time here: https://supertokens.com/call-user
e
done πŸ™‚ I'll be at home by at that time
r
thank you!
Copy code
curl --location --request GET 'https://try.supertokens.com/recipe/session?sessionHandle=someSession' \
--header 'api-key: key'
e
works:
1654550761853 |   1654538161853
does not work:
1654528138210 |   1654515538210
r
hey @execreate We have released a new version of the core v3.14.0 which has the fix for the issue we spoke about yesterday. If you are migrating from 3.12.X, you don't have to do anything other than just install the new version. Also, i would recommend that you still have the try / catch in your logic as there is a race condition in which a session might get revoked whilst you are looping through it and that might logout the current (unrelated) session. We will release new versions of the backend SDKs which will fix this as well (in 1-2 weeks time).
e
Cool! Thank you πŸ™‚
2 Views