Giter Club home page Giter Club logo

django-keycloak-auth's People

Contributors

dependabot[bot] avatar diogosilva30 avatar ftcardoso avatar jmggarcia avatar kdpisda avatar moritz89 avatar pcoelho-ubi avatar rjfv avatar simao-silva avatar uw-rvitorino avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

django-keycloak-auth's Issues

Add stale bot to handle inactive issues and PRs

Is your feature request related to a problem? Please describe.
Not a problem yet, but handle issues that are not active anymore

Describe the solution you'd like
Add a bot to mark old issues as stale with (e.g., https://github.com/marketplace/actions/close-stale-issues)

Describe alternatives you've considered
Manually tracking old and inactive issues

Additional context
This is standard with most larger projects. The default configuration of marking issues stale after 60 days, and closing them 7 days after that seems fine.

How does logging work?

Hi,

I configured the keykloak settings and tried to login into the admin area. The log in was refused. Nothing was printed from django.
How do I debug this? Is there a switch to enable debug prints?

Write in the documentation about configuring keycloak

I was unable to authenticate after configuring the project, an error about incorrect password or username was always returned. After some debugging investigations into the library, I found the following exception in from_credentials in Token.

b'{"error":"unauthorized_client","error_description":"Client not permitted for direct access grants"}'

To resolve this issue, I had to configure my keycloak client to enable direct access.

keycloak_config

It would be interesting to see in the official documentation how the keycloak client must be configured for the library to work correctly.

Set up CI test coverage report

Is your feature request related to a problem? Please describe.
Show the areas that have been tested, highlight those that should be tested to ensure stable releases.

Describe the solution you'd like

  • Have a detailed report via services such as SonarQube, Coveralls or similar that have a line by line coverage report
  • Have a badge at the top of the readme with a coverage percentage
  • Optional: in MRs highlight untested lines

Describe alternatives you've considered
None

Additional context
There are several resources and other projects whose implementation can be copied

IntegrityError: null value in column "email" violates not-null constraint

Describe the bug
IntegrityError django_keycloak.middleware in append_user_info_to_request error
null value in column "email" violates not-null constraint

django_keycloak/middleware.py in append_user_info_to_request (line 39) raises this error when the user_info does not contain the email property (because the Token is not valid anymore)

To Reproduce
Steps to reproduce the behavior:

  1. Login with your credentials in a UI calling a Django API served by this library
  2. Remain in the UI and allow your token to expire
  3. Click somewhere that calls the Django API
  4. See error crashing the Django project

Expected behavior
The middleware should try to get the email from the user info but if it's None it should return an Unauthorised response and not try to save the user info,

Screenshots
Screenshot 2022-10-20 at 18 22 12

Desktop (please complete the following information):

  • OS: Not relevant
  • Browser: Not relevant
  • Version: Not relevant

Smartphone (please complete the following information):

  • Device: Not relevant
  • OS: Not relevant
  • Browser: Not relevant
  • Version: Not relevant

Additional context
N/A

Add support for decoding JWT tokens

Since the JWT tokens are signed, it is possible to create a parallel code path to introspecting tokens with the server. This would reduce the load on the Keycloak server and reduce the latency for requests.

I have implemented and tested this and if there is interest, I would gladly upstream the changes.

The introspection code path is preserved and can be toggled with a setting flag.

Add caching to JWT decoding

The decoding of JWTs is 'relatively' expensive and called about 5 times per request. Caching the request results in almost a 10x speed up. Caching the call also reduces the total call by almost 20%. Therefore, it would be impactful to add a cache to the function. In order not to cache an expired token, the cache would be given a time-to-live (TTL). Here, even a 60 second cache time would have significant benefits.

I would propose adding the ttl_cache decorator from cachetools.

Graph of the cache timings:

timings

Zoomed graph without the first requests:

timings_zoom

Data and graph source:

timings.ods

  • Note about the missing first entry. Loading the JWKS from Keycloak takes about 10 ms and distorts the actual measurement which is why it was removed.

The timings were recorded with the following function:

from functools import wraps
from time import time

def timing(f):
    @wraps(f)
    def wrap(*args, **kw):
        ts = time()
        result = f(*args, **kw)
        te = time()
        print(f"took: {(te - ts) * 1000} ms")
        return result

    return wrap

Fix library dependencies

While working on the library when installing its dependencies, the packaging tool noticed, that the names of the PyPi packages were not correctly specified in setup.cfg. Rename rest_framework to djangorestframework and jwt to PyJWT.

It appeared as a bug, as jwtis actually a different library and caused the application to fail as it was installed instead of PyJWT.

Django application with Integration tests

Is your feature request related to a problem? Please describe.
To properly review the merge requests and ensure that changes do not break the community's integrations and deployments, we need integration tests that would be run with the contributed change requests from merge requests etc.

Describe the solution you'd like
One could have the integration tests on their own projects using the library, but it would be useful to have a sample Django application in the project that integrates the library and runs the tests.

Describe alternatives you've considered
This requires the setup of Keycloak. Will it make the project too heavy or complex to test?

Additional context
How can we leverage Github pipelines and runners to optimise this effort? What experience from other projects we can replicate here?

/cc @simao-silva @moritz89 @jaimeventura

Keycloak 401 on reading user info

Describe the bug
Keycloak 401 error after a few minutes when trying to access the Keycloak API

To Reproduce
Steps to reproduce the behavior:

  1. Read user info from KeycloakUser
  2. Wait 5 minutes
  3. Read user info from KeylcoakUser

Expected behavior
No exceoption and email, name returned

Additional context
Problem is that the refresh token is not refreshed. The KeycloakAdmin class has to be configured to get a refresh token and update the access token.

Invalid install_requires configuration

Could it be that the current state of the install_requires in the setup.cfg file is invalid? Trying to install the current version of the package directly from Github results in an install failure. It seems to be from a commit that I introduced in the last MR.

A fix would be to use >= instead of ~= in the setup.cfg file.

pipenv install -e git+https://github.com/urbanplatform/django-keycloak-auth.git@master#egg=django_uw_keycloak

Courtesy Notice: Pipenv found itself running within a virtual environment, so it will automatically use that environment, instead of creating its own for any project. You can set PIPENV_IGNORE_VIRTUALENVS=1 to force pipenv to ignore that environment and create its own instead. You can set PIPENV_VERBOSITY=-1 to suppress this warning.
Installing -e git+https://github.com/urbanplatform/django-keycloak-auth.git@master#egg=django_uw_keycloak...
Error:  An error occurred while installing -e git+https://github.com/urbanplatform/django-keycloak-auth.git@master#egg=django_uw_keycloak!
Error text: Obtaining django_uw_keycloak from git+https://github.com/urbanplatform/django-keycloak-auth.git@master#egg=django_uw_keycloak (from -r /tmp/pipenv-_zrizod4-requirements/pipenv-tjpqe814-requirement.txt (line 1))
  Updating /home/moritz/.virtualenvs/core-FEar66-8/src/django-uw-keycloak clone (to revision master)
  Preparing metadata (setup.py): started
  Preparing metadata (setup.py): finished with status 'error'

  Running command git fetch -q --tags
  Running command git reset --hard -q 6dd764c3b6df785821fd9a60d3bbc7fbc76ec73e
  error: subprocess-exited-with-error
  
  × python setup.py egg_info did not run successfully.
  │ exit code: 1
  ╰─> [43 lines of output]
      Traceback (most recent call last):
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/requirements.py", line 102, in __init__
          req = REQUIREMENT.parseString(requirement_string)
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/pkg_resources/_vendor/pyparsing.py", line 1654, in parseString
          raise exc
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/pkg_resources/_vendor/pyparsing.py", line 1644, in parseString
          loc, tokens = self._parse( instring, 0 )
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/pkg_resources/_vendor/pyparsing.py", line 1402, in _parseNoCache
          loc,tokens = self.parseImpl( instring, preloc, doActions )
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/pkg_resources/_vendor/pyparsing.py", line 3417, in parseImpl
          loc, exprtokens = e._parse( instring, loc, doActions )
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/pkg_resources/_vendor/pyparsing.py", line 1406, in _parseNoCache
          loc,tokens = self.parseImpl( instring, preloc, doActions )
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/pkg_resources/_vendor/pyparsing.py", line 3205, in parseImpl
          raise ParseException(instring, loc, self.errmsg, self)
      pkg_resources._vendor.pyparsing.ParseException: Expected stringEnd (at char 15), (line:1, col:16)
      
      During handling of the above exception, another exception occurred:
      
      Traceback (most recent call last):
        File "<string>", line 2, in <module>
        File "<pip-setuptools-caller>", line 34, in <module>
        File "/home/moritz/.virtualenvs/core-FEar66-8/src/django-uw-keycloak/setup.py", line 8, in <module>
          setup()
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/setuptools/__init__.py", line 152, in setup
          _install_setup_requires(attrs)
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/setuptools/__init__.py", line 145, in _install_setup_requires
          dist.parse_config_files(ignore_option_errors=True)
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/_virtualenv.py", line 21, in parse_config_files
          result = old_parse_config_files(self, *args, **kwargs)
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/setuptools/dist.py", line 807, in parse_config_files
          self._finalize_requires()
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/setuptools/dist.py", line 534, in _finalize_requires
          self._move_install_requirements_markers()
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/setuptools/dist.py", line 573, in _move_install_requirements_markers
          inst_reqs = list(pkg_resources.parse_requirements(spec_inst_reqs))
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 3099, in parse_requirements
          yield Requirement(line)
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 3109, in __init__
          super(Requirement, self).__init__(requirement_string)
        File "/home/moritz/.virtualenvs/core-FEar66-8/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/requirements.py", line 104, in __init__
          raise InvalidRequirement(
      pkg_resources.extern.packaging.requirements.InvalidRequirement: Parse error at "'~= "3.0"'": Expected stringEnd
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed

× Encountered error while generating package metadata.
╰─> See above for output.

note: This is an issue with the package mentioned above, not pip.
hint: See above for details.

This is likely caused by a bug in django_uw_keycloak. Report this to its maintainers.
✘ Installation Failed

IntegrityError null value in column "first_name" of relation "users_keycloakprofile" violates not null constraint

Describe the bug
After being logged in for some time, the user gets a 500 error, "null value in column "first_name" of relation "users_keycloakprofile" violates not null cosntraint".
It's not explicit, after debbuging we could find out that the token has expired, because if we ask for a new one it works. This doesn't happen every time, just every now and then.

To Reproduce
Steps to reproduce the behavior:

  1. Login with your credentials in a Mobile App calling a Django API served by this library
  2. Remain in the UI and allow your token to expire
  3. Click somewhere that calls the Django API
  4. See error crashing the Django project

Expected behavior
When the token is expired, we want to receive a 401 Not Authorized, however we get a 500(null value in column "first_name" of relation "users_keycloakprofile" violates not null cosntraint)

Screenshots
198083275-5af6fb7d-ff2d-4ddd-bf03-5d1018cd416e

Desktop (please complete the following information):

  • OS: windows
  • Browser: chrome
  • Version: v.106

Enable dependabot

Is your feature request related to a problem? Please describe.
Provides an automated vulnerability report and MRs to fix vulnerable dependencies

Describe the solution you'd like
Enable Github's dependabot in the settings

Describe alternatives you've considered
Integrating safety check in the Github actions

[bug] user with no email in keycloak are failing to login in Django

Describe the bug
A user has been registered to keyCloak and has username and password but no email (username can be phone number OR a string).
if user attempts to login into Django backend, Django is throwing IntegrityError

To Reproduce
Steps to reproduce the behavior:

  1. create a user in KeyCloak but don't assign an email. make it optional
  2. generate a credentials for that user
  3. visit Django admin page EX: http://localhost:8000/admin/
  4. put username and password same as KeyCloak
  5. You will see the error

workaround:

  1. after seeing the error, Go back to keyCloak and assign any email to that user.
  2. Now you can login to Django admin

Expected behavior
Allowing access to Django admin with no email

Screenshots
image

Desktop (please complete the following information):

  • docker container - backend - FROM python:3.11-slim-bullseye
  • docker container - IAM - FROM quay.io/keycloak/keycloak:18.0

Additional context
Main dependencies

djangorestframework==3.14.0
Django==4.1.3
django-uw-keycloak==2.0.1
python-keycloak==2.6.0

Could we make URLs more configurable?

I would love to use this library without changing the code.
The URLs are configured in urls.py. In my case I have to remove the /auth from every url because our IT has removed that from the keycloak urls.
Can we add an option to this library to make URLs configurable in settings.py?

Superfluous GraphQL middleware

The Graphene middleware (KeycloakGrapheneMiddleware) does not have any additional functionality over the standard middleware (KeycloakMiddleware). Both of them only add the user object to the request through the request's token. The only difference is that the Graphene middleware checks this for each field in the GraphQL query even though performing this once when the query is received is adequate.

The main reason for this issue is to remove it to avoid confusing future users of the library and simplifying the remaining middleware.

Formatting rules

If contributions are welcome, it would be of use to have a set of formatting rules to keep a consistent and automatically formatted code base. Is such a set of rules available?

Make middleware async capable

When using an ASGI server, it is more efficient if the entire middleware stack is async capable. A small change to the middleware allows the KeycloakMiddleware to support being async.

[docs] how to register new user from Django to keyCloak and sign-in - JWT

Is your feature request related to a problem? Please describe.
I am still new to Django and KeyCloak, I integrated Django with KeyCloak container thanks to your repo.
Now I am trying to implement signing up, sign in, sign out and token verification from Django to KeyCloak as KeyCloak is the source of truth when it comes to IAM but I am not finding a clear documentation of how to do so.

Describe the solution you'd like
I used to extend AUTH_USER_MODEL to my AUTH MODEL before( ex: AUTH_USER_MODEL='app.CustomUser')

Now it's set to AUTH_USER_MODEL = "django_keycloak.KeycloakUserAutoId"

Currently if any user sign up in KeyCloak will grant access to django via REST endpoints, but I don't how can I make Django verify their identity via REST. it's done via GUI and I saw the users and synced it to KeyCloak container. But now I want to build up a full IAM flow.

I am expecting KeyCloak to generate JWT token to be provided to frontend to use it, then as a backend I need to verify the TOKEN and authorization. Not only authentication

Describe alternatives you've considered
Going back to Auth model with no keyCloak but I am still studying how can I implement my requirements

Additional context
I am stuck in here, I don't know how can I login or verify against keyCloak with dynamic way. So, if I changed keyCload later on. I should be modifying service layer and not REST layer

from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
# Create your views here.
class LoginView(APIView):

    def post(self, request):
        # serializer = LoginSerializer(data=request.data)
        # serializer.is_valid(raise_exception=True)
        # user = UserService.login(username=data.username, password=data.password)
        return Response({'message':'validate'}, status=status.HTTP_202_ACCEPTED)

Fix _is_client_token_timed_out for timed out tokens exceeding grace period

The check if the client token is timed out is broken. None is returned when trying to decode an expired token. However, the function _is_client_token_timed_out still tries to access the expiry (exp) and issued at time (iat). This causes a TypeError as None is not subscriptable.

A fix would be to return true to the expired check if the decoding of the token returns None.

The error happens at django_keycloak/keycloak.py:337

Improve Readme

1st suggestion

When using GraphQL the middleware must only be declared in the GRAPHENE setting

image

and so, not declared in the MIDDLEWARE

image

2nd suggestion

after version 1.1.1 add in the KEYCLOAK_CONFIG -> 'DECODE_TOKEN': True

KEYCLOAK_CONFIG = {
    'SERVER_URL': '<PUBLIC_SERVER_URL>',
    'INTERNAL_URL': '<INTERNAL_SERVER_URL>', # Optional: Default is SERVER_URL
    'BASE_PATH': '', # Optional: Default matches Keycloak's default '/auth'
    'REALM': '<REALM_NAME>',
    'CLIENT_ID': '<CLIENT_ID>',
    'CLIENT_SECRET_KEY': '<CLIENT_SECRET_KEY>',
    'CLIENT_ADMIN_ROLE': '<CLIENT_ADMIN_ROLE>',
    'REALM_ADMIN_ROLE': '<REALM_ADMIN_ROLE>',
    'EXEMPT_URIS': [],  # URIS to be ignored by the package
    'GRAPHQL_ENDPOINT': 'graphql/',  # Default graphQL endpoint
    'DECODE_TOKEN': True # **!!!ADDED!!!**
}
      

Make test mixin explicit

Currently KeycloakTestMixin overrides the setUp and tearDown functionality of TestCase to perform its user clean up. However, this approach is not very clear and can cause errors when not included in the correct order as a sub-class. Therefore, a more robust approach would be for the test class to call them explicitly in its own setUp and tearDown functions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.