Code Monkey home page Code Monkey logo

keycloak-restrict-client-auth's Introduction

Keycloak: Restrict user authorization on clients

This is a simple Keycloak authenticator to restrict user authorization on clients.

GitHub release (latest SemVer) Keycloak Dependency Version GitHub Release Date Github Last Commit

CI build open issues CodeScene general

Quick introduction (Video interview with Niko Köbler)

Youtube Video - Interview with Niko Köbler

What is it good for?

As a Keycloak consultant, I often receive inquiries about restricting user authorization for specific clients. People commonly ask,

Can I allow certain users to authenticate with a client while denying access to others?

While the answer used to be "no" for out-of-the-box Keycloak, I have developed this extension to meet this need. but I recommend taking the time to understand the potential security implications before using this extension.

So, before using this extension, please take a moment to review the security considerations outlined in the security consideration section.

How does it work?

The authenticator can work either role-based or policy-based.

Role-based mode

In this mode, the authenticator uses client roles to restrict authentication. It works like this:

  • The authenticator checks whether a client defines a role named restricted-access
    • If it does the authenticator checks whether the user has that role
      • If it does, the authenticator returns success (i.e. authentication is successful)
      • If it does not, the authenticator returns failure (i.e. authentication is unsuccessful)
    • If it does not, the authenticator returns success (i.e. authentication is successful).

This means that you can enable the authenticator on a per-client basis by adding a client role named restricted-access to your client. A client with that role has the authenticator enabled. Only users with that role can authenticate to that client.

Policy-based mode

In this mode, the authenticator uses client resources, permissions and policies to restrict authentication. This mode only works for confidential OIDC clients with authorization enabled. It works like this:

  • The authenticator checks whether a client defines a resource named Keycloak Client Resource
    • If it does, the authenticator checks whether policies and permission evaluate to PERMIT
      • If it does, the authenticator returns success (i.e. authentication is successful)
      • If it does not, the authenticator returns failure (i.e. authentication is unsuccessful)
    • If it does not, the authenticator returns success (i.e. authentication is successful).

This means that you can enable the authenticator on a per-client basis by adding a resource named Keycloak Client Resource to your client. A client with that resource has the authenticator enabled. Users will only be able to authenticate to such a client if the associated policies and permission permit access.

How to install?

Download a release (*.jar file) that works with your Keycloak version from the list of releases. Follow the below instructions depending on your distribution and runtime environment.

Standalone (without container)

Copy the jar to the providers folder and execute the following command:

${kc.home.dir}/bin/kc.sh build

Container image (Docker)

For Docker-based setups mount or copy the jar to /opt/keycloak/providers.

If you are using RedHat SSO instead of Keycloak open source, mount or copy the jar to /opt/eap/providers/.

You may want to check docker-compose.yml as an example.

Maven/Gradle

Packages are being released to GitHub Packages. You find the coordinates here!

It may happen that I remove older packages without prior notice, because the storage is limited on the free tier.

