How to access keycloak with the admin-client? - spring-boot

I'm trying to change roles of a user in keycloak with the keycloak-admin-client in a spring boot application, but I can't even instanciate keycloak.
I'm trying to get the keycloak server here, but Im getting a InstantiationError
String serverUrl = "http://localhost:8080/auth";
String realm = "User-Service-Realm";
String clientId = "admin-cli";
Keycloak keycloak = Keycloak.getInstance(
serverUrl,
realm,
"admin",
"admin",
clientId);
Exception in thread "main" java.lang.InstantiationError: org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder
at org.keycloak.admin.client.Keycloak.<init>(Keycloak.java:58)
at org.keycloak.admin.client.Keycloak.getInstance(Keycloak.java:106)
at de.uni.stuttgart.isw.ccm.userservice.api.KeycloakAdminClientExample.main(KeycloakAdminClientExample.java:31)
Apparently its a problem with the admin-client itself, since the keycloak builder is based on the resteasyclientbuilder.

You seem to have incompatible libraries or library versions. The error message complains that ResteasyClientBuilder is abstract. That not the case in our working project.
So as a reference, here is an extract from our gradle file so you can see a working combination of library versions:
implementation 'org.keycloak:keycloak-admin-client:6.0.1'
implementation 'javax.ws.rs:javax.ws.rs-api:2.0'
implementation 'org.jboss.resteasy:resteasy-jaxrs:3.6.3.Final'
implementation 'org.jboss.resteasy:resteasy-client:3.6.3.Final'
implementation 'org.jboss.resteasy:resteasy-jackson2-provider:3.6.3.Final'
Update:
ResteasyClientBuilder has become an abstract class with version 4.0 of RESTEasy. So it looks as if you are using version 4.x, while Keycloak expects 3.x.

Related

Spring Boot 2.3.4: Bug with JwtValidators.createDefaultWithIssuer(String)?

I found an odd behavior with JWT parsing and JwtValidators.
Scenario:
Spring Boot OIDC client (for now a tiny web app, only displaying logged in user and some OIDC objects provided by Spring)
Custom JwtDecoderFacotry<ClientRegistration> for ID-Token validation
JwtValidatorFactory based on JwtValidators.createDefaultWithIssuer(String)
This worked well with Spring Boot version <= 2.2.10.
Debugging:
NimbusJwtDecoder (JAR spring-security-oauth2-jose) uses claim set converters. The 'iss' (issuer) claim is handled as URL.
JwtIssuerValidator (internally created by JwtValidators.createDefaultWithIssuer(String)) wraps a JwtClaimValidator<String>.
this one finally calls equals() that is always false - it compares String with URL.
My current workaround is not calling JwtValidators.createDefaultWithIssuer() but just using the validators new JwtTimestampValidator() and an own implementation of OAuth2TokenValidator<Jwt> (with wrapping JwtClaimValidator<URL>).
Anyone else having trouble with this?
--Christian
It's a bug. Pull Request is created.

How to Configure OAuth 2.0 in Spring by storing the Auth Codes in DataBase instead of ConCurrentHashMap

Currently I am using Spring Security Oauth2 2.3.2 Release. I want to set up a Authorization Code Grant Type Based Authentication.
I debugged the Spring Security "/oauth/authorize" EndPoint. I found below code
private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices();
I debugged more into the code and I found out that AuthorizationCodeServices is implementented by 3 Classes .
1) InMemoryAuthorizationCodeServices
2) JdbcAuthorizationCodeServices
3) RandomValueAuthorizationCodeServices
Default Implementation of Spring provides the InMemoryAuthorizationCodeServices. I want to configure it based on the JdbcAuthorizationCodeServices. Now, for that do I need to write my own endpoint and code or could it be done using any configuration?

Implement multi-tenanted application with Keycloak and springboot

