experimentation

This commit is contained in:
kritzl 2025-10-24 00:09:27 +02:00
commit 8c1d25133f
Signed by: kritzl
SSH key fingerprint: SHA256:5BmINP9VjZWaUk5Z+2CTut1KFhwLtd0ZynMekKbtViM
6 changed files with 163 additions and 18 deletions

View file

@ -1,11 +1,12 @@
services:
keycloak:
image: quay.io/keycloak/keycloak:latest
image: quay.io/keycloak/keycloak:26.4.2
pull_policy: always
command: start-dev
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
KC_LOG_LEVEL: info
ports:
- "8080:8080"
volumes:

View file

@ -15,9 +15,9 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<keycloak.version>26.4.0</keycloak.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<keycloak.version>26.4.2</keycloak.version>
</properties>
<dependencies>
@ -43,6 +43,11 @@
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
@ -108,4 +113,4 @@
</plugins>
</pluginManagement>
</build>
</project>
</project>

View file

@ -1,13 +0,0 @@
package de.ccc.hamburg.keycloak;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}

View file

@ -0,0 +1,52 @@
package de.ccc.hamburg.keycloak;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.NotAuthorizedException;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.Auth;
import org.keycloak.services.managers.AuthenticationManager;
import java.util.function.Function;
public class AuthHelper {
public static AuthenticationManager.AuthResult getAuthResult(KeycloakSession session, Function<AuthenticationManager.AuthResult, Boolean> authFn) {
AuthenticationManager.AuthResult auth = new AppAuthManager.BearerTokenAuthenticator(session).authenticate();
System.err.println(auth.getToken().getIssuedFor());
if (auth == null) {
throw new NotAuthorizedException("Bearer");
} else if (!authFn.apply(auth)) {
throw new ForbiddenException();
}
return auth;
}
public static Auth getAuth(KeycloakSession session, Function<AuthenticationManager.AuthResult, Boolean> authFn) {
return getAuth(session, getAuthResult(session, authFn));
}
public static Auth getAuth(KeycloakSession session, String clientId, Function<AuthenticationManager.AuthResult, Boolean> authFn) {
return getAuth(session, getAuthResult(session, authFn), clientId);
}
public static Auth getAuth(KeycloakSession session, AuthenticationManager.AuthResult authResult) {
return getAuth(session, authResult, null);
}
public static Auth getAuth(KeycloakSession session, AuthenticationManager.AuthResult authResult, String clientId) {
RealmModel realm = session.getContext().getRealm();
ClientModel client;
if (clientId == null) {
client = authResult.getClient();
} else {
client = realm.getClientByClientId(clientId);
}
return new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), false);
}
}

View file

@ -0,0 +1,60 @@
package de.ccc.hamburg.keycloak;
import java.util.Map;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.keycloak.models.KeycloakSession;
import org.keycloak.services.managers.Auth;
import org.keycloak.services.resource.RealmResourceProvider;
public class SSHKeyResourceProvider implements RealmResourceProvider {
private final KeycloakSession session;
public SSHKeyResourceProvider(KeycloakSession keycloakSession) {
this.session = keycloakSession;
}
@Override
public Object getResource() {
return this;
}
@Override
public void close() {
}
@GET
@Path("hello")
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Public hello endpoint", description = "This endpoint returns hello and the name of the requested realm.")
@APIResponse(responseCode = "200", description = "", content = {
@Content(schema = @Schema(implementation = Response.class, type = SchemaType.OBJECT)) })
public Response helloAnonymous() {
return Response.ok(Map.of("hello", session.getContext().getRealm().getName())).build();
}
@GET
@Path("hello-auth")
@Produces(MediaType.APPLICATION_JSON)
public Response helloAuthenticated() {
try {
Auth auth = AuthHelper.getAuth(session,
authResult -> authResult.getToken().getIssuedFor().equals("admin-cli"));
return Response.ok(Map.of("hello", auth.getUser().getUsername())).build();
} catch (Exception e) {
System.err.println(e);
return Response.status(401, e.getMessage()).build();
}
}
}

View file

@ -0,0 +1,40 @@
package de.ccc.hamburg.keycloak;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.services.resource.RealmResourceProvider;
import org.keycloak.services.resource.RealmResourceProviderFactory;
import org.keycloak.Config.Scope;
import com.google.auto.service.AutoService;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.services.resource.RealmResourceProvider;
import org.keycloak.services.resource.RealmResourceProviderFactory;
@AutoService(RealmResourceProviderFactory.class)
public class SSHKeyResourceProviderFactory implements RealmResourceProviderFactory {
static final String PROVIDER_ID = "ssh-key-provider";
@Override
public RealmResourceProvider create(KeycloakSession keycloakSession) {
return new SSHKeyResourceProvider(keycloakSession);
}
@Override
public void init(Config.Scope scope) {
}
@Override
public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_ID;
}
}