How to configure?

  • Create a new flow per binding (e.g. browser flow, direct grant flow etc.)

  • Add a sub-flow e.g. named Login and mark it as Required

  • Add an authenticator execution Restrict user authentication on clients and mark the execution as Required.

  • Within the Login sub-flow add authenticators/executions/conditionals and further sub-flows as needed (see Keycload documentation for details

  • Then bind your newly created flow as desired - either as a default for the whole realm or on a per-client basis.

    See the image below for an example. Example flow

  • Follow instructions below for the desired mode

⚠️ User identity:

The authenticator needs a user identity to check whether the user has the desired role or not. Hence, ensure that you have steps/executions in your flow prior to this authenticator that can ensure user's identity.

Client Role based mode

  1. Configure the authenticator by clicking on Actions -> Config and select client-role as the Access Provider. Role-based access restriction

  2. Add a role named restricted-access to the client you want to restrict access to.

    See the image below for an example. Client role configuration

  3. Afterwards, no user can authenticate to this client. To allow a user to authenticate, assign the role restricted-access to the user. You may do so either by assigning the role to the user directly or via groups or combined roles.

Changing the role name

You do not like the role name restricted-access or you do have some kind of naming conventions in place? You can change the role name globally by configuring the provider.

spi-restrict-client-auth-access-provider-client-role-enabled=true
spi-restrict-client-auth-access-provider-client-role-client-role-name=custom-role

For details on SPI and provider configuration, please refer to Configuring providers guide.

Resource Policy based mode

⚠️ OIDC only:

Policy-based mode only works with OIDC clients (Client Protocol must be openid-connect)

  1. Configure the authenticator by clicking on Actions -> Config and select policy as the Access Provider. Policy-based access restriction
  2. Configure the Access Type of the client to confidential
  3. Set Authorization Enabled to on
  4. Go to Authorization -> Resources and click Create to create a new resource Resource configuration
  5. Set the Name and Display name to Keycloak Client Resource and keep the other fields blank
  6. Save the resource Resources overview
  7. Click Create Permission to add permissions and policies (see Authorization Services Guide for details)
  8. Afterwards, no user can authenticate to this client unless permissions have been granted by configured policies.

Using a custom error message

If a user tries to log in via a browser-based flow and access gets denied by the authenticator, a custom error message can be displayed. In the flow choose the Actions button and then choose Config. You will see the following configuration screen.

Error message configuration

You can directly define a particular message or use a property, which will be used for mapping the error message. If you choose a property, the property will be looked up from your custom theme's messages*.properties files and therefore supports internationalization.

# messages.properties
restricted-access.denied=Access denied. User is missing required role 'restricted-access'
# messages_de.properties
restricted-access.denied=Zugriff verweigert. Dem Benutzer fehlt die notwendige Rolle 'restricted-access'.

If the field is left blank, default property access-denied is used. In this case you do not need a custom theme, since this property comes with Keycloak out of the box. For details on how to add custom messages to Keycloak, please refer to section Messages and Internationalization in the server developer guide.

Client Policy support

⚠️ Feature preview:

Support for client policies is currently feature preview. I am happy to get some feedback on this. However, depending on feedback the feature may be changed or even be removed again in the future.

Since version 18.1.0 this extension has basic built-in support for client policies.

Conditions

This extension provides a client policy condition named restrict-client-auth-enabled to check whether user authentication on a client has been restricted or not.

Executors

This extension provides a client policy executor named restrict-client-auth-auto-config to automatically enable restricted access for clients. The executor can be cofigured to either enable restricted access based on resource policies or based on client role.

Security considerations

Policy enforcement

To avoid any confusion, it is important to note that this extension is not a policy enforcement point (PEP). It does not enforce authorization decisions. It is part of making the authorization decision, but it does not enforce it. Clients must enforce decisions being made.

According to the OIDC specification/OpenID Connect Core 1.0 incorporating errata set 1, it is the responsibility of the client to check the audience claims. Section 3.1.3.7. ID Token validation, point 3ff state that

The Client MUST validate that the aud (audience) Claim contains its client_id value registered at the Issuer identified by the iss (issuer) Claim as an audience. [...]

And further it is very clear about the enforcement by the client:

The ID Token MUST be rejected if the ID Token does not list the Client as a valid audience, or if it contains additional audiences not trusted by the Client. If the ID Token contains multiple audiences, the Client SHOULD verify that an azp Claim is present. If an azp (authorized party) Claim is present, the Client SHOULD verify that its client_id is the Claim Value.

So, by design this extension cannot be a PEP.

What this extension supports you with is authorization decision-making and communicating the outcome to the user during login flow. If configured correctly, it will prevent issuance of tokens that contain an audience or authorized party claim for a client that users do not have access to.

Token issuance or non-issuance is (beside claims in the token) just one way to communicate the outcome of authorization decision-making. It is not enforcement of the decision.

Make sure your clients enforce decisions correctly and ensure validation auf aud (audience) and azp (authorized party) claims.

If you are using a Keycloak adapter, make sure your clients are verifying the audience claim by enabling verify-token-audience in your adapter config.

Protect all possible flows

Ensure that you protect authentication to your clients in all flows a user may access. This includes not just the browser flow or the other realm-wide flows, but also identity provider overrides and post login flows.

Here is one example: suppose a user tries to log in via the built-in browser flow, at the end of which you have added the "Restrict user authentication on clients" step. If the "Cookie" or "Forms" alternative is used, the user will proceed to this step and be evaluated. But if it is the "Identity Provider Redirector" alternative which gets used, the subsequent steps will be skipped and the user will not be subject to this validation (this is a general feature of how brokering works in Keycloak authentication flows, not specific to this plugin). This extension must also be configured in the identity provider's post login flow in order to apply.

Disable the Audience Resolve mapper if necessary

The Audience Resolve protocol mapper is enabled by default by client scope roles, but it may be necessary to remove it in some cases. Failing to set up audience claims correctly may result in a token containing the restricted client as an audience claim, even if the user does not have access to that client.

Frequently asked questions

Does it work with the legacy Wildfly-based Keycloak distro?

Maybe! There is even a high chance it will, since this extension does not make use of any Quarkus-related functionality. For installation instructions, please refer to an older version of this readme.

Please note that with the release of Keycloak 20.0.0 the Wildfly-based distro is no longer supported. Hence, I dropped support for the Wildfly-based distro already. Though this library may still work with the Wildfly-based distro, I will no longer put any efforts into keeping this extension compatible.

Does it work with Keycloak version X.Y.Z?

If you are using Keycloak version X (e.g. X.y.z), version X.b.c should be compatible. Keycloak SPIs are quite stable. So, there is a high chance this authenticator will work with other versions, too. Check the details of latest build results for an overview or simply give it a try.

Authenticator version X.b.c is compiled against Keycloak version X.y.z. For example, version 16.3.1 will be compiled against Keycloak version 16.y.z.

I do not guarantee what version a.b or y.z will be. Neither do I backport features to older version, nor maintain any older versions of this authenticator. If you need the latest features or bugfixes for an older version, please fork this project or update your Keycloak instance. I recommend doing the latter on regular basis anyways.

Why not use "Allow/Deny Access" authenticators with conditions?

With Keycloak 13 two new authenticators have been added, namely Allow Access and Deny Access. Together with Condition - User Role authenticator authentication may be restricted in a similar way with out-of-the-box features. So, the question is why not use that and override authentication flows on a per client basis?

Here are some reasons/thoughts

  • It is not really flexible. Since Condition - User Role only allows for checking one concrete (realm or client-specific) role, a very complex flow handling all clients, or a totally separate flow for each individual client would be needed.
  • It simply does not work well with federated authentication (ie. identity provider redirects), since there is no way to configure client specific behaviour for First login flow or Post login flows. In other words, there is no feature like Authentication flow overrides at an IdP level. Hence, the same flow will be used for all clients. As said before, this becomes very complicated.

Getting error KC-SERVICES0013: Failed authentication

When getting an error or warning like this,

WARN  [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-26) REQUIRED and ALTERNATIVE elements at same level! Those alternative executions will be ignored: [auth-cookie, identity-
provider-redirector, null]
WARN  [org.keycloak.services] (default task-26) KC-SERVICES0013: Failed authentication: org.keycloak.authentication.AuthenticationFlowException: authenticator: restrict-client-auth-authenticator

you have mostlikely mixed required and alternative subflows/steps/authenticators at the same level in your custom flow. Keycloak does not support this.

Make sure you do not combine required and alternative authenticators at the same level. See the following image for details:

Flow explained

keycloak-restrict-client-auth's People

Contributors

actions-user avatar bhaugeea avatar danifr avatar dependabot[bot] avatar sventorben 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

keycloak-restrict-client-auth's Issues

[BUG] Cannot find authentication provider implementation with provider ID 'basic-auth'

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

I've updated Keycloak and this provider to 23.0.6 and 23.0.0 respectively. While everything was running perfectly on Keycloak v21, I cannot figure out why this provider suddenly doesn't work anymore. When logging in on my client, or when going to the Browser restricted client auth flow on the admin pages, the below error is thrown.

Cannot find authentication provider implementation with provider ID 'basic-auth'

I've spent many hours trying to make sure the .jar file is correctly installed and trying different things to get everything to work. The issue is definitely coming from somewhere in this package because the normal browser auth works fine. Any info would be great appreciated.

Expected Behavior

No response

Steps To Reproduce

No response

Version

- Keycloak: 23.0.6
- This extension: 23.0.0

Anything else?

No response

Support for customised messages per client

Is there an existing feature request for this?

  • I have searched the existing issues

Is your feature related to a problem? Please describe.

No response

Describe the solution you'd like

Each client will check different requirements, so the message to the user should explain the reason why access has been denied.

Describe alternatives you've considered

I have made a modification to the RestrictClientAuthAuthenticator.htmlErrorResponse method to look for whether there are messages of the form . and in that case that message is displayed instead of the configured in the authentication step

Anything else?

No response

[BUG] Regex Policy based on multivalued attributes

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Using keycloak-restrict-client-auth` with Policy-Based mode. When I want to use Regex Client Policy on multivalue attributes it does not work.
For example, I have User user1 with an attribute:

"attr": [
    "1test",
    "2test"
  ],

image

If I define the target_claim to my_attr and regex pattern to 1test it works, but when I would like to check the 2test I have no idea how to do it 😞. Do you know any solution?
image

Expected Behavior

Check each value from multivalued attribute not only first.

Steps To Reproduce

  1. Create Policy-Based flow,
  2. Use Regex policy based on multivalued attribute
  3. Check the second value of attribute in Policy

Version

- Keycloak: 24.0.1
- This extension: 24.0.0

Anything else?

No response

Unable to install the extension

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

  1. After adding SPI in the provider folder executing build command I am getting this logs, I am not sure whether the SPI installed correctly or not

logs:
`admin:~/keycloak/keycloak-22.0.0/bin$ ./kc.sh build
Updating the configuration and installing your custom providers, if any. Please wait.
2023-07-18 10:26:09,542 WARN [org.keycloak.services] (build-25) KC-SERVICES0047: restrict-client-auth-authenticator (de.sventorben.keycloak.authorization.client.RestrictClientAuthAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2023-07-18 10:26:09,580 WARN [org.keycloak.services] (build-25) KC-SERVICES0047: policy (de.sventorben.keycloak.authorization.client.access.policy.PolicyBasedAccessProviderFactory) is implementing the internal SPI restrict-client-auth-access-provider. This SPI is internal and may change without notice
2023-07-18 10:26:09,580 WARN [org.keycloak.services] (build-25) KC-SERVICES0047: client-role (de.sventorben.keycloak.authorization.client.access.role.ClientRoleBasedAccessProviderFactory) is implementing the internal SPI restrict-client-auth-access-provider. This SPI is internal and may change without notice
2023-07-18 10:26:09,599 WARN [org.keycloak.services] (build-25) KC-SERVICES0047: restrict-client-auth-auto-config (de.sventorben.keycloak.authorization.client.clientpolicy.executor.AutoConfigClientPolicyExecutorFactory) is implementing the internal SPI client-policy-executor. This SPI is internal and may change without notice
2023-07-18 10:26:09,940 WARN [org.keycloak.services] (build-25) KC-SERVICES0047: restrict-client-auth-enabled (de.sventorben.keycloak.authorization.client.clientpolicy.condition.RestrictedClientAuthEnabledPolicyConditionProviderFactory) is implementing the internal SPI client-policy-condition. This SPI is internal and may change without notice
2023-07-18 10:26:09,950 WARN [io.quarkus.arc.deployment.SplitPackageProcessor] (build-19) Detected a split package usage which is considered a bad practice and should be avoided. Following packages were detected in multiple archives:

  • "de.sventorben.keycloak.authorization.client.access.policy" found in [/home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth-22.0.0.jar, /home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth.jar]
  • "de.sventorben.keycloak.authorization.client.clientpolicy.executor" found in [/home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth-22.0.0.jar, /home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth.jar]
  • "de.sventorben.keycloak.authorization.client.clientpolicy.condition" found in [/home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth-22.0.0.jar, /home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth.jar]
  • "de.sventorben.keycloak.authorization.client.access.role" found in [/home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth-22.0.0.jar, /home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth.jar]
  • "de.sventorben.keycloak.authorization.client" found in [/home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth-22.0.0.jar, /home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth.jar]
  • "de.sventorben.keycloak.authorization.client.common" found in [/home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth-22.0.0.jar, /home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth.jar]
  • "de.sventorben.keycloak.authorization.client.access" found in [/home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth-22.0.0.jar, /home/ggadmin/keycloak/keycloak-22.0.0/lib/../providers/keycloak-restrict-client-auth.jar]
    2023-07-18 10:26:10,344 WARN [io.quarkus.arc.processor.BeanArchives] (build-24) Failed to index org.keycloak.models.map.storage.jpa.JpaMapStorageProviderFactory: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD@592e843a
    2023-07-18 10:26:10,345 INFO [io.quarkus.arc.processor.IndexClassLookupUtils] (build-24) Class for name: org.keycloak.models.map.storage.jpa.JpaMapStorageProviderFactory was not found in Jandex index. Please ensure the class is part of the index.
    2023-07-18 10:26:12,198 INFO [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 3973ms
    Server configuration updated and persisted. Run the following command to review the configuration:`

2.I dont see any option which is metioned in the document
Configure the **authenticator** by clicking on **Actions** -> **Config** and select client-role as the Access Provider.

image

image

Expected Behavior

it should provide the UI to create client role

Steps To Reproduce

Download latest jar from the link https://github.com/sventorben/keycloak-restrict-client-auth/releases/download/v22.0.0/keycloak-restrict-client-auth.jar

${kc.home.dir}/bin/kc.sh build

Version

- Keycloak:22.0.0
- This extension:22.0.0

Anything else?

No response

[BUG] Error Settings Menu for Flow Step

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

After copying the Browser Flow and adding the Restrict user authentication on clients , I cant go in settings of this card, because I get the error can't convert undefined to object . In the browser console I see the error

TypeError: can't convert undefined to object                                                    index.4ad08902.js:25:73

Expected Behavior

It should show the Settings UI as described in the Readme

Steps To Reproduce

Using Podman on Coreos:
Dockerfile

          ARG KEYCLOAK_VERSION=19.0.2
          ARG KEYCLOAK_RESTRICTED_CLIENT_AUTH_VERSION=19.0.0
          
          FROM quay.io/keycloak/keycloak:latest
          ARG KEYCLOAK_RESTRICTED_CLIENT_AUTH_VERSION
          
          ENV KC_DB=mariadb
          #ENV KC_FEATURES=declarative-user-profile
          
          RUN curl -fsSL https://github.com/sventorben/keycloak-restrict-client-auth/releases/download/v19.0.0/keycloak-restrict-client-auth.jar \
                -o /opt/keycloak/providers/keycloak-restrict-client-auth.jar
          
          RUN /opt/keycloak/bin/kc.sh build

Service for building the the Image

    - name: keycloak-build.service
      enabled: true
      contents: |
        [Unit]
        Description=Build custom kecloak container with client auth plugin
        Requires=network-online.target
        After=network-online.target

        [Service]
        Type=oneshot
        RemainAfterExit=yes
        ExecStart=/bin/podman build --no-cache -t mykeycloak /var/srv/builds/mykeycloak/
        ExecStop=sh -c 'podman image exists mycaddy && podman rmi --force mykeycloak'

        [Install]
        WantedBy=multi-user.target

Keycloak Service:

       - name: keycloak-app.service
      enabled: true
      contents: |
        [Unit]
        Description=Run keycloak
        Wants=network-online.target
        After=network-online.target
        RequiresMountsFor=%t/containers
        BindsTo=keycloak.service  
        After=keycloak.service

        [Service]
        Environment=PODMAN_SYSTEMD_UNIT=%n
        Restart=on-failure
        TimeoutStopSec=70
        ExecStartPre=/bin/rm -f %t/%n.ctr-id
        ExecStart=/usr/bin/podman run \
          --cidfile=%t/%n.ctr-id \
          --cgroups=no-conmon \
          --rm \
          --pod-id-file %t/keycloak.pod-id \
          --sdnotify=conmon \
          --replace \
          --detach \
          --name keycloak-app \
          --env KEYCLOAK_ADMIN=test \
          --env KEYCLOAK_ADMIN_PASSWORD=test mykeycloak start \
          --hostname=auth.${domain} \
          --proxy=edge \
          --db=mariadb \
          --db-url=jdbc:mariadb://keycloak-db.localhost/test \
          --db-username=test \
          --db-password=test
        ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
        ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
        Type=notify
        NotifyAccess=all

        [Install]
        WantedBy=default.target


Version

- Keycloak: 19.0.2 quarkus
- This extension: 19.0.0

Anything else?

Screenshot from 2022-09-20 00-31-04

No access denied when access is denied

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Managed to get it to do what it needs to do: Grant access by IdP group and block access to other IdP users. But when a user doesn't have access the login page refreshes instead of showing an access-denied page

Expected Behavior

I was expecting to see an error of sorts so a user knows not to enter their credentials again in vain.

Steps To Reproduce

  1. Install Keycloak 19.0.3
  2. Install the jar file to the providers folder and run build
  3. Follow the rest of the instructions and verify that valid users are granted access while others and blocked.

Version

- Keycloak: 19.0.3
- This extension: 19.0.0

Anything else?

As I'm new to Keycloak it's quite possible that my issue is simply user error.

[question] Policy-based mode

Hi,
i'm interested by your extension, particular for policy-based mode. I have a question about this mode :
we can configure policy for client about differents endpoints, for exemple :

  • policy1: https://my-app.io/enterprise -> need group enterprise
  • policy2: https://my-app.io/lts -> need group lts
    The app has no authorization check, only authentication delegate to oidc provider.
    This use case can works with your extension, and, if right, how ?

Thx

[Feature] Support for configuring different role per client

Is there an existing feature request for this?

  • I have searched the existing issues

Is your feature related to a problem? Please describe.

Hi,

first of all, thanks a lot for making this SPI, it works very well and it is very easy to set up :)

I was wondering if there is a way I could configure this plugin so I can set a different role per client.

For example in my organization we have GitLab and Slack both protected with Keycloak. Since they both use a pay-per-user license model I only want users with the slack_user role to be authorized to use Slack and role_gitlab for gitlab.

Is this something currently possible? If not, do you think it can be something that could be added to the current code?

Thank you very much,
Daniel.

Describe the solution you'd like

No response

Describe alternatives you've considered

No response

Anything else?

No response

User without restricted-access role is being able to authenticate.

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

User without restricted-access role is still being able to authenticate. Role itself created both in realm and client (In both cases there is 0 assignments). My current configuration is similar to this one https://user-images.githubusercontent.com/12183470/136276665-6b087651-baa9-43aa-addf-59db247529b7.png

Screenshot 2023-12-05 at 13 18 35 Screenshot 2023-12-05 at 13 25 01 Screenshot 2023-12-05 at 13 25 43 Screenshot 2023-12-05 at 13 27 35

Expected Behavior

User without restricted-access role is not being able to authenticate.

Steps To Reproduce

No response

Version

- Keycloak: 22.0.4
- This extension: 22.0.0

Anything else?

No response

Enable "Always Display in Console" If user is in Restricted Group

Is there an existing feature request for this?

  • I have searched the existing issues

Is your feature related to a problem? Please describe.

When a users signs in to keycloak I would like to have them see all the applications they have access to without having to login to the site first and create a session.

Describe the solution you'd like

Hello,

I would like to know if it is possible to enable "Always Display in Console" option in the client settings if the user is a member of the restricted group? If I am not able to do it with the keycloak-restrict-client-auth, can you recommend another approach, whether programmatically or otherwise.

Much appreciated.

Describe alternatives you've considered

I thought about enabling "Always Display in Console" for all apps, customizing the accounts page using something like Javascript and hide the icon if the user is not in the restricted group.

Anything else?

No response

[BUG] Keycloak 17.0.0 support

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Build process cannot find Keycloak 17.0.0 due to changes in naming pattern.
See https://groups.google.com/g/keycloak-dev/c/RQpL7L4FRy0 for details.

Expected Behavior

No response

Steps To Reproduce

No response

Version

- Keycloak: 17.0.0 (quarkus and wildfly)
- This extension: 16.0.1

Anything else?

No response

Work with Multiple Client

Is there an existing feature request for this?

  • I have searched the existing issues

Is your feature related to a problem? Please describe.

This is more of a question then a feature request, but if the answer is no then it can be a feature request. Does this feature work with multiple clients, and by that I mean will it work to isolate more than one client?

Here is an example. Lets say I have 4 apps that I want to configure on one Realm. Can I create 4 different authenticators. Use those 4 different authenticators one per app, and users would be able to access 1, 2, 3 or 4 applications depending on their roles?

The problem trying to wrap my head around is if all clients have this restricted-access role needed for one or the other application, is it possible to have a user restricted to any more than 1 app at a time?

Describe the solution you'd like

No response

Describe alternatives you've considered

No response

Anything else?

No response

[BUG] Not authorized users can authenticate in client

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

When an user will be log in at a client that isn't authorized, the Keycloak deny the access, but if this user log in a client that are been authorized, this same user can log in everyone client while the session is valid.

Expected Behavior

The role validation must be run in everyone authentication maked by user

Steps To Reproduce

No response

Version

- Keycloak: 19.0.1
- This extension: 19.0.0

Anything else?

No response

[Doumentation] Document usage with other flows than login flow

Is there an existing feature request for this?

  • I have searched the existing issues

Is your feature related to a problem? Please describe.

Describe the usage of this extension in combination

  • with identity provider redirects and the usage of post-login flows.
  • registration flow
  • reset credentials flow
  • non-browser flows (e.g. direct grant, see #160)

See also #114, #121, or #224 as a starting point.

Describe the solution you'd like

No response

Describe alternatives you've considered

No response

Anything else?

No response

[BUG] Small error in the README

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

When configuring the jar, the README says to use this format

spi.restrict-client-auth-access-provider.client-role.client-role-name

But I couldn't get it to work unless I used all hyphens instead of dots.

spi-restrict-client-auth-access-provider-client-role-client-role-name

Expected Behavior

No response

Steps To Reproduce

No response

Version

- Keycloak:17.0.1
- This extension: Latest

Anything else?

No response

[BUG] Restriction with an Identity Provider appears to be non-functional

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

I am configuring the access restriction. I have no problem restricting access using Username Password Form. However, as soon as I use the configured identity provider, the restriction never applies.

Expected Behavior

The same operation between the Username/password connection and the identifty provider connection.

Steps To Reproduce

Here is the connection flow I have:

image

Version

- Keycloak: 19.0.1 (quarkus)
- This extension: 19.0.0

Anything else?

I searched through the existing issues, I did not find a clue to solve my problem. Sorry if this is the case.

I also wondered about "is this prodider supposed to work with an Identity Provider?". The only answer I could find in the README is here. And it just says, that this provider is better than the "Allow/Deny Access" feature which doesn't work with identity providers.

In any case, thank you for your work!

Can't identify a user

Hello,

At first I would like to say thank you for your attempt to resolve one the most popped up question regarding setting up restrictions for users.

I am one of those people who want to limit access for members of specific Active Directory group to a certain client. I found your solution and tried to apply to it. I did everything in accordance to the guide described in the description of the solution, but still did not get the desired behavior.

So here are some facts about the installation:
KeyCloak 15.0.2 running in Docker
PostgreSQL database is used
Authenticator is installed and is added into a custom authentication flow, which was copied from the standard Browser flow, as the latest step
image

The role restricted-access was created within client's configuration
image

and was added to group kiali_users
image

The Role Mappings of my user contains the info about assigned role
image

However, I can't log in to the client.
I found the following events in KeyCloak logs:

18:36:17,407 WARN  [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-26) REQUIRED and ALTERNATIVE elements at same level! Those alternative executions will be ignored: [auth-cookie, identity-
provider-redirector, null]
18:36:17,408 WARN  [org.keycloak.services] (default task-26) KC-SERVICES0013: Failed authentication: org.keycloak.authentication.AuthenticationFlowException: authenticator: restrict-client-auth-authenticator
        at [email protected]//org.keycloak.authentication.DefaultAuthenticationFlow.processSingleFlowExecutionModel(DefaultAuthenticationFlow.java:431)
        at [email protected]//org.keycloak.authentication.DefaultAuthenticationFlow.processFlow(DefaultAuthenticationFlow.java:253)
        at [email protected]//org.keycloak.authentication.AuthenticationProcessor.authenticateOnly(AuthenticationProcessor.java:990)
        at [email protected]//org.keycloak.authentication.AuthenticationProcessor.authenticate(AuthenticationProcessor.java:852)
        at [email protected]//org.keycloak.protocol.AuthorizationEndpointBase.handleBrowserAuthenticationRequest(AuthorizationEndpointBase.java:151)
        at [email protected]//org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildAuthorizationCodeAuthorizationResponse(AuthorizationEndpoint.java:300)
        at [email protected]//org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.process(AuthorizationEndpoint.java:183)
        at [email protected]//org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildGet(AuthorizationEndpoint.java:106)
        at jdk.internal.reflect.GeneratedMethodAccessor835.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at [email protected]//org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:138)
        at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:546)
        at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:435)
        at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$0(ResourceMethodInvoker.java:396)
        at [email protected]//org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:358)
        at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:398)
        at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:365)
        at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:150)
        at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:110)
        at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:141)
        at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:104)
        at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:440)
        at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:229)
        at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:135)
        at [email protected]//org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:358)
        at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138)
        at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215)
        at [email protected]//org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:245)
        at [email protected]//org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:61)
        at [email protected]//org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
        at [email protected]//javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
        at [email protected]//io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
        at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
        at [email protected]//org.keycloak.provider.wildfly.WildFlyRequestFilter.lambda$doFilter$0(WildFlyRequestFilter.java:41)
        at [email protected]//org.keycloak.services.filters.AbstractRequestFilter.filter(AbstractRequestFilter.java:43)
        at [email protected]//org.keycloak.provider.wildfly.WildFlyRequestFilter.doFilter(WildFlyRequestFilter.java:39)
        at [email protected]//io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
        at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
        at [email protected]//io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
        at [email protected]//io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
        at [email protected]//io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
        at [email protected]//io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
        at [email protected]//org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
        at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at [email protected]//io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
        at [email protected]//io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117)
        at [email protected]//io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
        at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at [email protected]//io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
        at [email protected]//io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
        at [email protected]//io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
        at [email protected]//io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
        at [email protected]//io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
        at [email protected]//io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
        at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at [email protected]//org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
        at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at [email protected]//org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
        at [email protected]//io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52)
        at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)
        at [email protected]//io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
        at [email protected]//io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
        at [email protected]//org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
        at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1530)
        at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1530)
        at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1530)
        at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1530)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99)
        at [email protected]//io.undertow.server.Connectors.executeRootHandler(Connectors.java:387)
        at [email protected]//io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:841)
        at [email protected]//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at [email protected]//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
        at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
        at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
        at [email protected]//org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280)
        at java.base/java.lang.Thread.run(Thread.java:829)

18:36:17,416 WARN  [org.keycloak.events] (default task-26) type=LOGIN_ERROR, realmId=Company, clientId=kiali-dev-server, userId=null, ipAddress=10.47.250.28, error=invalid_user_credentials, auth_method=openid-connect, auth_type=code, response_type=code, redirect_uri=https://lsn-kiali.example.com/kiali, code_id=08413b01-d357-489e-9ddb-dcc6c5dbfd8c, response_mode=query, authSessionParentId=08413b01-d357-489e-9ddb-dcc6c5dbfd8c, authSessionTabId=GpbPyq5G8K

Among events I see the message like the following in administrative interface of KeyCloak:
image

Could you please point me to a misconfiguration if it is somewhere or point the direction that I should pay attention for figuring out the cause of the wrong behavior?

Thank you in advance.

[BUG] Extension not bein executed

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

When using the extension with an oauth provider, we are experiencing the problem, that the extension is not even executed (as it seems) when authenticating against the oauth provider.
When trying to login with an existing keycloak session, the extension is called and does exactly what it is supposed to do, we verfied that through putting users in and out of groups.
When using a keycloak local user, the extensions also works as expected. But it does not with the oauth provider, it just seems to bypass the extension and goes to the application.
So far we only implemented it in the Browser Flow.

Expected Behavior

I expect that the extension blocks (or allows) access to a client based on roles or policies also when using an oauth identity provider.

Steps To Reproduce

Implement the Browser Flow as documented
Toplevel -> Login (Required)
below the toplevel in login: -> Session, Identity Provider, Username Form (with the nested form itself) all as "Alternative)
In parallel the Restricted access extension. (Required)
Use an oauth identity provider in the respective step and the login will always be granted.

Version

- Keycloak:23.0.6
- This extension:23.0.0

Anything else?

We can see that the restriction step in the Browser Flow is create in parallel to the "Login" steps instead of after them in the visual representation. But we do not know whether the representation is actuall how it is executed (in the session step it seems to work)

[BUG] restrict is by passed if user connects with token

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

  • A client is configured to use this flow :

image

  • A user receives an email with a link including an action-token (for example : email validation, reset credentials ...).
  • The user follows the link, he's identified, optionaly confirm his email/set password, and he's logged in.

In case user use the classic form, the restriction works and he get the normal message that he's not allowed to access it.

Expected Behavior

He should not be allowed to logged in.

Steps To Reproduce

No response

Version

- Keycloak: 16.0.0
- This extension: 16.0.0

Anything else?

I'm not an expert on Keycloak so maybe I missed something ... My first idea is that using action token uses another flow but I can't identifie it (and "events" doesn't sho which flow has been used).

Regards

Does not work in Keycloak 19.0.3

Opening the settings window when editing authentication flow throws an error. Downgraded to 19.0.0 where everything works fine.

[Feature] Support a Docker-based release

Is there an existing feature request for this?

  • I have searched the existing issues

Is your feature related to a problem? Please describe.

No response

Describe the solution you'd like

There are deployment scenarios where obtaining the keycloak-restrict-client-auth JAR from a Docker image is preferable to other means. In particular, when running Keycloak in a Kubernetes environment, an initContainer sidecar may be used to pull this JAR into a shared providers directory, thus allowing for runtime modification of the Keycloak Pod's providers.

This removes the need for an end user to modify/support their own Keycloak container images.

Describe alternatives you've considered

Alternatives may include using an initContainer to pull the released JAR at runtime. This adds additional possible failure modes (ie. network unavailability).

Users may also support their own custom Keycloak images, but this comes with a significant support overhead.

Anything else?

No response

[BUG] Access provider list is empty

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

I installed the extension on a new keycloak docker instance from jboss/keycloak

When i try to configure the extension i can not select an „Access Provider“ as the field shows no entries.

Expected Behavior

The Access Provider list should display the correct options

Steps To Reproduce

  1. Add the extension to a fresh keycloak instance
  2. Edit the extension
  3. The Access Provider field is empty

Version

- Keycloak: 15.0.2
- This extension: 15.1.0

Anything else?

No response

[Documentation] Update images in docs

Is there an existing feature request for this?

  • I have searched the existing issues

Is your feature related to a problem? Please describe.

Screenshots in the docs are from the old admin console. Should be updated with screenshots from the new admin console.

Describe the solution you'd like

No response

Describe alternatives you've considered

No response

Anything else?

No response

Multiple apps SAML and 18.0.2

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

So I got around to trying this today. It doesn't appear to work with SAML authentication on version 18.0.2, or more likely I am not doing something correctly.

After adding the provider, restarting KC, I created a copy of the browser flow, edited it as per instructions. I then created the role in a client, and changed the "Authentication Flow Overrides" to the newly created flow which has the restrict feature enabled. when I try to login from an app using SAML, it redirects to KC and immediately presents me with "Invalid username or password" without prompting for either.

Expected Behavior

No response

Steps To Reproduce

No response

Version

- Keycloak:
- This extension:

Anything else?

No response

Issue with Browser flow

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

I have created the following form but when I always get Invalid username or password. Can someone tell me what I am doing wrong?

Expected Behavior

I should get a login form to enter my username and password

Steps To Reproduce

No response

Version

Keycloak 24.0.0

Anything else?

Screenshot 2024-03-05 at 09 41 53

[BUG] Error before authentication - invalid username password

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

I followed the instructions to set up the plugin. I'm using the Jar for 20.0.1 in my keycloak (20.0.2). I'm not using the restricted-access role yet. When I initiate a login process I directly get an invalid credentials' error.

The flow is:

image

The error:

image

The trace is:

2023-03-02 16:51:30,573 WARN [org.keycloak.services] (executor-thread-83) KC-SERVICES0013: Failed authentication: org.keycloak.authentication.AuthenticationFlowException: authenticator: restrict-client-auth-authenticator
at org.keycloak.authentication.DefaultAuthenticationFlow.processSingleFlowExecutionModel(DefaultAuthenticationFlow.java:423)
at org.keycloak.authentication.DefaultAuthenticationFlow.processFlow(DefaultAuthenticationFlow.java:250)
at org.keycloak.authentication.AuthenticationProcessor.authenticateOnly(AuthenticationProcessor.java:1017)
at org.keycloak.authentication.AuthenticationProcessor.authenticate(AuthenticationProcessor.java:879)
at org.keycloak.protocol.AuthorizationEndpointBase.handleBrowserAuthenticationRequest(AuthorizationEndpointBase.java:151)
at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildAuthorizationCodeAuthorizationResponse(AuthorizationEndpoint.java:338)
at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.process(AuthorizationEndpoint.java:194)
at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildGet(AuthorizationEndpoint.java:112)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:152)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:183)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:141)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:32)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:82)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:42)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:84)
at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:71)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:430)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:408)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$0(QuarkusRequestFilter.java:82)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:564)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:1589)

Expected Behavior

The expected behavior is to allow the login because i'm not using the restricted role yet.

Steps To Reproduce

I followed the instructions given.

Version

- Keycloak:20.0.2
- This extension: 20.0.1

Anything else?

No response

No error access-denied will be show in the result browser windows

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

I setup a simple test case following the documentation with Keycloak v21.0.2. Everything seems to work fine playing with the policies, but when the configured policies deny access no access-denied error message is shown in the resulting browser page instead an error of "An internal server error has occurred" is shown. Follow the error stacktrace on the Keycloak logs...

2023-04-05 16:53:34,964 WARN [de.sventorben.keycloak.authorization.client.access.policy.PolicyBasedAccessProvider] (executor-thread-48) Access for user 'duck' is denied. User does not have permission to access resource 'Keycloak Client Resource' on client 'f90a0346-a98b-4fdd-a290-90e5ee520352' in realm 'bemsi'. 2023-04-05 16:53:34,965 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-48) Uncaught server error: java.lang.NoSuchMethodError: 'org.keycloak.http.HttpRequest org.keycloak.authentication.AuthenticationFlowContext.getHttpRequest()' at de.sventorben.keycloak.authorization.client.RestrictClientAuthAuthenticator.errorResponse(RestrictClientAuthAuthenticator.java:87) at de.sventorben.keycloak.authorization.client.RestrictClientAuthAuthenticator.authenticate(RestrictClientAuthAuthenticator.java:50) at org.keycloak.authentication.DefaultAuthenticationFlow.processSingleFlowExecutionModel(DefaultAuthenticationFlow.java:446) at org.keycloak.authentication.DefaultAuthenticationFlow.processFlow(DefaultAuthenticationFlow.java:250) at org.keycloak.authentication.DefaultAuthenticationFlow.processSingleFlowExecutionModel(DefaultAuthenticationFlow.java:381) at org.keycloak.authentication.DefaultAuthenticationFlow.continueAuthenticationAfterSuccessfulAction(DefaultAuthenticationFlow.java:182) at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:158) at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:977) at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:311) at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:282) at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:274) at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:339) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170) at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130) at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660) at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524) at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474) at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364) at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476) at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434) at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192) at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:141) at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:32) at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492) at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261) at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161) at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364) at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164) at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247) at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73) at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151) at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:82) at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:42) at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284) at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173) at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140) at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:84) at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:71) at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284) at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173) at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140) at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:430) at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:408) at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284) at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173) at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140) at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$0(QuarkusRequestFilter.java:82) at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576) at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478) at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29) at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:833)

Expected Behavior

Default access denied error message.

Steps To Reproduce

No response

Version

No response

Anything else?

No response

Keycloak.X Support

Keycloak 16 will be the last preview of Keycloak.X and will become fully supported with Keycloak 17 by end of 2021.
https://www.keycloak.org/2021/10/keycloak-x-update

Make sure the library works with Keycloak.X

Implementation tasks:

  • Check support with testcontainers dasniko/testcontainers-keycloak#10 (or write an extension and contribute)
  • Extend compatibility matrix tests
  • Adjust docs for role-name config on X
  • Adjust docs for installation on X
  • Adjust docs for role vs policy mode config on.
  • Switch docker-compose to X

Cleanup tasks:

  • Use official release of keycloak-testcontainers for Keycloak.X once released
  • Remove allowTimestampedSnapshots (revert commit 5b27120)
  • Remove Jitpack Repository when testcontainers-keycloak 2.0 is on maven central
  • Deprecate support for legacy/Wildfly-based Keycloak

[Feature] Add SPI and provider configuration options

Is there an existing feature request for this?

  • I have searched the existing issues

Is your feature related to a problem? Please describe.

No response

Describe the solution you'd like

Add SPI and provider configuration options once ProviderFactory supports it.

For details see: https://github.com/keycloak/keycloak-community/blob/master/design/keycloak.x/configuration.md#spi-and-provider-configuration-options

Describe alternatives you've considered

No response

Anything else?

No response

[BUG] Unknown flow provider type

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

I get an KC-SERVICES0013: Failed authentication: org.keycloak.authentication.AuthenticationFlowException: Unknown flow provider type message in the logs (see below for complete stack trace), when trying to use the extension in KC24 (with proper extension version 24).

It's not a migrated flow, it's a newly created flow in the realm (see below for a picture of the flow). The flow is designed as mentioned in the README. Additionally, the same flow design works in KC23 with extension version 23.

In the UI I directly get an invalid username or password error message, I even can't start authentication properly (cant't entering anything like username/password).

Expected Behavior

No response

Steps To Reproduce

No response

Version

- Keycloak: 24.0.1
- This extension: 24.0.0

Anything else?

Configured auth-flow:

Bildschirmfoto 2024-03-12 um 15 45 28

Complete StackTrace

kcd_kc        | 2024-03-12 14:45:09,355 WARN  [org.keycloak.services] (executor-thread-15) KC-SERVICES0013: Failed authentication: org.keycloak.authentication.AuthenticationFlowException: Unknown flow provider type
kcd_kc        | 	at org.keycloak.authentication.AuthenticationProcessor.createFlowExecution(AuthenticationProcessor.java:879)
kcd_kc        | 	at org.keycloak.authentication.AuthenticationProcessor.authenticateOnly(AuthenticationProcessor.java:1026)
kcd_kc        | 	at org.keycloak.authentication.AuthenticationProcessor.authenticate(AuthenticationProcessor.java:884)
kcd_kc        | 	at org.keycloak.protocol.AuthorizationEndpointBase.handleBrowserAuthenticationRequest(AuthorizationEndpointBase.java:152)
kcd_kc        | 	at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildAuthorizationCodeAuthorizationResponse(AuthorizationEndpoint.java:337)
kcd_kc        | 	at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.process(AuthorizationEndpoint.java:202)
kcd_kc        | 	at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildGet(AuthorizationEndpoint.java:113)
kcd_kc        | 	at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint$quarkusrestinvoker$buildGet_4b690b27439f19dd29733dc5fd4004f24de0adb6.invoke(Unknown Source)
kcd_kc        | 	at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
kcd_kc        | 	at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
kcd_kc        | 	at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
kcd_kc        | 	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
kcd_kc        | 	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
kcd_kc        | 	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
kcd_kc        | 	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
kcd_kc        | 	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
kcd_kc        | 	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
kcd_kc        | 	at java.base/java.lang.Thread.run(Thread.java:840)

[BUG] Getting "Invalid Username or Password" as soon as visiting a client with the restricted-access step in the flow.

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

When visiting any client I receive an error message upon the page loading that states "Invalid Username or Password".

It doesn't even ask a username or password or try to authenticate, I just immediately experience the above on all clients after binding.

I tested:

  • Having added the restricted-access role to the client and users.
  • Without the restricted-access role on any clients.
  • With the restricted-access on all clients and all users.
  • Without the existence of the restricted-access role at all, and not configured on any client.

As soon as I remove the "Restrict user authentication on clients" step from the flow, it works.

This is my current flow (cloned from the default flow, and tested before/after adding the restrict step):
image

This is the configuration of the step:
image

The error message in action:
image

Expected Behavior

I expect to see the normal authentication dialog before getting access granted/access denied based on the authenticator and associated roles been given to users and clients per the readme instructions.

Steps To Reproduce

  1. My docker config is as follows (sensitive details (such as networks and DB info) omitted, external port and host censored):
  keycloak:
    image: quay.io/keycloak/keycloak:latest
    container_name: keycloak
    restart: unless-stopped
    command:
      - 'start'
      - '--hostname=x
      - '--proxy=edge'
    ports:
      - x:8080    
    volumes:
      - ./keycloak-restrict-client-auth.jar:/opt/keycloak/providers/keycloak-restrict-client-auth.jar
    labels:
      - 'traefik.http.routers.keycloak.entrypoints=websecure'
      - 'traefik.http.routers.keycloak.rule=Host(`x`)'
      - 'traefik.http.routers.keycloak.tls=true'
      - 'traefik.http.routers.keycloak.tls.certresolver=myresolver'
      - 'traefik.http.services.keycloak.loadbalancer.server.scheme=http'
      - 'traefik.http.services.keycloak.loadbalancer.server.port=8080'
      - 'traefik.enable=true
  1. I copied the default Browser flow.
  2. Added the 'Restrict user authentication on clients' step.
  3. Configured it as Required and for 'client-role'.
  4. Bound it as my Browser flow.
  5. I did test configuring the restricted-access role on users and clients, but the problem starts from step 5 and continues no matter what I do unless I remove the authenticator from the flow.

Version

- Keycloak: 19.0.1 (quarkus)
- This extension: 19.0.0 (Latest Release)

Anything else?

No response

[Feature] Keycloak Flow settings

Is there an existing feature request for this?

  • I have searched the existing issues

Is your feature related to a problem? Please describe.

The description of the Keycloak Flow settings in the documentation is not entirely clear.

Describe the solution you'd like

More detailed explanation of Flow settings.

Describe alternatives you've considered

Default Keycloak Browser Flow contains mixed required and alternative subflows/steps/authenticators, that, as described in documentation, can't be used in conjunction with keycloak-restrict-client-auth. Built-in Browser Flow contains Cookie, IdP and Forms alternatives on top. And you can't just add a keycloak-restrict-client-auth to the bottom of the list and set it as Required.
The solution is not just to create a copy of the built-in Bowser Flow, but to completely rebuild your own flow based on the Browser Flow. You need to create three sub-flows for Cookie, IdP and Forms and add keycloak-restrict-client-auth to each of this subflows.
JItHiHAKas

Anything else?

No response

[BUG] SSO allows bypassing the client restriction

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

When multiple clients exist, an active keycloak session created by logging in to one client bypasses restrictions set on another client and allows a user to log in

I tried with the "Role-based mode"

If we go to client that has restrictions first it works as expected and user is stopped at keycloak page

Expected Behavior

I expect that when I logged in to one client and keycloak session is active, when I go to another client that has restricted-access I would NOT be allowed to access

Steps To Reproduce

  1. Create 2 clients, client1 that has restrictions and client2 that doesn't
  2. Set restrictions such that user1 cannot log in to client1 because they don't have the restricted-access role for client1
  3. Log in to client2 with user1 - this works fine because there were no restrictions
  4. Go to client1 and keycloak will log you in bypassing the restrictions set by this plugin

Version

- Keycloak: 15.0.2 (wildfly)
- This extension: 15.1.0

Anything else?

No response

[Access Provider] <keycloak-clustered>

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

In a cluster of two nodes does not give a choice access provider (client-role or policy)

Expected Behavior

choice access provider (client-role or policy)

Steps To Reproduce

No response

Version

- Keycloak:15.1.1
- This extension:15.2

Anything else?

No response

How to make multiple groups and multiple clients restricted-access name

Hello
how can I make restricted-access multiple clients?
I saw the #92

but where to put the role
the client or authentication?

I tested 1 client 1 group
example (Zabbix)
in it has a roles called (restricted-access) and in
Groups (group role mappings) (client role) selected (restricted-access) for the Zabbix client
it's working but how to rename each client have different names like
(zabbix01.restricted-access)
(kibana03.restricted-access)

Zabbix01
(roles)=(zabbix01.restricted-access)
and in
(group role mappings)->(client role) selected (zabbix01.restricted-access) for the (Zabbix01 client)
Screenshot_36
Screenshot_35

[BUG] NullpointerException when authenticator is not configured

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

When the authenticator has not been configured (e.g. access provider is left empty or no authenticator config is present), RestrictClientAuthAuthenticator throws a NullPointerException:

{
  "refId": 1,
  "exceptionType": "java.lang.NullPointerException",
  "message": null,
  "frames": [
    {
      "class": "de.sventorben.keycloak.authorization.client.RestrictClientAuthAuthenticator",
      "method": "getAccessProvider",
      "line": 66
    },
    {
      "class": "de.sventorben.keycloak.authorization.client.RestrictClientAuthAuthenticator",
      "method": "authenticate",
      "line": 34
    },
    {
      "class": "org.keycloak.authentication.DefaultAuthenticationFlow",
      "method": "processSingleFlowExecutionModel",
      "line": 446
    },
    {
      "class": "org.keycloak.authentication.DefaultAuthenticationFlow",
      "method": "processFlow",
      "line": 253
    },
    {
      "class": "org.keycloak.authentication.DefaultAuthenticationFlow",
      "method": "processSingleFlowExecutionModel",
      "line": 389
    },
    {
      "class": "org.keycloak.authentication.DefaultAuthenticationFlow",
      "method": "processFlow",
      "line": 253
    },
    {
      "class": "org.keycloak.authentication.DefaultAuthenticationFlow",
      "method": "continueAuthenticationAfterSuccessfulAction",
      "line": 184
    },
    {
      "class": "org.keycloak.authentication.DefaultAuthenticationFlow",
      "method": "processAction",
      "line": 164
    },
    {
      "class": "org.keycloak.authentication.AuthenticationProcessor",
      "method": "authenticationAction",
      "line": 950
    },
    {
      "class": "org.keycloak.services.resources.LoginActionsService",
      "method": "processFlow",
      "line": 312
    },
    {
      "class": "org.keycloak.services.resources.LoginActionsService",
      "method": "processAuthentication",
      "line": 283
    },
    {
      "class": "org.keycloak.services.resources.LoginActionsService",
      "method": "authenticate",
      "line": 267
    },
    {
      "class": "org.keycloak.services.resources.LoginActionsService",
      "method": "authenticateForm",
      "line": 340
    },
    {
      "class": "jdk.internal.reflect.NativeMethodAccessorImpl",
      "method": "invoke0"
    },
    {
      "class": "jdk.internal.reflect.NativeMethodAccessorImpl",
      "method": "invoke",
      "line": 62
    },
    {
      "class": "jdk.internal.reflect.DelegatingMethodAccessorImpl",
      "method": "invoke",
      "line": 43
    },
    {
      "class": "java.lang.reflect.Method",
      "method": "invoke",
      "line": 566
    },
    {
      "class": "org.jboss.resteasy.core.MethodInjectorImpl",
      "method": "invoke",
      "line": 138
    },
    {
      "class": "org.jboss.resteasy.core.ResourceMethodInvoker",
      "method": "internalInvokeOnTarget",
      "line": 546
    },
    {
      "class": "org.jboss.resteasy.core.ResourceMethodInvoker",
      "method": "invokeOnTargetAfterFilter",
      "line": 435
    },
    {
      "class": "org.jboss.resteasy.core.ResourceMethodInvoker",
      "method": "lambda$invokeOnTarget$0",
      "line": 396
    },
    {
      "class": "org.jboss.resteasy.core.interception.PreMatchContainerRequestContext",
      "method": "filter",
      "line": 358
    },
    {
      "class": "org.jboss.resteasy.core.ResourceMethodInvoker",
      "method": "invokeOnTarget",
      "line": 398
    },
    {
      "class": "org.jboss.resteasy.core.ResourceMethodInvoker",
      "method": "invoke",
      "line": 365
    },
    {
      "class": "org.jboss.resteasy.core.ResourceLocatorInvoker",
      "method": "invokeOnTargetObject",
      "line": 150
    },
    {
      "class": "org.jboss.resteasy.core.ResourceLocatorInvoker",
      "method": "invoke",
      "line": 104
    },
    {
      "class": "org.jboss.resteasy.core.SynchronousDispatcher",
      "method": "invoke",
      "line": 440
    },
    {
      "class": "org.jboss.resteasy.core.SynchronousDispatcher",
      "method": "lambda$invoke$4",
      "line": 229
    },
    {
      "class": "org.jboss.resteasy.core.SynchronousDispatcher",
      "method": "lambda$preprocess$0",
      "line": 135
    },
    {
      "class": "org.jboss.resteasy.core.interception.PreMatchContainerRequestContext",
      "method": "filter",
      "line": 358
    },
    {
      "class": "org.jboss.resteasy.core.SynchronousDispatcher",
      "method": "preprocess",
      "line": 138
    },
    {
      "class": "org.jboss.resteasy.core.SynchronousDispatcher",
      "method": "invoke",
      "line": 215
    },
    {
      "class": "org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher",
      "method": "service",
      "line": 245
    },
    {
      "class": "org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher",
      "method": "service",
      "line": 61
    },
    {
      "class": "org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher",
      "method": "service",
      "line": 56
    },
    {
      "class": "javax.servlet.http.HttpServlet",
      "method": "service",
      "line": 590
    },
    {
      "class": "io.undertow.servlet.handlers.ServletHandler",
      "method": "handleRequest",
      "line": 74
    },
    {
      "class": "io.undertow.servlet.handlers.FilterHandler$FilterChainImpl",
      "method": "doFilter",
      "line": 129
    },
    {
      "class": "org.keycloak.provider.wildfly.WildFlyRequestFilter",
      "method": "lambda$doFilter$0",
      "line": 41
    },
    {
      "class": "org.keycloak.services.filters.AbstractRequestFilter",
      "method": "filter",
      "line": 43
    },
    {
      "class": "org.keycloak.provider.wildfly.WildFlyRequestFilter",
      "method": "doFilter",
      "line": 39
    },
    {
      "class": "io.undertow.servlet.core.ManagedFilter",
      "method": "doFilter",
      "line": 61
    },
    {
      "class": "io.undertow.servlet.handlers.FilterHandler$FilterChainImpl",
      "method": "doFilter",
      "line": 131
    },
    {
      "class": "io.undertow.servlet.handlers.FilterHandler",
      "method": "handleRequest",
      "line": 84
    },
    {
      "class": "io.undertow.servlet.handlers.security.ServletSecurityRoleHandler",
      "method": "handleRequest",
      "line": 62
    },
    {
      "class": "io.undertow.servlet.handlers.ServletChain$1",
      "method": "handleRequest",
      "line": 68
    },
    {
      "class": "io.undertow.servlet.handlers.ServletDispatchingHandler",
      "method": "handleRequest",
      "line": 36
    },
    {
      "class": "org.wildfly.extension.undertow.security.SecurityContextAssociationHandler",
      "method": "handleRequest",
      "line": 78
    },
    {
      "class": "io.undertow.server.handlers.PredicateHandler",
      "method": "handleRequest",
      "line": 43
    },
    {
      "class": "io.undertow.servlet.handlers.RedirectDirHandler",
      "method": "handleRequest",
      "line": 68
    },
    {
      "class": "io.undertow.servlet.handlers.security.SSLInformationAssociationHandler",
      "method": "handleRequest",
      "line": 117
    },
    {
      "class": "io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler",
      "method": "handleRequest",
      "line": 57
    },
    {
      "class": "io.undertow.server.handlers.PredicateHandler",
      "method": "handleRequest",
      "line": 43
    },
    {
      "class": "io.undertow.security.handlers.AbstractConfidentialityHandler",
      "method": "handleRequest",
      "line": 46
    },
    {
      "class": "io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler",
      "method": "handleRequest",
      "line": 64
    },
    {
      "class": "io.undertow.security.handlers.AuthenticationMechanismsHandler",
      "method": "handleRequest",
      "line": 60
    },
    {
      "class": "io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler",
      "method": "handleRequest",
      "line": 77
    },
    {
      "class": "io.undertow.security.handlers.NotificationReceiverHandler",
      "method": "handleRequest",
      "line": 50
    },
    {
      "class": "io.undertow.security.handlers.AbstractSecurityContextAssociationHandler",
      "method": "handleRequest",
      "line": 43
    },
    {
      "class": "io.undertow.server.handlers.PredicateHandler",
      "method": "handleRequest",
      "line": 43
    },
    {
      "class": "org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler",
      "method": "handleRequest",
      "line": 61
    },
    {
      "class": "io.undertow.server.handlers.PredicateHandler",
      "method": "handleRequest",
      "line": 43
    },
    {
      "class": "org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler",
      "method": "handleRequest",
      "line": 68
    },
    {
      "class": "io.undertow.servlet.handlers.SendErrorPageHandler",
      "method": "handleRequest",
      "line": 52
    },
    {
      "class": "io.undertow.server.handlers.PredicateHandler",
      "method": "handleRequest",
      "line": 43
    },
    {
      "class": "io.undertow.servlet.handlers.ServletInitialHandler",
      "method": "handleFirstRequest",
      "line": 269
    },
    {
      "class": "io.undertow.servlet.handlers.ServletInitialHandler",
      "method": "access$100",
      "line": 78
    },
    {
      "class": "io.undertow.servlet.handlers.ServletInitialHandler$2",
      "method": "call",
      "line": 133
    },
    {
      "class": "io.undertow.servlet.handlers.ServletInitialHandler$2",
      "method": "call",
      "line": 130
    },
    {
      "class": "io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1",
      "method": "call",
      "line": 48
    },
    {
      "class": "io.undertow.servlet.core.ContextClassLoaderSetupAction$1",
      "method": "call",
      "line": 43
    },
    {
      "class": "org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction",
      "method": "lambda$create$0",
      "line": 105
    },
    {
      "class": "org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction",
      "method": "lambda$create$0",
      "line": 1530
    },
    {
      "class": "org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction",
      "method": "lambda$create$0",
      "line": 1530
    },
    {
      "class": "org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction",
      "method": "lambda$create$0",
      "line": 1530
    },
    {
      "class": "org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction",
      "method": "lambda$create$0",
      "line": 1530
    },
    {
      "class": "io.undertow.servlet.handlers.ServletInitialHandler",
      "method": "dispatchRequest",
      "line": 249
    },
    {
      "class": "io.undertow.servlet.handlers.ServletInitialHandler",
      "method": "access$000",
      "line": 78
    },
    {
      "class": "io.undertow.servlet.handlers.ServletInitialHandler$1",
      "method": "handleRequest",
      "line": 99
    },
    {
      "class": "io.undertow.server.Connectors",
      "method": "executeRootHandler",
      "line": 387
    },
    {
      "class": "io.undertow.server.HttpServerExchange$1",
      "method": "run",
      "line": 841
    },
    {
      "class": "org.jboss.threads.ContextClassLoaderSavingRunnable",
      "method": "run",
      "line": 35
    },
    {
      "class": "org.jboss.threads.EnhancedQueueExecutor",
      "method": "safeRun",
      "line": 1990
    },
    {
      "class": "org.jboss.threads.EnhancedQueueExecutor$ThreadBody",
      "method": "doRunTask",
      "line": 1486
    },
    {
      "class": "org.jboss.threads.EnhancedQueueExecutor$ThreadBody",
      "method": "run",
      "line": 1377
    },
    {
      "class": "org.xnio.XnioWorker$WorkerThreadFactory$1$1",
      "method": "run",
      "line": 1280
    },
    {
      "class": "java.lang.Thread",
      "method": "run",
      "line": 829
    }
  ]
}

Expected Behavior

Should not throw a NullPointerException but use the default authenticator and access provider client-role instead.

Steps To Reproduce

  1. Add the authenticator to a flow
  2. do not configure anything
  3. try to authenticate via the given flow

Version

- Keycloak: 15.1.1
- This extension: 15.2.0, 16.0.0

Anything else?

No response

[Enhancement] Update screenshots in README

Is there an existing feature request for this?

  • I have searched the existing issues

Is your feature related to a problem? Please describe.

With Keycloak 19 the new admin console became the default and the old one got deprecated.

Describe the solution you'd like

Update all screenshots in the README to reflect changes in the new admin console.

Describe alternatives you've considered

No response

Anything else?

No response

Client Restriction Fails with Internal Server Error

I just updated Keycloak to version 22.0.1 and tested your provider with release v22.0.0.

The plugin still works but the error message in the frontend is just a "We are sorry - An internal server error has occurred".

This is the stack trace from the Keycloak error log:

| 2023-08-01 14:11:31,022 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-2) Uncaught server error: java.lang.NoSuchMethodError: 'org.jboss.resteasy.spi.HttpRequest org.keycloak.authentication.AuthenticationFlowContext.getHttpRequest()'
| 	at de.sventorben.keycloak.authorization.client.RestrictClientAuthAuthenticator.errorResponse(RestrictClientAuthAuthenticator.java:87)
| 	at de.sventorben.keycloak.authorization.client.RestrictClientAuthAuthenticator.authenticate(RestrictClientAuthAuthenticator.java:50)

which points to this line in your code:

if (MediaTypeMatcher.isHtmlRequest(context.getHttpRequest().getHttpHeaders())) {

how to add jar to Redhat single sign-on 7.6

Hello
I have installed redhat single sign-on 7.6 base on keycloak 18.0.0
i cant find the directory:

/opt/jboss/keycloak/providers

when i added the jar file in:

/opt/eap/standalone/deployments/

it added but empty (access provider)
can you help me?
so i can select (access provider) in action>config
Screenshot_20
Screenshot_21

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.