When we use 'KeycloakSpringBootConfigResolver' for reading the keycloak configuration from Spring Boot properties file instead of keycloak.json.
Now there are guidelines to implement a multi-tenant application using keycloak by overriding 'KeycloakConfigResolver' as specified in http://www.keycloak.org/docs/2.3/securing_apps_guide/topics/oidc/java/multi-tenancy.html.
The steps defined here can only be used with keycloak.json.
How can we adapt this to a Spring Boot application such that keycloak properties are read from the Spring Boot properties file and multi-tenancy is achieved.
You can access the keycloak config you secified in your application.yaml (or application.properties) if you inject org.keycloak.representations.adapters.config.AdapterConfig into your component.
#Component
public class MyKeycloakConfigResolver implements KeycloakConfigResolver {
private final AdapterConfig keycloakConfig;
public MyKeycloakConfigResolver(org.keycloak.representations.adapters.config.AdapterConfig keycloakConfig) {
this.keycloakConfig = keycloakConfig;
}
#Override
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
// make a defensive copy before changing the config
AdapterConfig currentConfig = new AdapterConfig();
BeanUtils.copyProperties(keycloakConfig, currentConfig);
// changes stuff here for example compute the realm
return KeycloakDeploymentBuilder.build(currentConfig);
}
}
After several trials, the only feasible option for spring boot is to have
Multiple instances of the spring boot application running with different spring 'profiles'.
Each application instance can have its own keycloak properties (as it is under different profiles) including the realm.
The challenge is to have an upgrade path for all instances for version upgrades/bug fixes, but I guess there are multiple strategies already implemented (not part of this discussion)
there is a ticket regarding this problem: https://issues.jboss.org/browse/KEYCLOAK-4139?_sscc=t
Comments for that ticket also talk about possible workarounds intervening in servlet setup of the service used (Tomcat/Undertow/Jetty), which you could try.
Note that the documentation you linked in your first comment is super outdated!

How to use Apache Shiro for authorization only?

Before I explain the issue I should say that we only need Apache Shiro for authorization and athentication is already enabled with OAuth2.
So my code to enable Shiro is exactly as the code in this link here.
I have also checked this issue. But for me if I enable LifecycleBeanPostProcessor almost most beans will be null. I made that create method in config class static as it suggests in the second link but no luck.
So my question is, is there any way to only enable authorization without registering shiro filter? If not, how to get around this issue? Because it seems ShiroFilterFactoryBean requires LifecycleBeanPostProcessor and that breaks the whole application.
We are using latest version of Spring Boot and Shiro 1.2.4
As outlined in an issue in the comments, you would need to set an already authenticated identity in the subject, which can be done with the Subject.Builder() (I'm using version 1.5.2 here).
Subject user = new Subject.Builder()
.principals(new SimplePrincipalCollection("bud", "myRealm"))
.authenticated(true)
.buildSubject();
if (user.hasRole("admin")) {
// do some authorized stuff
}
When implementing a custom realm the authentication ability can be disabled by returning false from the Realm’s supports method as described here .

Injecting springSecurityService into Controller with Grails 3.0.3

I am trying to get current user inside a controller in a Grails 3.0.3 application.
I have used this repo as a base for my security setup - security is GORM based. I am using following line in build.gradle in order to include Spring Security Framework:
compile "org.springframework.boot:spring-boot-starter-security"
but when I try to inject springSecurityService like it was recommended in other SO threads (see for example: this one) in my controller, I get only a null object. It is not initiated like it should be.
class RestapiController {
def springSecurityService
def currentUser(){
def user = springSecurityService.currentUser
render user
}
}
How can I inject springSecurityService into a controller in Grails 3.0.3?
UPDATE:
In the end I used following line to get the current user:
SecurityContextHolder.context.authentication.name
springSecurityService isn't part of Spring Security, it's in the Grails spring-security-core plugin. Spring Security doesn't have the concept of the "current user". You can access the current Authentication and get the username, password, enabled, etc., but there's nothing in the framework that gets you back to the source object that was used to populate the authentication (in Grails + spring-security-core this is often a User domain class instance) - that would have to be done in your application code.
This weekend I released an initial version of the plugin that works with Grails 3, version 3.0.0.M1. The documentation is here. There's a short tutorial in the docs to help get you started, and you might also check out this sample app using the plugin in Grails 3.

Resources