fastapi-keycloak icon indicating copy to clipboard operation
fastapi-keycloak copied to clipboard

Required custom roles

Open hall-b opened this issue 3 years ago • 8 comments

In the Quickstart code example we can see that for the admin endpoint, the user needs to have the "admin" role assigned in order to proceed. This is a great feature.

However, from what I noticed, this function checks only the roles that we can find under "realm_access" -> "roles". There are also other roles that can be found under "resource_access" for each defined client in keycloak.

How can I create this filter based on roles with a custom keycloak client that has its own custom roles?

Thanks in advance for your reply!

hall-b avatar May 19 '22 13:05 hall-b

Hey @albanlienart,

I believe this inquiry is not related to this package. However, we have another package, that focuses on the described use case: FastAPI Auth Middleware. Check out https://fastapi-auth-middleware.code-specialist.com/examples/simple_with_scopes/ for a specific example. I hope I got you right.

Please close this issue if that resolved your question 🙂

yannicschroeer avatar May 19 '22 15:05 yannicschroeer

Hey @yannicschroeer ,

Thanks for the quick reply ! It is related, I was just wondering if we can check some custom roles coming from other clients from keycloak. It is similar to what already exists, I would just give a bit more flexibility ;)

But the package you mention seems interesting, I'll have a look !

hall-b avatar May 19 '22 16:05 hall-b

Well, if you want to use custom roles, it is by definition not related to keycloak and thereby not this package. You can use your own roles by managing them via keycloak, but if you want to use custom roles from another client, you will need a custom implementation or another package, as this one focuses on keycloak. I can understand your motivation but I don't see that in the scope of this package.

yannicschroeer avatar May 20 '22 08:05 yannicschroeer

I was speaking about custom roles that you can define inside keycloak. When you create a new client inside keycloak, you can define roles related to that client. I'm speaking about those roles.

Anyway, I guess the package you mention can be used to do so. On my side, I implemented a custom role verifying function to not depend upon too many external dependencies.

Thanks for your interactions!

hall-b avatar May 20 '22 09:05 hall-b

Oh okay, sorry, seems I got you wrong after all. Your request is legit and will be considered for implementation, it indeed increases the flexibility. A pull request from your side would be appreciated 😊 otherwise we will leave this open as an enhancement until either me or someone else finds the time to implement this

yannicschroeer avatar May 20 '22 09:05 yannicschroeer

I'm trying to play around with this since we also need the client roles for access control. My first step is to define a property that returns the roles for the client. Given that the user can have different roles in multiple clients, I assumed that the current client is the azp. The property code looks similar to how the realm roles property is defined in OIDCUser.

# in class OIDCUser
azp: str
...
@property
def client_roles(self) -> List[str]:
    """Returns the roles of the user in the current authorized party

    Returns:
        List[str]: If the resource access dict contains roles for the current authorized party.
    """
    if not self.azp:
        raise KeycloakError(
            status_code=404,
            reason="The 'azp' section of the provided access token is missing",
        )        
    if not self.resource_access:
        raise KeycloakError(
            status_code=404,
            reason="The 'resource_access' section of the provided access token is missing",
        )
    if not self.resource_access[self.azp]:
        raise KeycloakError(
            status_code=404,
            reason=f"The 'resource_access' section of the provided access token did not contain the client {self.azp}.",
        )
    try:
        return self.resource_access[self.azp]["roles"]
    except KeyError as e:
        raise KeycloakError(
            status_code=404,
            reason=f"The 'resource_access' section of the provided access token did not contain any 'roles' for {self.azp}.",
        ) from e

My problem right now is I'm not really sure if the azp will always be included in the token since it is optional by definition (see https://openid.net/specs/openid-connect-core-1_0.html#IDToken).

azp OPTIONAL. Authorized party - the party to which the ID Token was issued. If present, it MUST contain the OAuth 2.0 Client ID of this party. This Claim is only needed when the ID Token has a single audience value and that audience is different than the authorized party. It MAY be included even when the authorized party is the same as the sole audience. The azp value is a case sensitive string containing a StringOrURI value.

edgarfelizmenio avatar Aug 11 '22 10:08 edgarfelizmenio

Hi @edgarfelizmenio , Do you have started a branch somewhere for a PR?

remicres avatar Oct 20 '22 09:10 remicres

I made a small PR, inspired from @edgarfelizmenio idea

The returned roles are now the concatenation of the following:

  • everything in realm_access["roles"]
  • everything in resource_access[azp]["roles"] (only when azp is defined)

remicres avatar Oct 20 '22 10:10 remicres