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

Two-Factor Authentication #107

Open
WayneLambert opened this issue Aug 6, 2021 · 12 comments
Open

Two-Factor Authentication #107

WayneLambert opened this issue Aug 6, 2021 · 12 comments
Assignees
Labels
app: users Issues relating to the `users` app feature Feature for the project

Comments

@WayneLambert
Copy link
Owner

WayneLambert commented Aug 6, 2021

This issue tracks the implementation of using either a device or email token as a second factor in their multi-factor authentication process.

@WayneLambert WayneLambert added the feature Feature for the project label Aug 6, 2021
@WayneLambert WayneLambert self-assigned this Aug 6, 2021
WayneLambert added a commit that referenced this issue Aug 6, 2021
Addresses the following:

- Uses the Django cryptography library to store challenge tokens within
  the database table securely so that no-one can see the actual token
  generated for the user other than the user

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 6, 2021
Addresses the following:

- Creates a new `EmailToken` model
- Implements the use of the Django Cryptography package to encrypt the
  `challenge_token` field
- Performs a series of migrations to amend the model to be suitable
- Makes minor adjustments to the exisiting `Profile` model for
  readability/maintainability

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 6, 2021
Addresses the following:

- Adds a setting to control the number of seconds that the email token
  is valid for.

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 6, 2021
Addresses the following:

- Customises the form to make it user friendly
- Customises the form to include classes for formatting

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 6, 2021
Addresses the following:

- Adds view/URL to support the sending of the token
- Adds view/URL to support the input/validation of the token
- Small renaming of existing templates to suit the current application
  context
- Adds some supplementary utility functions

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 6, 2021
Addresses the following:

- Adds template for the sending of the token
- Adds template for the input/validation of the token
- Renames the template for the device token setup

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 6, 2021
Addresses the following:

- Adds a base email template
- Adds a template with the token for the email method

Contributes towards: #107
@WayneLambert WayneLambert changed the title 2FA - by Email 2FA Aug 10, 2021
@WayneLambert WayneLambert changed the title 2FA Two-Factor Authentication Aug 10, 2021
@WayneLambert WayneLambert added the app: users Issues relating to the `users` app label Aug 10, 2021
@WayneLambert
Copy link
Owner Author

WayneLambert commented Aug 10, 2021

Features To Include

  • Set up a mixin for DeviceAuthUserMixin

  • Set up a mixin for EmailAuthUserMixin

  • Set up a mixin for TwoFactorAuthUserMixin

  • Send an email to the user once they have set up their two-factor authentication

  • Set a token_valid_expiration_date

  • Set up a pathway redirect upon login that directs an email authenticator to a screen that accepts the email token

  • Logic needs to check that the token is within its expiration date (28 days)

  • Set up throttling on the user

  • Resolve testing issue which emulates a user being verified/authenticated with their second factor.

@WayneLambert WayneLambert pinned this issue Aug 10, 2021
@WayneLambert
Copy link
Owner Author

WayneLambert commented Aug 13, 2021

Testing Scenarios for LoginView

  • Scenario 1: The user does not exist (mickey-mouse)

    • Create a helpful message
    • Return them to the login screen with the message presented
  • Scenario 2: The user exists but is not set up for 2FA at all (john-terry - 7)

    • Feed through the initial setup process
  • Scenario 3: The user exists and is using the device token method of 2FA (james-bond - 62)

    • Offload the implementation to the third-party package
    • Present the user with the screen where they need to enter their device token
  • Scenario 4: The user exists and is attempting to 2FA with an expired email token (donald-trump - 66)

    • Redirect the user through the setup process once again. This should give them a new choice of whether to use the device or email method of 2FA.
    • Solution accounts for cases where there are more than one email token in the DB
  • Scenario 5: The user exists and uses an unexpired email token as 2FA (bruce-willis - 67)

    • Retreive the token from the DB
    • Send the token to the user
    • Redirect them to the screen where they can enter it

@WayneLambert
Copy link
Owner Author

The testing scenarios outlined in this comment have been tested and the code works as expected.

donald-trump now has an entry in the database for a token authentication in addition to an expired email token. How does logging in as donald now work?

@WayneLambert
Copy link
Owner Author

The testing scenarios outlined in this comment have been tested and the code works as expected.

donald-trump now has an entry in the database for a token authentication in addition to an expired email token. How does logging in as donald now work?

Due to the hierarchy of logic, Donald is presented with the opportunity to choose their method of 2FA again.

@WayneLambert
Copy link
Owner Author

Need to make a decision on how long the token should be valid for weighing security against convenience.

@WayneLambert
Copy link
Owner Author

