16
votes

Comment puis-je restreindre l'accès client à un seul groupe d'utilisateurs dans Keycloak?

J'ai un client dans keycloak pour ma page Web awx (ansible tower). Je n'ai besoin que des utilisateurs d'un groupe keycloak spécifique pour pouvoir keycloak connecter via ce client.

Comment puis-je interdire à tous les autres utilisateurs (à l'exception d'un groupe particulier) d'utiliser ce client keycloak ?


3 commentaires

Vous pouvez obtenir de l'aide à partir de ce document, il est clairement indiqué comment réaliser ce keycloak.org/docs/3.3/server_admin/topics/...


Vous avez probablement publié un mauvais lien? Le contrôle d'accès et les autorisations de la console d'administration expliquent uniquement comment les autorisations peuvent être définies en interne pour chaque utilisateur / groupe. Mon problème est de savoir comment autoriser la connexion via ce client uniquement à plusieurs utilisateurs de keycloak


Si vous ne trouvez pas le "script" d'exécution du flux, consultez ce lien: stackoverflow.com/questions/53390134/...


8 Réponses :


11
votes

Sur la console d'administration Keycloak, allez dans le menu Clients, sélectionnez votre client. Sur la page de configuration du client, définissez Autorisation activée: Activé , cliquez sur Enregistrer . Un nouvel onglet Autorisation devrait apparaître, allez-y, puis dans l'onglet Politiques en dessous, cliquez sur Créer une politique et sélectionnez Politique de groupe . Là, vous pouvez restreindre l'accès à des groupes spécifiques , en supposant que vous avez déjà défini vos groupes via le menu Groupes.

--EDIT 2019-11-08--

Comme mentionné dans les commentaires, le protocole client doit être défini sur openid-connect et le type d'accès doit être défini sur confidentiel , afin de rendre visible l'option Autorisation activée .


5 commentaires

Cela fonctionnerait parfaitement avec openid. Mais dans SAML, il n'est pas possible d'activer l'autorisation par un bouton.


En effet :-( Maintenant je suis au courant de cette (grosse) limitation de Keycloak pour SAML. Heureux que vous ayez trouvé une solution de contournement.


Pour les autres qui n'ont pas l '«Autorisation activée», définissez le type d'accès sur «confidentiel», puis il apparaîtra.


J'ai suivi les instructions, mais l'authentification n'est en aucun cas bloquée. Cela ne fonctionne pas pour moi.


Cela ne fonctionnera pas, car l'autorisation dans Keycloak fait référence à l'utilisation de l' API des services d'autorisation . C'est quelque chose que l'application client devrait explicitement prendre en charge et appliquer, Keycloak lui-même n'applique pas les politiques.



3
votes

Je l'ai résolu comme ceci:

  1. Créez un nouveau rôle dans Keycloak.
  2. Attribuez ce rôle au groupe.
  3. Créez un nouveau script d'authentification dans Kycloak. Configurez quel rôle est autorisé lors de la connexion (par exemple, user.hasRole(realm.getRole("yourRoleName")) ).
  4. Dans les paramètres du client, sous "Remplacement du flux d'authentification", choisissez le script d'authentification qui vient d'être créé.

5 commentaires

Comment ajouter le nouveau script d'authentification personnalisé dans la console d'administration?


keycloak-> realm-> authentication-> créer une nouvelle authentification. Une fois que vous l'avez configuré, sous "flux", vous pouvez "ajouter une exécution" puis choisir le script dans la liste.


@lukasell votre navigation est floue, on ne sait pas où cliquer quoi. Pouvez-vous améliorer votre commentaire?


Impossible de suivre les étapes


Ce script se termine toujours par null has no such function "hasRole" , In KeyCloak 10.x et 11.x.



6
votes

Si cela peut aider, voici un script qui aide à implémenter ce comportement pour n'importe quel client: si le client contient un rôle donné (ici, il s'appelle feature:authenticate ), alors le script vérifie si l'utilisateur a le rôle et affiche une page d'erreur (un nouveau modèle qui doit être déployé dans le thème) sinon.

AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError");

 function authenticate(context) {
    var MANDATORY_ROLE = 'feature:authenticate';
    var username = user ? user.username : "anonymous";

    var client = session.getContext().getClient();

    LOG.debug("Checking access to authentication for client '" + client.getName() + "' through mandatory role '" + MANDATORY_ROLE + "' for user '" + username + "'");

    var mandatoryRole = client.getRole(MANDATORY_ROLE);

    if (mandatoryRole === null) {
        LOG.debug("No mandatory role '" + MANDATORY_ROLE + "' for client '" + client.getName() + "'");
        return context.success();
    }

    if (user.hasRole(mandatoryRole)) {
        LOG.info("Successful authentication for user '" + username + "' with mandatory role '" + MANDATORY_ROLE + "' for client '" + client.getName() + "'");
        return context.success();
    }

    LOG.info("Denied authentication for user '" + username + "' without mandatory role '" + MANDATORY_ROLE + "' for client '" + client.getName() + "'");
    return denyAccess(context, mandatoryRole);
 }

 function denyAccess(context, mandatoryRole) {
    var formBuilder = context.form();
    var client = session.getContext().getClient();
    var description = !mandatoryRole.getAttribute('deniedMessage').isEmpty() ? mandatoryRole.getAttribute('deniedMessage') : [''];
    var form = formBuilder
        .setAttribute('clientUrl', client.getRootUrl())
        .setAttribute('clientName', client.getName())
        .setAttribute('description', description[0])
        .createForm('denied-auth.ftl');
    return context.failure(AuthenticationFlowError.INVALID_USER, form);
 }


2 commentaires

Comment mettons-nous en œuvre et utilisons-nous cela? Ce n'est pas clair, même si c'est censé être simple.


Cela fonctionne (détails soumis sur le déploiement); la seule modification de script que j'ai eu à faire: return context.failure(AuthenticationFlowError.CLIENT_DISABLED); au lieu d'utiliser la fonction personnalisée denyAccess (a causé des problèmes avec le thème par défaut).



1
votes

selon docu https://www.keycloak.org/docs/6.0/server_admin/#executions vous devez activer cette fonctionnalité pour ajouter des scripts personnalisés avec "ajouter une exécution".

bin/standalone.sh|bat -Dkeycloak.profile.feature.scripts=enabled

Solution @Allan avec fonctionnalité: authentifier me va bien


2 commentaires

fonctionnalité: l'authentification ne fonctionne pas en cas de session existante dans une autre application. Exemple. Essayez de vous connecter à l'application de compte, puis à votre application.


le téléchargement de script doit également être activé à partir de keycloak 8



1
votes

Vous pouvez utiliser cette extension pour restreindre l'accès à un groupe spécifique: https://github.com/thomasdarimont/keycloak-extension-playground/tree/master/auth-require-group-extension


1 commentaires

ceci et d'autres scripts dans les réponses ne fonctionnent pas sur Keycloak 9, j'obtiens un utilisateur nul même si l'utilisateur est connecté



4
votes

Suivi de la réponse d'Allan: Son approche fonctionne (pour moi ;-)), même si j'ai eu du mal à la déployer. Voici comment je l'ai fait:

  • Regroupez le script dans un fichier JAR comme documenté ici , déployez-le en le copiant sur standalone / deployments / (voir lien manuel)
  • Activer les scripts: Démarrez Keycloak avec -Dkeycloak.profile.feature.scripts=enabled
  • Dans votre royaume, créez un nouveau flux. Dupliquez le flux du navigateur dans un sous-flux requis et ajoutez l'authentificateur de script en tant qu'élément final (obligatoire): Capture d'écran de la configuration de flux
  • Ajoutez maintenant à tous les clients qui devraient être limités une feature:authenticate rôle client feature:authenticate . Les utilisateurs qui ne portent pas ce rôle n'auront pas accès à l'application.

3 commentaires

Bonjour, j'utilise cette méthode mais dans le script, l'utilisateur est nul, savez-vous pourquoi il ne passe pas l'utilisateur même s'il est connecté?


Mon erreur a été de ne pas dupliquer tout le flux du navigateur, mais j'avais les sous-flux sur l'exécution des rôles requis uniquement. Merci quand même!


J'avais l'habitude d'utiliser des authentificateurs javscript pour déployer le script, mais ils sont maintenant obsolètes . Votre approche est la bonne si vous utilisez des versions plus récentes de KC.



1
votes

J'ai trouvé une solution qui ne nécessite pas l'extension de scripts ni aucun changement sur le flux.

La clé de cette solution sont les étendues client. Une application qui veut autoriser un utilisateur a besoin d'une portée comme l'email ou l'uid, non? Que faire si vous ne les transmettez à une application que si un utilisateur appartient à un groupe spécifique?

Dans ce qui suit, le nom de mon application cliente est App1.

Solution:

  1. Accédez à vos rôles client (royaume -> Clients -> cliquez sur App1 -> Rôles)
  2. Cliquez sur «Ajouter un rôle» -> entrez le nom (par exemple, «accès») -> cliquez sur «Enregistrer»
  3. Accédez aux étendues client (royaume -> étendues client)
  4. Cliquez sur le périmètre requis par votre application client (par exemple 'email')
  5. Attribuez le rôle du client «accès» dans l'onglet «Portée» en choisissant l'application cliente «App1» dans la liste déroulante «Rôles du client»

Désormais, vous ne pourrez plus vous connecter à votre application client App1, car le rôle «accès» n'est attribué à aucun utilisateur ou groupe. Tu peux essayer.

Créons un nouveau groupe et attribuons-lui le rôle et un utilisateur.

  1. Créer un groupe (royaume -> Groupes -> Cliquez sur 'Nouveau' -> entrez le nom 'Utilisateurs de l'application1' -> Cliquez sur Enregistrer)
  2. Dans le groupe, choisissez 'Role Mappings', choisissez 'App1' dans la liste déroulante des rôles client et attribuez le rôle 'access'
  3. Attribuer un utilisateur à 'Utilisateurs App1' (royaume -> Utilisateurs -> Cliquez sur Utilisateur -> Groupes -> Sélectionnez 'Utilisateurs App1 -> Cliquez sur Rejoindre)

Voila, l'utilisateur choisi peut se connecter à App1.


0 commentaires

0
votes

J'ai essayé la solution d'Allan et elle fonctionne bien avec Keycloak 11.0.3, mais elle présente certains inconvénients mentionnés ci-dessous. Voici ma solution pour le script d'authentification qui n'accorde pas l'accès aux utilisateurs s'ils ne sont pas membres d'au moins un des groupes donnés. Dans ce cas, un message d'erreur unique s'affiche.

AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError");

 function authenticate(context) {
    var allowed_groups = ['foo', 'bar'];
    var username = user ? user.username : "anonymous";
    var groups = user.getGroups();
    var group_array = groups.toArray();
    
    for (var i in group_array) {
        var gn = group_array[i].getName();
        if (allowed_groups.indexOf(gn) >= 0) {
            LOG.info("Access granted for user '" + username + "' for being member of LDAP group '" + gn + "'");
            return context.success();
        }    
    }

    LOG.info("Access denied for user '" + username + ". for not being member of any of the following LDAP groups: " + allowed_groups);
    context.failure(AuthenticationFlowError.IDENTITY_PROVIDER_DISABLED, context.form().setError(
        "User doesn't have the required LDAP group membership to view this page", null).createForm("error.ftl"));
    return;
 }

Il y a deux inconvénients mineurs liés à l'expérience utilisateur avec cette solution à mentionner:

  • Lorsqu'un utilisateur non connecté tente de se connecter à un client dont l'accès est refusé par le script d'authentification, l'ensemble du flux d'authentification est considéré comme un échec. Cela signifie que l'utilisateur ne se connecte pas à Keycloak malgré le fait qu'il a fourni les informations d'identification correctes
  • Lorsqu'un utilisateur connecté essaie de se connecter à un client dont l'accès est refusé par le script d'authentification, la page de connexion Keycloak s'affiche (sans afficher de message d'erreur), ce qui est trompeur car l'utilisateur peut avoir le faux sentiment qu'il n'est pas connecté

De plus, si vous gérez plusieurs clients et que vous avez besoin de vérifier différents groupes (ou rôles) par client, vous devez implémenter autant de nouveaux flux d'authentification que de contrôles différents dont vous avez besoin. En bref, la solution fonctionne, mais elle présente certains inconvénients. Je crois qu'une fonctionnalité simple telle que restreindre l'accès en fonction de groupes ou de rôles est essentielle pour un système de gestion des identités et des accès et devrait être prise en charge de manière native!


1 commentaires

Il y a un autre inconvénient de cette solution. Vous devez définir le type d'authentification du formulaire sur obligatoire, sinon la variable utilisateur fournit null dans le script. En faisant cela, les utilisateurs sont obligés de s'authentifier à chaque fois (pour chaque client), ce n'est donc plus une solution SSO