Uncaught server error: java.lang.IllegalStateException: Could not find composite in role admin:
by madhura nishshanka
Hi All,
I am getting following exception when I execute create realm and delete
realm rest APIs concurrently. Is this a known issue in keycloak?. The
jmeter script used is also attached. Can some one please help me on this?
ERROR [org.keycloak.services.error.KeycloakErrorHandler] (default task-4)
Uncaught server error: java.lang.IllegalStateException: Could not find
composite in role admin: 4c8f06e2-74f0-4d83-94af-1ae61e1aecde
at
org.keycloak.models.cache.infinispan.RoleAdapter.getComposites(RoleAdapter.java:136)
at
org.keycloak.models.utils.KeycloakModelUtils.searchFor(KeycloakModelUtils.java:190)
at
org.keycloak.models.cache.infinispan.RoleAdapter.hasRole(RoleAdapter.java:173)
at
org.keycloak.models.cache.infinispan.UserAdapter.hasRole(UserAdapter.java:313)
at
org.keycloak.authorization.common.UserModelIdentity.hasRealmRole(UserModelIdentity.java:57)
at
org.keycloak.services.resources.admin.permissions.MgmtPermissions.canCreateRealm(MgmtPermissions.java:384)
at
org.keycloak.services.resources.admin.permissions.MgmtPermissions.requireCreateRealm(MgmtPermissions.java:389)
at
org.keycloak.services.resources.admin.RealmsAdminResource.importRealm(RealmsAdminResource.java:135)
at sun.reflect.GeneratedMethodAccessor767.invoke(Unknown Source)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at
org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:140)
at
org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:509)
at
org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:399)
at
org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$0(ResourceMethodInvoker.java:363)
at
org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:358)
at
org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:365)
at
org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:337)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:137)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:100)
at
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:443)
at
org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:233)
at
org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:139)
at
org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:358)
at
org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:142)
at
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:219)
at
org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:227)
at
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
at
io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at
org.keycloak.services.filters.KeycloakSessionServletFilter.doFilter(KeycloakSessionServletFilter.java:90)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at
io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at
io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at
io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at
io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at
org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
at
io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at
io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at
io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at
io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at
io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at
io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
at
io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
at
io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
at
io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at
io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at
io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at
org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
at
org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at
org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at
org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at
org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at
io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at
io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at
io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:360)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at
org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at
org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
at
org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
at
org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1378)
at java.lang.Thread.run(Thread.java:748).
Thanks
Madhura
5 years, 11 months
Switching to Native JavaScript promise by default
by Stian Thorgersen
I would like to switch the JavaScript adapter to use Native promises by
default and deprecate the legacy promise with the aim to remove it in the
future.
This would result in users that want to continue to use the legacy promise
having to explicitly enable this in the config.
I see this as the best path to eventually remove the legacy promises.
5 years, 11 months
Role Mappings on Subsequent Logons
by Will Osborn
Hi,
I have setup a keycloak server and using an identity provider successfully setup SSO with claims to role mappings. Is there any way to allow subsequent logons to recheck the claims and reapply the role mappings so if they change in the identity provide system those changes are passed through to Keycloak?
Thanks
Will
[/var/folders/zg/5xxh34t177b013xm4c89lzw00000gp/T/com.microsoft.Outlook/WebArchiveCopyPasteTempFiles/AeG8I8l0vp2nAAAAABJRU5ErkJggg==]
Will Osborn | Head of delivery
Phone +44 203 9301640
VAKT Global Ltd, Floor 24
1 Canada Square,
London, E14 5AB
Disclaimer: This e-mail and any attachment may contain information that is privileged or confidential. It is intended solely for the use of the individual or entity to which it is addressed. If you are not the intended recipient, please notify the author immediately by telephone or by replying to this e-mail, and then delete all copies of the e-mail on your system. If you are not the intended recipient, you must not use, disclose, distribute, copy, print or rely on this e-mail.
Whilst we have taken reasonable precautions to ensure that this e-mail and any attachment has been checked for viruses, we cannot guarantee that they are virus free and we cannot accept liability for any damage sustained as a result of software viruses. We would advise that you carry out your own virus checks, especially before opening an attachment.
VAKT Global Limited is registered in England and Wales under the Company Number 11295972. Its registered office is Floor 24, 1 Canada Square, London, E14 5AB.
5 years, 11 months
Getting timestamp from EVENT_ENTITY
by Edmund Loh
The EVENT_TIME column in the EVENT_ENTITY table is stored as datatype
NUMBER(38,0). How can I go about converting this to a timestamp through the
use of SQL statements?
5 years, 11 months
Customize saml response
by Pulkit Srivastava
Hi,
I am using as external idp with keycloak. External idp sends SAML response
to keycloak but keycloak modifies that response before sending it to the
application, so i am unable to get some important attributes. How can we
stop keycloak from modifying the response or how can we customize the
response.
Thanks,
Pulkit
5 years, 11 months
Re: [keycloak-user] Policy Enforcer: enforcement-mode=ENFORCING question
by Alexey Titorenko
Thanks!
> On 4 Feb 2019, at 15:58, Pedro Igor Silva <psilva(a)redhat.com> wrote:
>
> Yeah, you are right. I've created https://issues.jboss.org/browse/KEYCLOAK-9483 <https://issues.jboss.org/browse/KEYCLOAK-9483> to track this and make this behaviour more intuitive without forcing you to create additional permissions or only associate scopes.
>
> On Mon, Feb 4, 2019 at 10:52 AM Alexey Titorenko <titorenko(a)dtg.technology> wrote:
> Ok, thank you, Pedro.
>
> Just few words about this.
>
> If I see description of ‘Resource’ field, then it says that it is just a filter for scopes field shown below it (see screenshot below). It this filter has side affects and changes access area, then it is even more strange and dangerous.
> This might be problematic if I have two resources in my service that have same set of scopes (or intersecting sets).
>
>
> Again, thank you for Jira ticket.
>
> Alexey
>
> <Screenshot 2019-02-04 at 15.45.20.png>
>
>
>
>
>> On 4 Feb 2019, at 15:41, Pedro Igor Silva <psilva(a)redhat.com <mailto:psilva@redhat.com>> wrote:
>>
>> Or just leave "list" and remove the resource from your permission ....
>>
>> I agree with you, will open a JIRA to make this more intuitive.
>>
>> Tks
>>
>>
>> On Mon, Feb 4, 2019 at 10:39 AM Alexey Titorenko <titorenko(a)dtg.technology <mailto:titorenko@dtg.technology>> wrote:
>> Hi Pedro.
>>
>> Ok, I understand. To my opinion it is a bit not intuitive and dangerous, as scope based permission opens access to the whole resource. Yes, if I specify permissions for all scopes, then it works fine.
>>
>> Thank you!
>>
>> Alexey
>>
>>
>>> On 4 Feb 2019, at 15:32, Pedro Igor Silva <psilva(a)redhat.com <mailto:psilva@redhat.com>> wrote:
>>>
>>> The main point here is that you are granted with a permission without any scope:
>>>
>>> 2019-02-04 12:29:12.698 DEBUG 5364 --- [nio-8085-exec-4] o.k.a.a.AbstractPolicyEnforcer : Authorization GRANTED for path [PathConfig{name='Documents', type='null', path='/documents/{id}', scopes=[], id='b14999a7-0853-4063-8fe6-c0469a975846', enforcerMode='ENFORCING'}]. Permissions [[Permission {id=b14999a7-0853-4063-8fe6-c0469a975846, name=Documents, scopes=[]}]].
>>>
>>> The policy enforcer understands that "no scopes" means access to the resource itself and that explains why you are able to access that protected resource.
>>>
>>> The reason why you are granted with permission with no scopes is that the policy engine checks whether or not the permission (regardless if scope or resource based) is associated with a resource. If so, access to the resource is granted.
>>>
>>> You can try removing the resource from "List Documents" permission and leave only the "list" scope.
>>>
>>> Another option is define a scope-based permission to each scope.
>>>
>>> For last, I'm wondering if we should only grant access to a resource if the permissions ia actually a resource-based permission. So you will none of the steps above would be necessary and your configuration will work as expected.
>>>
>>> Wdyt ?
>>>
>>>
>>> On Mon, Feb 4, 2019 at 7:54 AM Alexey Titorenko <titorenko(a)dtg.technology <mailto:titorenko@dtg.technology>> wrote:
>>> Hello guys!
>>>
>>> Could someone help me with this.
>>>
>>> I’m playing with policy enforcers in test Spring Boot application trying to find how to apply it to our cases. I’m trying to investigate how 'ENFORCING’ mode is working with scope based permissions.
>>>
>>> My intuitive understanding of this:
>>> if resource does not have any permissions defined on it, then access is denied for any scope requested.
>>> if resource has some permissions, then access to scopes, not covered by any existing permissions is always denied.
>>>
>>> What I see in reality:
>>> first case works fine. Access to my service is denied If no permissions defined on it.
>>> if the resource has a permission, controlling access to one scope, then access to the other scopes is always GRANTED.
>>>
>>> In particular, I’ve created demo REST document storage service, which defines CRUD operations, plus one ‘list’ operation to get list of documents for an entity. All these operations are covered by a corresponding scope (create, view, update, delete, list). After that:
>>> If I have no permissions defined for this service, then no access is granted whatever scope I request.
>>> If I define scope-based permission, let’s say, controlling access to the ‘list’ scope on the resource, then access is automatically granted to requests for all CRUD operations, for example, for ‘create' operation.
>>>
>>> Is it how this is intended to work or not? My expectation is that everything should be denied (every scope), until explicitly allowed by some permission.
>>>
>>> Below are debug log messages that might be of some interest, my policy enforcer config, and some screenshots.
>>>
>>> The first log entry corresponds to ‘create’ operation with ‘create’ scope and the other one — to ‘list’ operation.
>>>
>>> Thank you,
>>> Alexey.
>>>
>>> From Logs:
>>> 2019-02-04 12:29:12.698 DEBUG 5364 --- [nio-8085-exec-4] o.k.a.a.AbstractPolicyEnforcer : Authorization GRANTED for path [PathConfig{name='Documents', type='null', path='/documents/{id}', scopes=[], id='b14999a7-0853-4063-8fe6-c0469a975846', enforcerMode='ENFORCING'}]. Permissions [[Permission {id=b14999a7-0853-4063-8fe6-c0469a975846, name=Documents, scopes=[]}]].
>>>
>>> 2019-02-04 12:29:11.846 DEBUG 5364 --- [nio-8085-exec-3] o.k.a.a.AbstractPolicyEnforcer : Authorization GRANTED for path [PathConfig{name='Documents', type='null', path='/documents/', scopes=[], id='b14999a7-0853-4063-8fe6-c0469a975846', enforcerMode='ENFORCING'}]. Permissions [[Permission {id=b14999a7-0853-4063-8fe6-c0469a975846, name=Documents, scopes=[list]}]].
>>>
>>>
>>> Config
>>> svc.name <http://svc.name/>=docs-uma
>>> server.port = 8085
>>> keycloak.realm=DemoApp
>>> keycloak.auth-server-url=http://localhost:8180/auth <http://localhost:8180/auth>
>>> keycloak.ssl-required=external
>>> keycloak.resource=docs-svc-uma
>>> keycloak.cors=true
>>> keycloak.use-resource-role-mappings=true
>>> keycloak.verify-token-audience=false
>>> keycloak.credentials.secret=0e55734e-aadc-4268-8757-b5dca453980a
>>> keycloak.confidential-port=0
>>> keycloak.bearer-only=true
>>>
>>> keycloak.securityConstraints[0].securityCollections[0].name = secured operation
>>> keycloak.securityConstraints[0].authRoles[0] = user
>>> keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /documents
>>> keycloak.securityConstraints[0].securityCollections[0].patterns[1] = /documents/*
>>>
>>> keycloak.securityConstraints[1].securityCollections[0].name = admin operation
>>> keycloak.securityConstraints[1].authRoles[0] = admin
>>> keycloak.securityConstraints[1].securityCollections[0].patterns[0] = /admin
>>> keycloak.securityConstraints[1].securityCollections[0].patterns[1] = /admin/
>>>
>>> logging.level.org.keycloak=DEBUG
>>> logging.level.dtg.plays.iam.keycloak.demo.backend.docs.auth.keycloak.cip=DEBUG
>>>
>>> # policy enforcer
>>> keycloak.policy-enforcer-config.enforcement-mode=ENFORCING
>>> keycloak.policy-enforcer-config.lazy-load-paths=true
>>> keycloak.policy-enforcer-config.on-deny-redirect-to=/public
>>>
>>> keycloak.policy-enforcer-config.paths[0].name=Public Resources
>>> keycloak.policy-enforcer-config.paths[0].path=/*
>>>
>>> keycloak.policy-enforcer-config.paths[1].name=Admin Resources
>>> keycloak.policy-enforcer-config.paths[1].path=/admin/*
>>> keycloak.policy-enforcer-config.paths[1].claimInformationPointConfig.claims[some-claim]={request.uri}
>>> keycloak.policy-enforcer-config.paths[1].claimInformationPointConfig.claims[claims-from-document]={request.uri}
>>>
>>> keycloak.policy-enforcer-config.paths[2].name=Documents
>>> keycloak.policy-enforcer-config.paths[2].path=/documents/
>>> keycloak.policy-enforcer-config.paths[2].methods[0].method=POST
>>> keycloak.policy-enforcer-config.paths[2].methods[0].scopes[0]=create
>>> keycloak.policy-enforcer-config.paths[2].methods[1].method=GET
>>> keycloak.policy-enforcer-config.paths[2].methods[1].scopes[0]=list
>>> keycloak.policy-enforcer-config.paths[3].name=Documents
>>> keycloak.policy-enforcer-config.paths[3].path=/documents/{id}
>>> keycloak.policy-enforcer-config.paths[3].methods[0].method=GET
>>> keycloak.policy-enforcer-config.paths[3].methods[0].scopes[0]=get
>>> keycloak.policy-enforcer-config.paths[3].methods[1].method=POST
>>> keycloak.policy-enforcer-config.paths[3].methods[1].scopes[0]=update
>>> keycloak.policy-enforcer-config.paths[3].methods[2].method=DELETE
>>> keycloak.policy-enforcer-config.paths[3].methods[2].scopes[0]=delete
>>>
>>> Client authorisation config:
>>> {
>>> "allowRemoteResourceManagement": true,
>>> "policyEnforcementMode": "ENFORCING",
>>> "resources": [
>>> {
>>> "name": "Admin Resources",
>>> "type": "urn:docs-svc-uma:resources:admin",
>>> "ownerManagedAccess": false,
>>> "attributes": {},
>>> "_id": "0ca1b086-c3d1-47eb-8fa6-3bb699af8791",
>>> "uris": [
>>> "/admin/*",
>>> "/admin"
>>> ],
>>> "icon_uri": ""
>>> },
>>> {
>>> "name": "Documents",
>>> "type": "urn:docs-svc-uma:resources:documents",
>>> "ownerManagedAccess": false,
>>> "attributes": {},
>>> "_id": "b14999a7-0853-4063-8fe6-c0469a975846",
>>> "uris": [
>>> "/documents/{id}",
>>> "/documents/"
>>> ],
>>> "scopes": [
>>> {
>>> "name": "view"
>>> },
>>> {
>>> "name": "update"
>>> },
>>> {
>>> "name": "delete"
>>> },
>>> {
>>> "name": "create"
>>> },
>>> {
>>> "name": "list"
>>> }
>>> ]
>>> }
>>> ],
>>> "policies": [
>>> {
>>> "id": "72f8ced8-8b2f-41f3-be41-c371e5d66788",
>>> "name": "Default Policy",
>>> "description": "A policy that grants access only for users within this realm",
>>> "type": "js",
>>> "logic": "POSITIVE",
>>> "decisionStrategy": "AFFIRMATIVE",
>>> "config": {
>>> "code": "// by default, grants any permission associated with this policy\n$evaluation.grant();\n"
>>> }
>>> },
>>> {
>>> "id": "b786a8bb-3705-4df6-86cd-c041065d3703",
>>> "name": "Never",
>>> "type": "js",
>>> "logic": "POSITIVE",
>>> "decisionStrategy": "UNANIMOUS",
>>> "config": {
>>> "code": "$evaluation.deny();"
>>> }
>>> },
>>> {
>>> "id": "6ca70fa3-907b-4368-97cb-3aadc1b6d5db",
>>> "name": "List Documents",
>>> "type": "scope",
>>> "logic": "POSITIVE",
>>> "decisionStrategy": "UNANIMOUS",
>>> "config": {
>>> "resources": "[\"Documents\"]",
>>> "scopes": "[\"list\"]",
>>> "applyPolicies": "[\"Default Policy\"]"
>>> }
>>> }
>>> ],
>>> "scopes": [
>>> {
>>> "id": "be6a7101-f5a3-4b9f-a6be-349e167e89ae",
>>> "name": "create"
>>> },
>>> {
>>> "id": "ba3a7575-db45-407b-b74a-4e8b1fc461c2",
>>> "name": "delete"
>>> },
>>> {
>>> "id": "e749c197-b70a-4ccd-a719-1c9ef40b6050",
>>> "name": "update"
>>> },
>>> {
>>> "id": "d72a9d39-3750-41c4-954f-0db7853cb964",
>>> "name": "list"
>>> },
>>> {
>>> "id": "6ee46777-a0ee-492a-bb4e-ef8aaeb8f402",
>>> "name": "view",
>>> "iconUri": ""
>>> }
>>> ]
>>> }
>>>
>>>
>>>
>>> _______________________________________________
>>> keycloak-user mailing list
>>> keycloak-user(a)lists.jboss.org <mailto:keycloak-user@lists.jboss.org>
>>> https://lists.jboss.org/mailman/listinfo/keycloak-user <https://lists.jboss.org/mailman/listinfo/keycloak-user>
>
5 years, 11 months
Policy Enforcer: enforcement-mode=ENFORCING question
by Alexey Titorenko
Hello guys!
Could someone help me with this.
I’m playing with policy enforcers in test Spring Boot application trying to find how to apply it to our cases. I’m trying to investigate how 'ENFORCING’ mode is working with scope based permissions.
My intuitive understanding of this:
if resource does not have any permissions defined on it, then access is denied for any scope requested.
if resource has some permissions, then access to scopes, not covered by any existing permissions is always denied.
What I see in reality:
first case works fine. Access to my service is denied If no permissions defined on it.
if the resource has a permission, controlling access to one scope, then access to the other scopes is always GRANTED.
In particular, I’ve created demo REST document storage service, which defines CRUD operations, plus one ‘list’ operation to get list of documents for an entity. All these operations are covered by a corresponding scope (create, view, update, delete, list). After that:
If I have no permissions defined for this service, then no access is granted whatever scope I request.
If I define scope-based permission, let’s say, controlling access to the ‘list’ scope on the resource, then access is automatically granted to requests for all CRUD operations, for example, for ‘create' operation.
Is it how this is intended to work or not? My expectation is that everything should be denied (every scope), until explicitly allowed by some permission.
Below are debug log messages that might be of some interest, my policy enforcer config, and some screenshots.
The first log entry corresponds to ‘create’ operation with ‘create’ scope and the other one — to ‘list’ operation.
Thank you,
Alexey.
From Logs:
2019-02-04 12:29:12.698 DEBUG 5364 --- [nio-8085-exec-4] o.k.a.a.AbstractPolicyEnforcer : Authorization GRANTED for path [PathConfig{name='Documents', type='null', path='/documents/{id}', scopes=[], id='b14999a7-0853-4063-8fe6-c0469a975846', enforcerMode='ENFORCING'}]. Permissions [[Permission {id=b14999a7-0853-4063-8fe6-c0469a975846, name=Documents, scopes=[]}]].
2019-02-04 12:29:11.846 DEBUG 5364 --- [nio-8085-exec-3] o.k.a.a.AbstractPolicyEnforcer : Authorization GRANTED for path [PathConfig{name='Documents', type='null', path='/documents/', scopes=[], id='b14999a7-0853-4063-8fe6-c0469a975846', enforcerMode='ENFORCING'}]. Permissions [[Permission {id=b14999a7-0853-4063-8fe6-c0469a975846, name=Documents, scopes=[list]}]].
Config
svc.name=docs-uma
server.port = 8085
keycloak.realm=DemoApp
keycloak.auth-server-url=http://localhost:8180/auth
keycloak.ssl-required=external
keycloak.resource=docs-svc-uma
keycloak.cors=true
keycloak.use-resource-role-mappings=true
keycloak.verify-token-audience=false
keycloak.credentials.secret=0e55734e-aadc-4268-8757-b5dca453980a
keycloak.confidential-port=0
keycloak.bearer-only=true
keycloak.securityConstraints[0].securityCollections[0].name = secured operation
keycloak.securityConstraints[0].authRoles[0] = user
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /documents
keycloak.securityConstraints[0].securityCollections[0].patterns[1] = /documents/*
keycloak.securityConstraints[1].securityCollections[0].name = admin operation
keycloak.securityConstraints[1].authRoles[0] = admin
keycloak.securityConstraints[1].securityCollections[0].patterns[0] = /admin
keycloak.securityConstraints[1].securityCollections[0].patterns[1] = /admin/
logging.level.org.keycloak=DEBUG
logging.level.dtg.plays.iam.keycloak.demo.backend.docs.auth.keycloak.cip=DEBUG
# policy enforcer
keycloak.policy-enforcer-config.enforcement-mode=ENFORCING
keycloak.policy-enforcer-config.lazy-load-paths=true
keycloak.policy-enforcer-config.on-deny-redirect-to=/public
keycloak.policy-enforcer-config.paths[0].name=Public Resources
keycloak.policy-enforcer-config.paths[0].path=/*
keycloak.policy-enforcer-config.paths[1].name=Admin Resources
keycloak.policy-enforcer-config.paths[1].path=/admin/*
keycloak.policy-enforcer-config.paths[1].claimInformationPointConfig.claims[some-claim]={request.uri}
keycloak.policy-enforcer-config.paths[1].claimInformationPointConfig.claims[claims-from-document]={request.uri}
keycloak.policy-enforcer-config.paths[2].name=Documents
keycloak.policy-enforcer-config.paths[2].path=/documents/
keycloak.policy-enforcer-config.paths[2].methods[0].method=POST
keycloak.policy-enforcer-config.paths[2].methods[0].scopes[0]=create
keycloak.policy-enforcer-config.paths[2].methods[1].method=GET
keycloak.policy-enforcer-config.paths[2].methods[1].scopes[0]=list
keycloak.policy-enforcer-config.paths[3].name=Documents
keycloak.policy-enforcer-config.paths[3].path=/documents/{id}
keycloak.policy-enforcer-config.paths[3].methods[0].method=GET
keycloak.policy-enforcer-config.paths[3].methods[0].scopes[0]=get
keycloak.policy-enforcer-config.paths[3].methods[1].method=POST
keycloak.policy-enforcer-config.paths[3].methods[1].scopes[0]=update
keycloak.policy-enforcer-config.paths[3].methods[2].method=DELETE
keycloak.policy-enforcer-config.paths[3].methods[2].scopes[0]=delete
Client authorisation config:
{
"allowRemoteResourceManagement": true,
"policyEnforcementMode": "ENFORCING",
"resources": [
{
"name": "Admin Resources",
"type": "urn:docs-svc-uma:resources:admin",
"ownerManagedAccess": false,
"attributes": {},
"_id": "0ca1b086-c3d1-47eb-8fa6-3bb699af8791",
"uris": [
"/admin/*",
"/admin"
],
"icon_uri": ""
},
{
"name": "Documents",
"type": "urn:docs-svc-uma:resources:documents",
"ownerManagedAccess": false,
"attributes": {},
"_id": "b14999a7-0853-4063-8fe6-c0469a975846",
"uris": [
"/documents/{id}",
"/documents/"
],
"scopes": [
{
"name": "view"
},
{
"name": "update"
},
{
"name": "delete"
},
{
"name": "create"
},
{
"name": "list"
}
]
}
],
"policies": [
{
"id": "72f8ced8-8b2f-41f3-be41-c371e5d66788",
"name": "Default Policy",
"description": "A policy that grants access only for users within this realm",
"type": "js",
"logic": "POSITIVE",
"decisionStrategy": "AFFIRMATIVE",
"config": {
"code": "// by default, grants any permission associated with this policy\n$evaluation.grant();\n"
}
},
{
"id": "b786a8bb-3705-4df6-86cd-c041065d3703",
"name": "Never",
"type": "js",
"logic": "POSITIVE",
"decisionStrategy": "UNANIMOUS",
"config": {
"code": "$evaluation.deny();"
}
},
{
"id": "6ca70fa3-907b-4368-97cb-3aadc1b6d5db",
"name": "List Documents",
"type": "scope",
"logic": "POSITIVE",
"decisionStrategy": "UNANIMOUS",
"config": {
"resources": "[\"Documents\"]",
"scopes": "[\"list\"]",
"applyPolicies": "[\"Default Policy\"]"
}
}
],
"scopes": [
{
"id": "be6a7101-f5a3-4b9f-a6be-349e167e89ae",
"name": "create"
},
{
"id": "ba3a7575-db45-407b-b74a-4e8b1fc461c2",
"name": "delete"
},
{
"id": "e749c197-b70a-4ccd-a719-1c9ef40b6050",
"name": "update"
},
{
"id": "d72a9d39-3750-41c4-954f-0db7853cb964",
"name": "list"
},
{
"id": "6ee46777-a0ee-492a-bb4e-ef8aaeb8f402",
"name": "view",
"iconUri": ""
}
]
}
5 years, 11 months
Not existent attributes for users from user-federeation cause NPE
by Lorenzo Luconi Trombacchi
I’m using Keycloak version 4.8.3 with a custom user federation plugin. I created a new realm, configured my user federation plugin and created a new client. I tried to authenticate and I got an error 500 from keycloak.
In Keycloak log I found this NullPointerException:
14:09:15,472 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (default task-1) Uncaught server error: java.lang.NullPointerException
at org.keycloak.models.utils.KeycloakModelUtils.resolveAttribute(KeycloakModelUtils.java:414)
at org.keycloak.models.utils.KeycloakModelUtils.resolveAttribute(KeycloakModelUtils.java:415)
at org.keycloak.protocol.oidc.mappers.UserAttributeMapper.setClaim(UserAttributeMapper.java:93)
at org.keycloak.protocol.oidc.mappers.UserAttributeMapper.setClaim(UserAttributeMapper.java:101)
at org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper.setClaim(AbstractOIDCProtocolMapper.java:117)
at org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper.setClaim(AbstractOIDCProtocolMapper.java:119)
at org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper.transformAccessToken(AbstractOIDCProtocolMapper.java:81)
at org.keycloak.protocol.oidc.TokenManager.transformAccessToken(TokenManager.java:606)
at org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper.transformAccessToken(AbstractOIDCProtocolMapper.java:81)
at org.keycloak.protocol.oidc.TokenManager.createClientAccessToken(TokenManager.java:422)
at org.keycloak.protocol.oidc.TokenManager$AccessTokenResponseBuilder.generateAccessToken(TokenManager.java:795)
at org.keycloak.protocol.oidc.TokenManager.transformAccessToken(TokenManager.java:544)
at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.resourceOwnerPasswordCredentialsGrant(TokenEndpoint.java:569)
at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.processGrantRequest(TokenEndpoint.java:186)
at org.keycloak.protocol.oidc.TokenManager.createClientAccessToken(TokenManager.java:402)
…..
After some tests I found the problem: the “Assigned Default Client Scopes” list, in my newly created client, includes the “profile” scope.
The “profile” scope includes a lot of attributes and not all of them are exported from my federation plugin for my users. Removing profile scope solve the problem and now I can successfully authenticate my federeted users.
In class KeycloakModelUtils the are two implementation of the method resolveAttribute:
public static List<String> resolveAttribute(GroupModel group, String name) {
List<String> values = group.getAttribute(name);
if (values != null && !values.isEmpty()) return values;
if (group.getParentId() == null) return null;
return resolveAttribute(group.getParent(), name);
}
public static Collection<String> resolveAttribute(UserModel user, String name, boolean aggregateAttrs) {
List<String> values = user.getAttribute(name);
Set<String> aggrValues = new HashSet<String>();
if (!values.isEmpty()) {
if (!aggregateAttrs) {
return values;
}
aggrValues.addAll(values);
}
for (GroupModel group : user.getGroups()) {
values = resolveAttribute(group, name);
if (values != null && !values.isEmpty()) {
if (!aggregateAttrs) {
return values;
}
aggrValues.addAll(values);
}
}
return aggrValues;
}
As you can see the first implementation checks if values is null, but not the second one where I got NPE.
In my UserModel implementation I override the getAttrubute method:
public class UserAdapter extends AbstractUserAdapterFederatedStorage {
…..
@Override
public List<String> getAttribute(String name) {
if (attributes.containsKey(name)) {
return attributes.get(name);
}
return super.getAttribute(name);
}
}
If I force this method to return an empty list instead of null value, this solve the problem. Is this the right fix? getAttribute method must not returns a null value?
I hope this helps.
Thanks,
Lorenzo
5 years, 11 months