Can I use FormView instead of TemplateView? Or can I manually declare the single form within the post method which would give me access to the form object enabling access to cleaned_data and errors.

@WayneLambert
Copy link
Owner Author

Can I use FormView instead of TemplateView? Or can I manually declare the single form within the post method which would give me access to the form object enabling access to cleaned_data and errors.

The post method included an instantiation of the form enabling access to the form data rather than the POST data.

@WayneLambert
Copy link
Owner Author

The ProfileView and the ProfileUpdateView are two examples of views that should only be available within the project for users that have two-factor authenticated.

Other examples include the PostUpdateView.

These should be used as the examples to include a custom mixin and for their corresponding tests to be adapted to emulate being two-factor authenticated.

@WayneLambert
Copy link
Owner Author

The ProfileView and the ProfileUpdateView are two examples of views that should only be available within the project for users that have two-factor authenticated.

Other examples include the PostUpdateView.

These should be used as the examples to include a custom mixin and for their corresponding tests to be adapted to emulate being two-factor authenticated.

The ProfileView is an example of where multiple permutations of the test has been set up to ensure that the intended outcome happens for each authentication status attempting to access the view.

WayneLambert added a commit that referenced this issue Aug 18, 2021
Addresses the following:

- Adds settings for development
- Adds settings for production

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 18, 2021
Addresses the following:

- Adds model for email method of 2FA
  - Includes the migration history during development
- Tweaks `Profile` model
- Removes redundant model methods
- Replaces custom full_name method with in-built Django one
- Replaces `super()` call on `save` method with Python 3 syntax

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 18, 2021
Addresses the following:

- Adds the `EmailToken` model to the admin panel
- Ensures the challenge token is not visible in the admin panel
- Ensures the `EmailToken` panel is completely read-only
- Removes unused models from the panel
- Adjusts the image resizing function with a `SCALE_FACTOR` constant

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 18, 2021
Addresses the following:

- Override `LoginView` to account for the scenarios of device or email
  authentication as the second factor
- `LoginView` now ensures that the user is taken through the 2FA process
  if they have not already done so
- Email is sent upon generation of a code
- Email is sent upon setup of an email code with user-friendly
  information on how long the code will last
- Existing forms have been updated to make them clearer and some
  suplerflous methods have been removed from clean methods
- Refactor some existing code to make clearer
- Where beneficial, type hints and docstrings added

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 18, 2021
Addresses the following:

- Adds function to enable the calculcation of the challenge expiration
  date/time
- Adds function to enable the calculcation of the token expiration
  date/time
- Adds docstrings

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 18, 2021
Addresses the following:

- Adds mixin to enable a view to be conditionally available to users
  that have a device 2FA setup
- Adds mixin to enable a view to be conditionally available to users
  that have an email 2FA setup
- Adds mixin to enable a view to be conditionally available to users
  that have either a device or an email 2FA setup

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 18, 2021
Addresses the following:

- In order to make code more understandable and representative of what
  is actually going on, the `related_name` attribute's value was changed
  from `user` to `profile`
- Changes made in API reference
- Changes made in `PublishedManager` to manage blog `Post` objects
- Changes also made in template references

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 18, 2021
Addresses the following:

- Replaces usage of `user.username` on the `User` model with the
  in-built Django convenience method of `get_username()`
- Replaces usage of the `get_full_name()` method on the `Profile` model with the
  in-built Django convenience method of `get_full_name()`
- Replaces references to the old implementations to the new ones in
  templates, API serializers, testing fixtures, feeds, and views code

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 18, 2021
Addresses the following:

- Adds first name template context in view
- Adds first name template variable in template
- Renames existing email variable to be redacted email for additonal
  clarity

Contributes towards: #107
@WayneLambert
Copy link
Owner Author

WayneLambert commented Aug 19, 2021

  • Change the max_length attribute of the challenge_token field to 255. Run makemigrations and migrate.
  • Remove the import from two_factor.utils import default_device
  • Add an image into the email for branding purposes
  • For the token submission form, use FormView instead but attempt to use a form that inherits from forms.Form rather than forms.ModelForm. I think using forms.ModelForm is blocking me being able to the FormView.
  • Add tests for the ProfileView
  • Add tests for the ProfileUpdateView
  • Add tests for the PostCreateView
  • Add tests for the PostUpdateView

WayneLambert added a commit that referenced this issue Aug 23, 2021
Addresses the following:

- Amend max length of `challenge_token` field
- Prepare migrations file

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 23, 2021
Addresses the following:

- Remove redundant `default_device` import

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 23, 2021
Addresses the following:

- Adds database migrations upon Heroku release
- Adds horizontal scaling for the app

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 23, 2021
Addresses the following:

- Uses `Form` instead of `ModelForm`
- Uses `FormView` instead of `TemplateView`
- Uses `form_valid` method instead of `post` method
- Uses cleaned data rather than just the form's data
- Slightly simplifies logic

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 30, 2021
Addresses the following:

- Returns an explicit boolean from the model methods rather than having
  the method return a None object and therefore implicit falseyness

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 30, 2021
Addresses the following:

- Adds method to alert the user of an incorrect password
- Extract logic into more methods to work towards single responsibility
  principle
- Add implementation to check for user password
- Reorganise the potential routes for a user to log in
- Improve `post` method docstring and additional comments to explain the
  flow/logic of the request
- Simplify the token form to use a simpler and more
  conventional/consistent name for the token fields
- By convention, denotes some methods as private

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 30, 2021
Addresses the following:

- Remove redundant declaration of integer field for `TOTPDeviceForm`
  since the Django Two-Factor Auth package already handles this
- Implements the fields' attrs to only account for what the class is
  doing rather than re-implementing some of what the parent class is
  implementing already.
- Adds docstring to aid understanding of the forms' purposes
- Remove redundant clean methods
- Adds minimum and maximum values for the integer field used for the
  token validation. This will provide the user with quicker feedback if
  they should enter a numeric value beyond the defined bounds

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 30, 2021
Addresses the following:

- Updates the `login` template to include some reformatting of error
  messages
- Updates the `setup_email_token` template to have a more accurately
  named link

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 30, 2021
Addresses the following:

- Adds tests for the TOTP device form
- Adds tests for the Email token submission form

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 30, 2021
Addresses the following:

- Removes a redundant import in the `models.py` module

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 30, 2021
Addresses the following:

- Remove unnecessary test
- Sort imports
- Remove unnecessary additional reference to a pytest mark to allow
  database access

Contributes towards: #107
WayneLambert added a commit that referenced this issue Aug 31, 2021
Following the integration of Django Axes, the custom authenticate method
requires a request to be passed to the function so that Django Axes can
evaluate the request

Addresses the following:

- Adds request argument to the authenticate method
- Adds variable assignments for readability
- Slightly adjusts the ordering of the function for slightly greater
  efficiency and reduced computation overhead

Contributes towards: #107, #118
WayneLambert added a commit that referenced this issue Aug 31, 2021
Following using an integer field instead of a character field, a bug
with the token input was introduced.

Addresses the following:

- Adds code to ensure the string of the token is 6 characters long by
  padding it with leading zeros.

Contributes towards: #107
WayneLambert added a commit that referenced this issue Sep 7, 2021
Addresses the following:

- The `UserLoginView` has been updated to reflect better practices for
  the retrieval of objects, the clearing down and intialisation of
  messages
- Moves the password reset workflow configuration from the URLs to
  subclassed views
- Updates the `ProfileView` to be more consistent with the other parts
  of the file and code base
- Updates some docstrings to be a more clear and concise explanation of
  the code's purpose

Contributes towards: #107
WayneLambert added a commit that referenced this issue Sep 7, 2021
Addresses the following:

- Adds form handling to the `login` template to handle the package's
  code
- Makes some formatting changes to the `register` template so that it is
  consistent with other UI screens within the registration and login
  workflows
- Removes the `logout` template since it is no longer needed. The
  `LOGOUT_REDIRECT_URL` takes the user back to the blog's home page

Contributes towards: #107
@WayneLambert WayneLambert unpinned this issue Oct 2, 2021
@WayneLambert
Copy link
Owner Author

  • Build a smaller and more efficient multi-stage Docker image

@WayneLambert
Copy link
Owner Author

Replace the django-cryptography package with the django-encrypted-model-fields. This is a more frequently maintained package and will not prevent the upgrade path.

WayneLambert added a commit that referenced this issue Feb 20, 2022
Addresses the following:

- Remove the `django-cryptography` package
- Add `django-encrypted-model-fields` package
- Remove migrations relating to third party package
- Revert migrations back to 0003
- Makes new migrations
- Adds `FIELD_ENCRYPTION_KEY` setting and environment variable
- Add `EncryptedCharField` as the field type for `email_token` field
- Remove some excessive logging to the Django server terminal output

Contributes towards: #107
WayneLambert added a commit that referenced this issue Feb 20, 2022
Addresses the following:

- Adds `FIELD_ENCRYPTION_KEY` to pytest setting
- Removes erroneous import in file

Contributes towards: #107
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
app: users Issues relating to the `users` app feature Feature for the project
Projects
None yet
Development

No branches or pull requests

1 participant