[keycloak-user] Restrict access from web app client
Pedro Igor Silva
psilva at redhat.com
Fri Aug 18 13:38:02 EDT 2017
The "kc.client.id" is a built-in attribute that our policy evaluation
engine makes available to policies before processing them. It basically
maps to the "azp" claim within the token.
When using the evaluation tool, you can also select a client in order to
change the value of this claim and simulate evaluations based on a specific
client acting on behalf of an user.
I did a simple test here where I have a resource server with a single
resource protect by a policy just like that JS policy you wrote. When I
change the client, I'm able to see different results for the evaluation.
But I think what you are trying to do is beyond what we support. You
mentioned that you want to protect specific Keycloak internal services such
as Account Service. That is not possible ...
Sorry for the missing link, this what I was supposed to send
https://github.com/keycloak/keycloak/blob/master/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzFunctionalAdapterTest.java#L283
.
But this example is all about a RS protecting their resources where only a
specific client is allowed to access. It is not related with
protecting/accessing Keycloak internal services ....
On Fri, Aug 18, 2017 at 12:32 PM, Pablo Fernandez <pablo.fernandez at cscs.ch>
wrote:
> 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>
> >
> >
>
> _______________________________________________
> 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