[keycloak-user] Restrict access from web app client

Pablo Fernandez pablo.fernandez at cscs.ch
Fri Aug 18 11:32:35 EDT 2017


Dear Pedro,

Answers inline:

On 18/08/17 14:48, Pedro Igor Silva wrote:
> Hi Pablo,
>
> From your first e-mail, you posted the following policy:
>
> ---
> // by default, grants any permission associated with this policy
> //$evaluation.grant();
> var context = $evaluation.getContext();
> var contextAttributes = context.getAttributes();
> if (contextAttributes.containsValue('kc.client.id
> <http://kc.client.id/>', 'simplewebapp')) {
>     $evaluation.deny();
> }
> $evaluation.grant();
> ---
>
> At the end of the script you are granting access, no matter what. You
> should try to change your code to avoid calling $evaluation.grant()
> after calling $evaluation.deny().

I just tried to put the grant() call inside an else (if condition then
deny else grant), but with the same result: the policy always returns
PERMIT (I just discovered the Evaluate tab). In fact, when I see the
authorization data (in the eval tab again) I don't see the kc.client.id
context attributes... but that's maybe a defect of the evaluation?

This is the info I get from the auth data, the only reference to
simplewebapp (client 1) is in resource_access:

{
  "exp": 0,
  "nbf": 0,
  "iat": 0,
  "iss": "https://myidp.domain.country:8443/auth/realms/keystonerealm",
  "aud": "5e91cb22-991c-4874-b8fe-8add2d48b463",
  "sub": "daf782c3-24d7-41fa-8bf1-4ace50b218c9",
  "azp": "5e91cb22-991c-4874-b8fe-8add2d48b463",
  "auth_time": 0,
  "realm_access": {
    "roles": [
      "manage-account",
      "realm-admin",
      "offline_access",
      "uma_authorization",
      "view-profile"
    ]
  },
  "resource_access": {
    "simplewebapp": {
      "roles": []
    },
    "keystone": {
      "roles": []
    }
  },
  "authorization": {
    "permissions": []
  },
  "LDAP_ENTRY_DN": [
    "uid=pablof,ou=group,dc=aa,dc=bb"
  ],
  "uidNumber": [
    "21471"
  ],
  "name": "Pablo ",
  "preferred_username": "pablof",
  "given_name": "Pablo",
  "createTimestamp": [
    "20170630074958Z"
  ],
  "modifyTimestamp": [
    "20170630074958Z"
  ],
  "LDAP_ID": [
    "pablof"
  ]
}

But then again I could not find a way to create a policy (for client 2)
based on resources from another client.

Something that puzzles me is that, even if I make enough conditions to
make my policy issue DENY, I can still log in with client 1 into client
2. Is there anything else I have to do to make the login fail?


>
> You don't really need to use a JS policy for such condition. Have you
> tried used the "Client Policy" ?

Yes, this is one of the things that I tried... but oddly enough, I
always get the same answer (DENY if set to Possitive logic, PERMIT if
set to Negative) regardless of the client 1 that I am using to access my
client 2.

>
> Could you provide more details about the application you are
> protecting ? What is the adapter you are using ? I think we have some
> tests that are doing pretty much the same thing you are looking for [1].

What do you mean by adapter in the application to protect? If what you
mean is how does client 2 accept/reject tokens, it's an Apache app (it's
actually OpenStack Keystone) with this config:

       OIDCClaimPrefix "OIDC-"
       OIDCResponseType "code"
       OIDCScope "openid profile"
       OIDCProviderMetadataURL
https://myidp.domain.country:8443/auth/realms/keystonerealm/.well-known/openid-configuration
       OIDCClientID keystone
       OIDCClientSecret mysecret
       OIDCProviderTokenEndpointAuth client_secret_basic
       OIDCCryptoPassphrase mypass
       OIDCRedirectURI
http://localhost:5000/v3/auth/OS-FEDERATION/websso/oidc/redirect
       OIDCOAuthVerifyJwksUri
"https://myidp.domain.country:8443/auth/realms/keystonerealm/protocol/openid-connect/certs"

If you mean client 1 (which is the one I want to limit the scope of its
actions), that's a simple webapp querying everything via REST api.

But please keep in mind that I want to protect users coming from client
1 from accessing services included in Keycloak itself (like the /account
API) and there is little I can do to protect it via the APACHE OIDC
module... and, ideally, I would like to do all this restricting inside
Keycloak, without touching every Apache (or whatever client 2) that I
have around here.

BTW, I think you are missing an URL for example [1] you wanted to show
me. Could you please re-post it?

I have the impression that I am missing something fundamental... but I
don't know what it can be.

Thanks a lot to everyone who is helping me out!
BR/Pablo



>
> Regards.
> Pedro Igor
>
> On Fri, Aug 18, 2017 at 6:00 AM, Pablo Fernandez
> <pablo.fernandez at cscs.ch <mailto:pablo.fernandez at cscs.ch>> wrote:
>
>     Thanks Simon,
>
>     Yes, I think we're getting closer. To avoid confusion, let me
>     rename the
>     originating client "A" and the resource client "B".
>
>     Answer in-line:
>
>
>     On 17/08/17 17:05, Simon Payne wrote:
>     > Hi, i'm not sure i follow your use case then.  I read your
>     question to mean
>     > 'how to restrict a resource server to only validating a token to
>     tokens
>     > requested by white listed clients.'
>     It's almost right, but just inside Keycloak (so, without touching the
>     client A itself or the resource server behind client B.)
>
>     > audience is keycloak defaults to the client id if not
>     specified.  you can
>     > override this to whatever you want by adding to the mappers tab.
>
>     I was taking a look at the different types of Mappers for client A and
>     did not find one for the audience. What kind of mapper should one use?
>     Hardcoded claim? Then, the claim should be called 'aud', right?
>     (I am doing everything through the web interface, btw)
>
>     But then, if I do it this way, I will have to change each resource
>     server, right?
>
>     > re-reading your email however, it sounds like scope or roles
>     might be your
>     > solution.  after adding the roles to either the user or service
>     account
>     I could add the role to the client A without using service
>     accounts, right?
>
>     > then you need to add the relevant authorization to each client
>     in the
>     > property file, mapping the resource to the role required. e.g.
>     (springboot)
>     >
>     > keycloak.realm = master
>     > keycloak.auth-server-url = xxxxx
>     > keycloak.ssl-required = external
>     > keycloak.resource = xxxxxx
>     > keycloak.credentials.secret=xxxxxx
>     > keycloak.bearer-only= true
>     >
>     > keycloak.security-constraints[0].authRoles[0] = user
>     > keycloak.security-constraints[0].securityCollections[0].name =
>     resources
>     >
>     keycloak.security-constraints[0].securityCollections[0].patterns[0]
>     = /*
>     >
>     > keycloak.security-constraints[1].authRoles[0] = super_user
>     > keycloak.security-constraints[1].securityCollections[0].name =
>     secure resources
>     >
>     keycloak.security-constraints[1].securityCollections[0].patterns[0]
>     = /products
>
>     I understand you are refering to client B, right? Anyway, I don't find
>     anywhere to change the property file from the web gui. I tried
>     creating
>     a new "auth-scope" in the Authorization section of client B,
>     assigned it
>     to the Default Resource, assigned them all to the Default
>     Permission and
>     all to the Default Policy (the one I defined with JS as for my first
>     email: if (contextAttributes.containsValue('kc.client.id
>     <http://kc.client.id>',
>     'simplewebapp')) {    $evaluation.deny(); }
>
>     (BTW simplewebapp is client A)
>
>     No luck :( am I doing something wrong?
>
>     (I did not force any role on client A, and policy is set to Enforcing)
>
>     > Alternatively you can make use of the authorization services to
>     achieve the
>     > same thing, but must enable at the client by using
>     > keycloak.policy-enforcer-config.enforcement-mode=ENFORCING  I
>     noticed that
>     > before the auth services would work i also had to include client
>     side
>     > mapping of the minimum level of authorization.
>     I guess here you are also speaking about client B, right?
>
>     I did not understand what you mean by client side mapping of the
>     minimum
>     level of authorization. What client mapping? Are there levels of
>     authorization?
>
>     Thanks a lot for your help!
>     BR/Pablo
>
>
>
>     >
>     >
>     > Hope this helps,
>     >
>     > Simon.
>     >
>     >
>     >
>     >
>     >
>     >
>     > On Thu, Aug 17, 2017 at 7:36 AM, Pablo Fernandez
>     <pablo.fernandez at cscs.ch <mailto:pablo.fernandez at cscs.ch>>
>     > wrote:
>     >
>     >> Dear Simon,
>     >>
>     >> Thanks for your reply.
>     >>
>     >> I am not quite sure your proposal would work in our case (or
>     maybe I
>     >> don't understand it): do you mean that the client will ask for a
>     >> specific audience to be put inside the token, and that the
>     other service
>     >> providers would have to check that the claim is targeted
>     against the
>     >> right audience? That creates a big overhead if you have many
>     SPs, which
>     >> we do. And anyway, how can you limit a certain client to be
>     issued token
>     >> of a certain audience within Keycloak? And furthermore, how can
>     I limit
>     >> the access to the /accounts API on Keycloak for a token given
>     to certain
>     >> clients?
>     >>
>     >> It would be great to have a mechanism inside Keycloak to limit the
>     >> scopes of the various clients directly, without extra work on the
>     >> clients or the SPs. Am I assuming something that is wrong? What
>     is the
>     >> Authorization tab (and/or the Scopes one) for?
>     >>
>     >> Thanks a lot again,
>     >> BR/Pablo
>     >>
>     >>
>     >> On 16/08/17 15:20, Simon Payne wrote:
>     >>> Pablo,
>     >>>
>     >>> i'm not sure whether this will be your solution directly, but
>     i found out
>     >>> recently that the 'aud' claim in the token is to represent the
>     audience.
>     >>> Now, when i used the spring-security-oauth client library i
>     found that it
>     >>> validated the resourceId against this aud claim.
>     >>>
>     >>> i thought it an unnecessary constraint at the time, but maybe
>     it could be
>     >>> used to restrict access by tokens, which although may have the
>     correct
>     >>> scope, have been issued to the incorrect or otherwise unknown
>     client?
>     >>>
>     >>> Simon.
>     >>>
>     >>> On Wed, Aug 16, 2017 at 1:41 PM, Pablo Fernandez <
>     >> pablo.fernandez at cscs.ch <mailto:pablo.fernandez at cscs.ch>>
>     >>> wrote:
>     >>>
>     >>>> Dear Keycloakers,
>     >>>>
>     >>>> I am (almost) new to Keycloak and having trouble, and I
>     thought I should
>     >>>> ask you after exhausting other options, so here I am.
>     >>>>
>     >>>> What I would like to find is a way to confine certain web
>     apps (with a
>     >>>> registered client in Keycloak) from accessing any other
>     client that is
>     >>>> not supposed to. Specifically, I have an oidc client named
>     'keystone'
>     >>>> that handles all OpenStack authentication and another oidc client
>     >>>> 'simplewebapp' that is a webapp that I want to give access to
>     'keystone'
>     >>>> while NOT giving access to any of the other clients (e.g.
>     account,
>     >>>> admin-cli, broker, etc.)
>     >>>>
>     >>>> Is there a way to do this?
>     >>>>
>     >>>> I thought about Scopes, but I see they are basically linked
>     to Roles
>     >>>> that I think have nothing to do with what I am doing (I
>     tried, though
>     >>>> creating new roles but it seems to me they don't prevent
>     anything from
>     >>>> happening). If I have to use Scopes, then how? Is there a
>     Role that I
>     >>>> can use to deny - or exclusively grant - access to another
>     client? I
>     >>>> also tried changing the Default Policy in 'keystone'
>     Authorization tab
>     >>>> to something like this (the opposite of what I wanted to do,
>     to make it
>     >>>> fail and see if I can use this mechanism), without success:
>     >>>>
>     >>>> ---
>     >>>> // by default, grants any permission associated with this policy
>     >>>> //$evaluation.grant();
>     >>>> var context = $evaluation.getContext();
>     >>>> var contextAttributes = context.getAttributes();
>     >>>> if (contextAttributes.containsValue('kc.client.id
>     <http://kc.client.id>', 'simplewebapp')) {
>     >>>>     $evaluation.deny();
>     >>>> }
>     >>>> $evaluation.grant();
>     >>>> ---
>     >>>>
>     >>>> I googled and browsed and tried many different setting
>     combinations
>     >>>> without success, so I hope someone here could give me a hint.
>     >>>>
>     >>>> Thanks!
>     >>>> Pablo Fernandez
>     >>>>
>     >>>>
>     >>>>
>     >>>> _______________________________________________
>     >>>> keycloak-user mailing list
>     >>>> keycloak-user at lists.jboss.org
>     <mailto:keycloak-user at lists.jboss.org>
>     >>>> https://lists.jboss.org/mailman/listinfo/keycloak-user
>     <https://lists.jboss.org/mailman/listinfo/keycloak-user>
>     >>>>
>     >>> _______________________________________________
>     >>> keycloak-user mailing list
>     >>> keycloak-user at lists.jboss.org
>     <mailto:keycloak-user at lists.jboss.org>
>     >>> https://lists.jboss.org/mailman/listinfo/keycloak-user
>     <https://lists.jboss.org/mailman/listinfo/keycloak-user>
>     >>
>     >>
>     >> _______________________________________________
>     >> keycloak-user mailing list
>     >> keycloak-user at lists.jboss.org
>     <mailto:keycloak-user at lists.jboss.org>
>     >> https://lists.jboss.org/mailman/listinfo/keycloak-user
>     <https://lists.jboss.org/mailman/listinfo/keycloak-user>
>     >>
>     > _______________________________________________
>     > keycloak-user mailing list
>     > keycloak-user at lists.jboss.org <mailto:keycloak-user at lists.jboss.org>
>     > https://lists.jboss.org/mailman/listinfo/keycloak-user
>     <https://lists.jboss.org/mailman/listinfo/keycloak-user>
>
>
>
>     _______________________________________________
>     keycloak-user mailing list
>     keycloak-user at lists.jboss.org <mailto:keycloak-user at lists.jboss.org>
>     https://lists.jboss.org/mailman/listinfo/keycloak-user
>     <https://lists.jboss.org/mailman/listinfo/keycloak-user>
>
>



More information about the keycloak-user mailing list