[keycloak-user] Restrict access to a client to a subset of Keycloak users

Shane Boulden shane.boulden at gmail.com
Fri Feb 24 16:47:32 EST 2017


Awesome, thanks Thomas!

Do you have any suggestions on my 'ClassNotFoundException' for org.keycloak.
representations.idm.OAuth2ErrorRepresentation? This is on 2.5.1.

Oauth2 = Java.type("org.keycloak.representations.idm.
OAuth2ErrorRepresentation");

Shane

On Sat, Feb 25, 2017 at 12:23 AM, Thomas Darimont <
thomas.darimont at googlemail.com> wrote:

> PR sent: https://issues.jboss.org/browse/KEYCLOAK-4505
>
> With that PR applied I can do the following:
>
> /*
>  * Template for JavaScript based authenticator's.
>  * See org.keycloak.authentication.authenticators.browser.
> ScriptBasedAuthenticatorFactory
>  */
>
> // import enum for error lookup
> AuthenticationFlowError = Java.type("org.keycloak.authentication.
> AuthenticationFlowError");
> OAuth2ErrorRepresentation = Java.type("org.keycloak.representations.idm.
> OAuth2ErrorRepresentation");
> Response = Java.type("javax.ws.rs.core.Response");
> MediaType = Java.type("javax.ws.rs.core.MediaType");
>
> /**
>  * An example authenticate function.
>  *
>  * The following variables are available for convenience:
>  * user - current user {@see org.keycloak.models.UserModel}
>  * realm - current realm {@see org.keycloak.models.RealmModel}
>  * session - current KeycloakSession {@see org.keycloak.models.
> KeycloakSession}
>  * clientSession - current client session {@see org.keycloak.models.
> ClientSessionModel}
>  * httpRequest - current HttpRequest {@see org.jboss.resteasy.spi.
> HttpRequest}
>  * script - current script {@see org.keycloak.models.ScriptModel}
>  * LOG - current logger {@see org.jboss.logging.Logger}
>   * You one can extract current http request headers via:
>  * httpRequest.getHttpHeaders().getHeaderString("Forwarded")
>  *
>  * @param context {@see org.keycloak.authentication.
> AuthenticationFlowContext}
>  */
> function authenticate(context) {
>
>     var username = user ? user.username : "anonymous";
>     LOG.info(script.name + " trace auth for: " + username);
>     LOG.info(script.name + " client session for client: " +
> clientSession.client.clientId);
>
>     var groups = user.getGroups();
>     var group_array = groups.toArray();
>
>     var authShouldFail = true;
>     for (var i in group_array) {
>       var gn = group_array[i].getName();
>       LOG.info(script.name + " group name: " + gn);
>       if (gn === "account-access") {
>         authShouldFail = false;
>         break;
>       }
>     }
>
>     if (authShouldFail
>      //&& clientSession.client.clientId === "dummy-account"
>      ) {
>
>         var errorRep = new OAuth2ErrorRepresentation("
> invalid_grant","invalid_user_credentials");
>         var response = Response.status(401).entity(
> errorRep).type(MediaType.APPLICATION_JSON_TYPE).build();
>
>         LOG.info(script.name + " failed auth for: " + username);
>         context.failure(AuthenticationFlowError.INVALID_USER, response);
>         return;
>     }
>
>     context.success();
> }
>
>
>
> 2017-02-24 12:19 GMT+01:00 Thomas Darimont <thomas.darimont at googlemail.com
> >:
>
>> FYI I just gave this a spin...
>>
>> It seems that the ScriptAuthenticator currently has no binding for
>> clientSession in order to access the client id for authentication,
>> e.g. this is missing in ScriptBasedAuthenticator
>>             bindings.put("clientSession", context.getClientSession());
>>
>> I'll send a PR which adds that binding. This will then enable to provide
>> client specific authentication behaviour.
>>
>> Chreers,
>> Thomas
>>
>> 2017-02-24 11:33 GMT+01:00 Shane Boulden <shane.boulden at gmail.com>:
>>
>>> I got this working today with a custom auth flow, thanks heaps!
>>>
>>> Just one thing - I've copied the 'Direct Grant Flow', and added a JS
>>> script at the end to only allow certain groups to authenticate using the
>>> OpenShift 'oc login' command from a prompt.
>>>
>>> This works allowing/denying access based on a group, however when a user
>>> does not belong to the correct group, the oc login prompt displays the
>>> following error:
>>>
>>> "Error from server: Internal error: unexpected error: 500"
>>>
>>> Here's the code I used for my JS script:
>>>
>>> function authenticate(context){
>>>   var groups = user.getGroups();
>>>   var group_array = groups.toArray();
>>>
>>>   for (var i in group_array) {
>>>     var gn = group_array[i].getName();
>>>
>>>     if (gn === "openshift-access") {
>>>       context.success();
>>>       return;
>>>     }
>>>   }
>>>   context.failure(authenticationflowerror.INVALID_USER)
>>>   return;
>>> }
>>>
>>> I thought this may be because the OpenShift CLI tool can't interpret the
>>> error message back from Keycloak. I've also tried the following, but I get
>>> a "ClassNotFound" exception when I try to import the OAuth2 error
>>> representation:
>>>
>>> Authenticationflowerror = Java.type("org.keycloak.authen
>>> tication.AuthenticationFlowError");
>>> // Throws 'ClassNotFoundException
>>> Oauth2 = Java.type("org.keycloak.representations.idm.OAuth2ErrorRepre
>>> sentation");
>>> Response = Java.type("javax.ws.rs.core.Response");
>>> MediaType = Java.Type("javax.ws.rs.core.MediaType");
>>>
>>> function authenticate(context) {
>>>   var groups = user.getGroups();
>>>   var group_array = groups.toArray();
>>>
>>>   for (var i in group_array) {
>>>     var gn = group_array[i].getName();
>>>
>>>     if (gn === "openshift-access") {
>>>       context.success();
>>>       return;
>>>     }
>>>   }
>>>   var errorRep = new Oauth2("invalid_grant","invalid_user_credentials");
>>>   response = Response.status(401).type(Medi
>>> aType.APPLICATION_JSON_TYPE).build();
>>>
>>>   context.failure(AuthenticationFlowError.INVALID_CREDENTIALS,
>>> response);
>>>   return;
>>> }
>>>
>>> Any ideas or assistance is appreciated.
>>>
>>> Shane
>>>
>>> On Fri, Feb 24, 2017 at 5:16 AM, Shane Boulden <shane.boulden at gmail.com>
>>> wrote:
>>>
>>>> Thanks very much Marek and Thomas for taking the time to get back to me.
>>>>
>>>> I've found an example of a JS authenticator here:
>>>>  http://www.lookatsrc.com/source/scripts/authenticator-templ
>>>> ate.js?a=org.keycloak:keycloak-services
>>>>
>>>> Is this how I would build the custom authenticator, and extend it to
>>>> check the user roles and clientID?
>>>>
>>>> Thanks
>>>>
>>>> Shane
>>>>
>>>> On 24 Feb. 2017 01:25, "Thomas Darimont" <thomas.darimont at googlemail.co
>>>> m> wrote:
>>>>
>>>>> Hello Shane,
>>>>>
>>>>> you could try to do that with the Javascript based Authenticator.
>>>>>
>>>>> Cheers,
>>>>> Thomas
>>>>>
>>>>> 2017-02-23 14:07 GMT+01:00 Marek Posolda <mposolda at redhat.com>:
>>>>>
>>>>>> I can think of some workarounds. Like for example, create an
>>>>>> Authenticator, which will be added to the bottom of the authentication
>>>>>> flow. Authenticator will throw an exception in case that unpermitted
>>>>>> user is trying to authenticate to the client corresponding to your
>>>>>> openshift application. You have the user available (he is already
>>>>>> authenticated) and you have also the client (can be determined based
>>>>>> on
>>>>>> clientId).
>>>>>>
>>>>>> Maybe even easier is to do that in custom RequiredActionProvider and
>>>>>> do
>>>>>> this check in "evaluateTriggers".
>>>>>>
>>>>>> This is workaround as it mixes authentication and authorization (among
>>>>>> other issues). But hopefully it can suit your needs.
>>>>>>
>>>>>> Marek
>>>>>>
>>>>>> On 23/02/17 07:19, Shane Boulden wrote:
>>>>>> > Hi everyone,
>>>>>> >
>>>>>> > I'm trying to figure out a fairly straight-forward problem set -
>>>>>> >
>>>>>> >     - I have a number of users in a Keycloak database, federated
>>>>>> from an
>>>>>> >     LDAP provider with a READ_ONLY policy (ie; I can't "disable"
>>>>>> the users)
>>>>>> >     - I want to limit access to a client to only certain Keycloak
>>>>>> users
>>>>>> >
>>>>>> > I thought this would be possible with a role that is shared by the
>>>>>> client
>>>>>> > and the user. However, it looks like Keycloak lets the application
>>>>>> itself
>>>>>> > determine access via a role: http://lists.jboss.org/
>>>>>> > pipermail/keycloak-user/2014-November/001205.html
>>>>>> >
>>>>>> > But what if I can't update the application's behaviour? Eg; if I
>>>>>> want to
>>>>>> > integrate Keycloak with OpenShift, and OpenShift doesn't consume any
>>>>>> > information from the OIDC provider?
>>>>>> >
>>>>>> > In this particular example, I don't want to limit the users in the
>>>>>> Keycloak
>>>>>> > database - I want to sync all users from LDAP, but limit
>>>>>> application access
>>>>>> > to only a subset.
>>>>>> >
>>>>>> > Any assistance is greatly appreciated.
>>>>>> >
>>>>>> > Shane
>>>>>> > _______________________________________________
>>>>>> > keycloak-user mailing list
>>>>>> > keycloak-user at lists.jboss.org
>>>>>> > https://lists.jboss.org/mailman/listinfo/keycloak-user
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> keycloak-user mailing list
>>>>>> keycloak-user at lists.jboss.org
>>>>>> https://lists.jboss.org/mailman/listinfo/keycloak-user
>>>>>>
>>>>>
>>>>>
>>>
>>
>


More information about the keycloak-user mailing list