Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

chore(backend): force token expire #969

Merged
merged 9 commits into from
Aug 29, 2024

Conversation

thbcmlowk
Copy link
Contributor

@thbcmlowk thbcmlowk commented Aug 5, 2024

Description

Part of FL-1656

Disable never expiring BearerToken

Companion

Substra/substra-frontend#385

How has this been tested?

On dev by:

  • Creating expiring tokens and one never-expiring
  • Applying the migration code
  • Check db results

Creating tokens

image

 select * from users_bearertoken;
            created            |     note      |         expires_at         |                  id                  | user_id 
-------------------------------+---------------+----------------------------+--------------------------------------+---------
 2024-08-27 12:47:09.093701+00 | expires-60    | 2024-10-26 12:47:08.395+00 | 3a07a145-9ecd-46e8-aa00-35a9a3d2ebf2 |       4
 2024-08-27 12:47:16.34687+00  | never-expires |                            | 456efb44-4f30-49f8-bc12-46a673da9f90 |       4

Applying migration

I have no name!@substra-backend-substra-backend-server-5674697f78-ds9nk:/usr/src/app$ ./manage.py migrate users
Operations to perform:
  Apply all migrations: users
Running migrations:
  Applying users.0008_alter_bearertoken_expires_at... OK

image

            created            |     note      |          expires_at           |                  id                  | user_id 
-------------------------------+---------------+-------------------------------+--------------------------------------+---------
 2024-08-27 12:47:09.093701+00 | expires-60    | 2024-10-26 12:47:08.395+00    | 3a07a145-9ecd-46e8-aa00-35a9a3d2ebf2 |       4
 2024-08-27 12:47:16.34687+00  | never-expires | 2024-08-27 12:50:24.131665+00 | 456efb44-4f30-49f8-bc12-46a673da9f90 |       4

Checklist

  • changelog was updated with notable changes
  • documentation was updated

Copy link

linear bot commented Aug 5, 2024

@thbcmlowk
Copy link
Contributor Author

/e2e --tests=substrafl,mnist,camelyon,frontend --refs=substra-frontend=chore/disable-never-expiring-token

@Owlfred
Copy link

Owlfred commented Aug 6, 2024

End to end tests: ✔️ SUCCESS

@thbcmlowk thbcmlowk force-pushed the chore/disable-never-expiring-token branch from 5722f0c to 2489bd4 Compare August 14, 2024 13:43
Copy link
Contributor

@SdgJlbl SdgJlbl left a comment

Choose a reason for hiding this comment

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

One question, otherwise LGTM.
I don't know enough about the OIDC implementation to know if it will work without issues there.
And we have to keep in mind at the next upgrade that all tokens will be revoked.

migrations.AlterField(
model_name="bearertoken",
name="expires_at",
field=models.DateTimeField(default=django.utils.timezone.now),
Copy link
Contributor

Choose a reason for hiding this comment

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

By default, all existing tokens will expire immediately at the time of the migration. Is that what you want?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the idea was rather to set an immediate expiration date for token that does not have one

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated, thank you

@@ -10,7 +10,7 @@

class BearerToken(Token):
note = models.TextField(null=True)
expires_at = models.DateTimeField(null=True)
expires_at = models.DateTimeField(null=False, default=timezone.now)
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand, does that mean that by default it expires instantly ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for asking, I am not sure I remember the rational behind this particular change.

Copy link
Contributor

Choose a reason for hiding this comment

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

It may have been that all already existing tokens are revoked

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we really want a default value or do we want to force the user to provide it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What it means is that if no value is provided, the token will be created with instant expire. Note that the fronted will disable the possibility to create token with a null expires_at field. One other option is to remove the default ; meaning that creating a token with a null expires_at field will raise the following error:

django.db.utils.IntegrityError: null value in column "expires_at" of relation "users_bearertoken" violates not-null constraint

Not sure of what would be the best behavior, but happy to rework this if we think it's worth.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do we really want a default value or do we want to force the user to provide it

Did not refresh, sorry. Obviously better if we force the user to provide it indeed. Is there a clean way to do so?

Copy link
Contributor

@guilhem-barthes guilhem-barthes Aug 28, 2024

Choose a reason for hiding this comment

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

How did you get this IntegrityError ? The serializer should have returned an error when receiving an empty field for expires_at (and if I recall correctly, DRF does not emit DB django error)

Copy link
Contributor Author

@thbcmlowk thbcmlowk Aug 28, 2024

Choose a reason for hiding this comment

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

I have the error when running tests that rely on instantiating tokens with null expires_at (eg here) and setting either:

  • required=True in the BearerTokenSerializer
  • blank=False in the BearerToken model

@thbcmlowk thbcmlowk force-pushed the chore/disable-never-expiring-token branch from 2489bd4 to d987c1c Compare August 27, 2024 12:55
@thbcmlowk thbcmlowk marked this pull request as ready for review August 27, 2024 13:04
@thbcmlowk thbcmlowk requested a review from a team as a code owner August 27, 2024 13:04
@thbcmlowk thbcmlowk marked this pull request as draft August 27, 2024 13:20
@github-actions github-actions bot added the api label Aug 27, 2024
@thbcmlowk
Copy link
Contributor Author

/e2e --tests=sdk,substrafl,mnist,camelyon,frontend

@Owlfred
Copy link

Owlfred commented Aug 27, 2024

End to end tests: ✔️ SUCCESS

@thbcmlowk thbcmlowk marked this pull request as ready for review August 28, 2024 08:45
response = authenticated_client.post(url, payload)

assert response.json() == {"expires_at": ["This field is required."]}
assert response.status_code == status.HTTP_400_BAD_REQUEST
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

@guilhem-barthes guilhem-barthes left a comment

Choose a reason for hiding this comment

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

Thanks for your work!

Signed-off-by: Thibault Camalon <135698225+thbcmlowk@users.noreply.github.com>
Signed-off-by: Thibault Camalon <135698225+thbcmlowk@users.noreply.github.com>
Signed-off-by: Thibault Camalon <135698225+thbcmlowk@users.noreply.github.com>
Signed-off-by: Thibault Camalon <135698225+thbcmlowk@users.noreply.github.com>
Signed-off-by: Thibault Camalon <135698225+thbcmlowk@users.noreply.github.com>
Signed-off-by: Thibault Camalon <135698225+thbcmlowk@users.noreply.github.com>
Signed-off-by: Thibault Camalon <135698225+thbcmlowk@users.noreply.github.com>
Signed-off-by: Thibault Camalon <135698225+thbcmlowk@users.noreply.github.com>
Signed-off-by: Thibault Camalon <135698225+thbcmlowk@users.noreply.github.com>
@thbcmlowk thbcmlowk force-pushed the chore/disable-never-expiring-token branch from 40b7d8d to 716c064 Compare August 29, 2024 07:51
@thbcmlowk thbcmlowk merged commit 7b1c1fa into main Aug 29, 2024
8 checks passed
@thbcmlowk thbcmlowk deleted the chore/disable-never-expiring-token branch August 29, 2024 08:41
@guilhem-barthes
Copy link
Contributor

/e2e --tests=sdk,substrafl,mnist,camelyon,frontend

@Owlfred
Copy link

Owlfred commented Aug 30, 2024

End to end tests: ❌ FAILURE

Jobs status:

  • Camelyon / camelyon,frontend:
  • Dispatch Jobs: ✔️
  • Documentation: ⏭️
  • MNIST / mnist,frontend:
  • SubstraFL / substrafl,frontend:
  • SubstraSDK / sdk:

“You shall not pass!” ― Gandalf, The Lord of the Rings, The Fellowship of the Ring

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants