Using OIDC adapter with 3rd party IdPs
by Dmitry Telegin
Hello everyone,
In this thread [1] Fabrizio has noted that while Keycloak SAML adapter can be easily used with 3rd party SAML IdPs, the some doesn't work with OIDC by some reason. The reason in fact is that we hardcode Keycloak-specific string templates:
public interface ServiceUrlConstants {
public static final String AUTH_PATH = "/realms/{realm-name}/protocol/openid-connect/auth";
public static final String TOKEN_PATH = "/realms/{realm-name}/protocol/openid-connect/token";
public static final String TOKEN_SERVICE_LOGOUT_PATH = "/realms/{realm-name}/protocol/openid-connect/logout";
public static final String ACCOUNT_SERVICE_PATH = "/realms/{realm-name}/account";
public static final String REALM_INFO_PATH = "/realms/{realm-name}";
public static final String CLIENTS_MANAGEMENT_REGISTER_NODE_PATH = "/realms/{realm-name}/clients-managements/register-node";
public static final String CLIENTS_MANAGEMENT_UNREGISTER_NODE_PATH = "/realms/{realm-name}/clients-managements/unregister-node";
public static final String JWKS_URL = "/realms/{realm-name}/protocol/openid-connect/certs";
}
and then resolve them in KeycloakDeployment. While I've suggested to Fabrizio that he could use KeycloakConfigResolver to customize KeycloakDeployment and override resolveUrls(), I wonder could it be out of the box?
I mean we could retrieve .well-known/openid-configuration from auth-server-url, or, in case of no backchannel, embed it into keycloak.json (keycloak-saml.xml style):
{
"auth-server-url": "http://localhost:8080/auth",
"openid-configuration": {
"authorization_endpoint": "https://accounts.intuit.com/op/v1/ase",
"id_token_signing_alg_values_supported": [
"RS256"
],
"issuer": "https://oauth.platform.intuit.com/op/v1",
"jwks_uri": "https://oauth.platform.intuit.com/op/v1/jwks",
"response_types_supported": [
"code"
],
"revocation_endpoint": "https://oauth.platform.intuit.com/oauth2/v1/tokens/revoke",
"subject_types_supported": [
"public"
],
"token_endpoint": "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer",
"userinfo_endpoint": "https://accounts.platform.intuit.com/v1/openid_connect/userinfo"
},
"ssl-required": "external",
"resource": "test",
"public-client": true,
"confidential-port": 0
}
Seems like a valuable addition to Keycloak, but surprisingly I couldn't find any related JIRA issue. What do you think?
[1] http://lists.jboss.org/pipermail/keycloak-user/2018-November/016193.html
Cheers,
Dmitry Telegin
CTO, Acutus s.r.o.
6 years, 1 month
There is already a httpSessionManager
by Calixto Meleán
I’m doing a simple tutorial with SpringBoot 2.1.0 and KeyCloack 4.5.0. When I start my app, I am getting the error below. It’s like the session manager bean is being registered more than once.
org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'httpSessionManager' defined in class path resource [com/example/demo/configuration/SecurityConfig.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=securityConfig; factoryMethodName=httpSessionManager; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/example/demo/configuration/SecurityConfig.class]] for bean 'httpSessionManager': There is already [Generic bean: class [org.keycloak.adapters.springsecurity.management.HttpSessionManager]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in URL [jar:file:/Users/bigcat/.m!
2/repository/org/keycloak/keycloak-spring-security-adapter/4.5.0.Final/keycloak-spring-security-adapter-4.5.0.Final.jar!/org/keycloak/adapters/springsecurity/management/HttpSessionManager.class]] bound.
Relevant maven dependencies I have are:
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
<version>${keycloak.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
SecurityConfig.class is:
@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Bean
public KeycloakConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
/**
* Registers the KeycloakAuthenticationProvider with the authentication manager.
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
/**
* Defines the session authentication strategy.
*/
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Override
protected void configure(HttpSecurity http) throws Exception
{
super.configure(http);
http
.authorizeRequests()
.antMatchers("/customers*").hasRole("pharmacist")
.anyRequest().permitAll();
}
}
Appreciate any help. Thanks
6 years, 1 month
Re: [keycloak-dev] [keycloak-user] /authz/protection/permission/ticket usage?
by Ulrik Sjölin
Hello,
Thank you for you quick answer, things are really close now :)
Unfortunately using returnNames in GET permission/ticket triggers an NPE
when I use returnNames. I have built from tip of master
(29f8187978ea464ff6636981ede22ac5f7f86075).
I paste in the full console printout below. The NPE occurs at:
15:13:47,468 ERROR XNIO-1 task-15
[org.keycloak.services.error.KeycloakErrorHandler] Uncaught server error
java.lang.NullPointerException
at
org.keycloak.models.utils.ModelToRepresentation.toRepresentation(ModelToRepresentation.java:877)
The function in question seems to fail to get the owner. I tried to use
ownerName when creating the ticket, and sure enough I got:
[
{
"id": "9785e990-8f14-408b-814b-f8f8b46e5076",
"owner": "5759f399-a9c0-47e1-8eb7-dd8b9148aaec",
"resource": "740fb06e-a543-4cca-9be1-ab240710c4c9",
"scope": "55b45b56-2fcb-4b18-b9ab-ec68c53fc14b",
"granted": true,
"requester": "b4e263e7-7739-4e0b-b554-b96520d27bae"
}
]
So the owner field is set in the DB but it seems that line 874 still sets
owner variable to null… I am really at loss what to do. I suspect a patch
where we
check for null on owner and requester is not the right thing to do :)
858 public static PermissionTicketRepresentation
toRepresentation(PermissionTicket ticket, AuthorizationProvider
authorization, boolean returnNames) {
859 PermissionTicketRepresentation representation = new
PermissionTicketRepresentation();
860
861 representation.setId(ticket.getId());
862 representation.setGranted(ticket.isGranted());
863 representation.setOwner(ticket.getOwner());
864 representation.setRequester(ticket.getRequester());
865
866 Resource resource = ticket.getResource();
867
868 representation.setResource(resource.getId());
869
870 if (returnNames) {
871 representation.setResourceName(resource.getName());
872 KeycloakSession keycloakSession =
authorization.getKeycloakSession();
873 RealmModel realm = authorization.getRealm();
874 UserModel owner =
keycloakSession.users().getUserById(ticket.getOwner(), realm);
875 UserModel requester =
keycloakSession.users().getUserById(ticket.getRequester(), realm);
876 representation.setRequesterName(requester.getUsername());
877 representation.setOwnerName(owner.getUsername());
878 }
879
880 Scope scope = ticket.getScope();
881
882 if (scope != null) {
883 representation.setScope(scope.getId());
884 if (returnNames) {
885 representation.setScopeName(scope.getName());
886 }
887 }
888
889 return representation;
890 }
891 }
Best Regards,
Ulrik
15:13:47,468 ERROR XNIO-1 task-15
[org.keycloak.services.error.KeycloakErrorHandler] Uncaught server error
java.lang.NullPointerException
at
org.keycloak.models.utils.ModelToRepresentation.toRepresentation(ModelToRepresentation.java:877)
at
org.keycloak.authorization.protection.permission.PermissionTicketService.lambda$find$90(PermissionTicketService.java:224)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.LinkedList$LLSpliterator.forEachRemaining(LinkedList.java:1235)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at
java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at
java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at
org.keycloak.authorization.protection.permission.PermissionTicketService.find(PermissionTicketService.java:225)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
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:106)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:132)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:106)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:132)
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:847)
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
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.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
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
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
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
15:15:05,130 ERROR XNIO-1 task-22
[org.keycloak.services.error.KeycloakErrorHandler] Uncaught server error
java.lang.NullPointerException
at
org.keycloak.models.utils.ModelToRepresentation.toRepresentation(ModelToRepresentation.java:877)
at
org.keycloak.authorization.protection.permission.PermissionTicketService.lambda$find$90(PermissionTicketService.java:224)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.LinkedList$LLSpliterator.forEachRemaining(LinkedList.java:1235)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at
java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at
java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at
org.keycloak.authorization.protection.permission.PermissionTicketService.find(PermissionTicketService.java:225)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
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:106)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:132)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:106)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:132)
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:847)
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
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.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
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
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
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
On 9 November 2018 at 14:37:01, Pedro Igor Silva (psilva(a)redhat.com) wrote:
Hi,
You can use "scopeName" and "requesterName" properties for that. Take a
look here
https://github.com/keycloak/keycloak/blob/5cbe595fe3094aae8135b8f2c729e9a...
.
Regards.
Pedro Igor
On Fri, Nov 9, 2018 at 7:18 AM Ulrik Sjölin <ulrik.sjolin(a)gmail.com> wrote:
> Hello,
>
> I have a question on how to use the
> API: /authz/protection/permission/ticket
>
> I can call the endpoint successfully if I do the call with only ids:
>
> curl --silent -X POST \
> http://
> ${host}:${port}/auth/realms/${realm}/authz/protection/permission/ticket
> \
> -H "Authorization: Bearer ${service_access_token}" \
> -H "Content-Type: application/json" \
> -d "{
> \"resource\":\"${resource_id}\",
> \"scope\":\"40065a35-02d5-4db9-be46-02566cf7a666\",
> \"requester\":\"79ae9a5a-0304-41ec-b721-d57a09d419cb\",
> \"granted\":\"true\"
> }”
>
> It would however be a lot more workable for me if I could use names like:
>
> curl --silent -X POST \
> http://
> ${host}:${port}/auth/realms/${realm}/authz/protection/permission/ticket
> \
> -H "Authorization: Bearer ${service_access_token}" \
> -H "Content-Type: application/json" \
> -d "{
> \"resource\":\"${resource_id}\",
> \"scope\":\”Read\",
> \"requester\":\”alice\",
> \"granted\":\"true\"
> }”
>
> But when I do this I get:
>
> {"error":"invalid_scope","error_description":"Scope [Read] is invalid”}
> {"error":"invalid_permission","error_description":"Requester does not
> exists in this server as user.”}
>
> Looking at the code there seems to be lookups from names to id, but
> for some reason it fails. What
> am I doing wrong? Any help is greatly appreciated.
>
> Best Regards,
>
> Ulrik Sjölin
>
> _______________________________________________
> keycloak-user mailing list
> keycloak-user(a)lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/keycloak-user
6 years, 1 month
master admin and realm admin check improvement
by Gideon Caranzo
Hi,
During realm import, there is a step wherein the master admin roles and
realm admin roles are checked. In my understanding, this is needed because
some realm JSON from older versions may not have all the admin roles.
These steps takes at least 20 seconds for my setup since I have a very
large number of realms. Is it okay if these are done only when roles are
present in the JSON to speed up realm creation?
It would look like this in *RealmManager *class:
*public* RealmModel importRealm(RealmRepresentation rep, *boolean*
skipUserDependent) {
…
*if* (rep.getRoles() != *null*) {
// Assert all *admin* roles are available once import took
place. This is needed due to import from previous version where JSON file
may not contain all *admin* roles
checkMasterAdminManagementRoles(realm);
checkRealmAdminManagementRoles(realm);
}
Thank you.
Best regards,
Gideon
6 years, 1 month
Order of Protocol Mappers
by Anil Saldanha
Hi all,
quick question. If a bunch of protocol mappers have been written and
listed in META-INF/services, is there a way to show them in alphabetical
order in the UI?
Regards,
Anil
6 years, 1 month
Full implementation of SAML artifact-binding for [JIRA KEYCLOAK-831]
by Doswald Alistair
Hello,
A couple of weeks ago I submitted a partial implementation of artifact-binding (only AuthnRequests were handled) as a pull request, mostly to have some code review before I proceeded (though I didn't get any feedback).
Now I have fully implemented the artifact binding part of SAML. How should I proceed:
1. Should I close the current pull request, and submit a new one with the full code,
2. Should I commit the code on the same fork as I'm currently doing a PR on? It should be adding into the PR and I can update the description to say that it's the full code.
Best regards,
Alistair
6 years, 1 month
Keycloak with CockroachDB
by Poiffaut Romain
Hello,
For the Cloudtrust project (https://github.com/cloudtrust), I have investigated the feasibility of supporting CockroachDB in Keycloak.
I have created a fork based on Keycloak 3.4.3 (it was the latest version when I started on this) working with CockroachDB 2.0.2. It is now working with this DB, and passes all unit tests. Some resilience tests have also been performed to validate the whole integration.
Address of the repo : https://github.com/cloudtrust/keycloak/tree/cockroach-db
For those who might be interested, here are some details:
CockroachDB is a multi-master SQL database designed to run in the cloud and being resilient to failures (https://www.cockroachlabs.com/).
This database has a lot of very interesting properties such as being lockless, distributed and supporting serializable isolation.
CockroachDB introduces the notion of SAVEPOINT. As this DB is lockless, a transaction may fail due to a concurrent transaction. In such case, we can rollback to the SAVEPOINT and retry the transaction. Retrying transactions has the benefit of increasing their priority each time they are retried, thus increasing their likelihood to succeed. (More detailed information are available in their very good documentation (e.g. https://www.cockroachlabs.com/docs/stable/transactions.html#client-side-t..., https://www.cockroachlabs.com/blog/how-cockroachdb-distributes-atomic-tra..., https://www.cockroachlabs.com/blog/serializable-lockless-distributed-isol... ))
So even if CockroachDB uses PostgreSQL driver to communicate with the DB, one of the challenges was to add an automatic transaction retry mechanism with the smallest impact on Keycloak.
Thanks to the architecture of Keycloak, this mechanism can be added in KeycloakSessionServletFilter with a very limited impact.
A second challenge is due to the rollbackOnly mechanism implemented in Keycloak and Hibernate: after a rollback, a transaction cannot be used anymore.
The retry operation must be performed in the same transaction to increase its priority.
Thus the rollbackOnly mechanism is disabled/bypassed in order to keep the transaction active even after a rollback is issued.
As suggested by CockroachDB, we replace the default Hibernate transaction coordinator class to a custom one (https://github.com/cockroachdb/hibernate-savepoint-fix).
Moreover, we mainly modify JpaKeycloakTransaction so that if the transaction fails to commit due to retryable transaction error, we disable the rollbackOnly mechansim to able to retry the transaction.
CockroachDB does not support addition of some constraints (e.g. primary keys) after table creation.
To circumvent this limitation, we can create a new table, migrate the data, delete the old table, rename the new table with the correct name.
As CockroachDb was not supported by Keycloak until now, we didn’t adapt all existing liquibase scripts. We decided to create a new liquibase script which creates the whole database schema for the current version.
This current limitation is being discussed and will be fixed in future release (https://github.com/cockroachdb/cockroach/issues/19141).
Some tests have also been slightly adapted to support SERIALIZABLE isolation, so other DBs configured with such level can also benefit from this adaptation (i.e. PostgreSQL)
These challenges have been solved and our forked version of Keycloak is now compatible with CockroachDB, but it currently is at the cost of breaking the usage of standard databases.
Our company is really interested to add the support of this DB into Keycloak and to provide it to the community.
The next steps now would be to migrate our fork to the latest version of Keycloak and add the support of this DB without breaking support of the others and we would be happy to discuss it.
Cheers,
Romain Poiffaut
6 years, 1 month
Re: [keycloak-dev] Custom REST endpoint - how to make sure that only admins can call it?
by marco.scheuermann@daimler.com
Using correct dev mailing list...
Von: "Scheuermann, Marco (059)" <marco.scheuermann(a)daimler.com>
Datum: Dienstag, 6. November 2018 um 13:41
An: "keycloak-dev-bounces(a)lists.jboss.org" <keycloak-dev-bounces(a)lists.jboss.org>
Cc: "Herrmann, David Christian (059)" <david_christian.herrmann(a)daimler.com>
Betreff: Custom REST endpoint - how to make sure that only admins can call it?
Hi Community,
we just implemented a custom REST endpoint based on
org.keycloak.services.resource.RealmResourceProvider;
How can we make sure that only users with admin role can call these endpoints?
Due to the fact that it is a SPI implementation, I have not deployment descriptors to configure security for the endpoint...
Greetings,
Marco
If you are not the addressee, please inform us immediately that you have received this e-mail by mistake, and delete it. We thank you for your support.
6 years, 1 month
The ultimate fate of master realm
by Dmitry Telegin
Hi,
The idea of getting rid of master realm has been around for years [1] [2]. Just wanted to know, what's the current stance on this? Can we tell for sure that there still will be master realm in KC 5.0? Or can we tell the opposite?
Some background: we're working on a Keycloak extension (provider) that needs to operate a global (non-realm-based) writable config. So I'm choosing between the two options:
- store config keys as master realm attributes;
- introduce full-fledged configuration system based on Apache Commons Configuration, backed by its own DB table and Infinispan cache.
The latter is obviously more complex, however more powerful. I've posted a write-up on it about a year ago [3], but didn't get any feedback. I hope it could be reevaluated today; for Keycloak proper, there are several use cases like auto-update settings, admin email, periodic tasks etc.
The former, on the contrary, is much easier to implement, however there is a risk of having to rewrite everything from scratch should master realm bite the dust one day.
Cheers,
Dmitry Telegin
CTO, Acutus s.r.o.
[1] http://lists.jboss.org/pipermail/keycloak-dev/2015-December/006066.html
[2] https://issues.jboss.org/browse/KEYCLOAK-3443
[3] http://lists.jboss.org/pipermail/keycloak-dev/2017-December/010261.html
6 years, 1 month