Compare commits

..

7 commits

Author SHA1 Message Date
149d98f90e Flag default-to-user-email
All checks were successful
/ Test (push) Successful in 56s
/ Test (pull_request) Successful in 48s
When set for an export config, if the user doesn't have that attribute, their email will be substituted as a default. If any of the values is not a valid email address, they are filtered out.

Closes #29
2026-07-18 19:59:39 +02:00
1c2adb1a92 Add running tests
All checks were successful
/ Test (push) Successful in 52s
/ Test (pull_request) Successful in 54s
2026-07-18 18:28:05 +02:00
cd31ec8a20 Refactor and cleanup
* simplify AttributeEndpointsResourceProvider
* improve explanation of properties in AdminUiPage
* add example for mailing lists and map endpoint
* better explain configuration and operation of provider in main readme
* adjust the Keycloak realm
* Add unit test for endpoint class
2026-07-18 18:17:21 +02:00
a540e63bf3 Finish merge 2026-07-18 15:25:13 +02:00
9073ef086a Merge branch 'main' into add-map-endpoint
Some checks failed
/ Verify (pull_request) Failing after 39s
/ Verify (push) Failing after 40s
2026-07-18 14:20:22 +02:00
464c02dfb0 Add returning attributes split by name
All checks were successful
/ Verify (push) Successful in 44s
/ Verify (pull_request) Successful in 48s
Adds an endpoint that returns the list of attribute values as a map of attribute names in the requested attribute group.

This is useful for requesting the mailing list addresses, where the individual attributes apply to different mailing lists.
2026-07-12 19:20:03 +02:00
2c3c0a3dab Fix matchRole lookup to include group-inherited and composite roles
All checks were successful
/ Verify (push) Successful in 1m8s
/ Verify (pull_request) Successful in 46s
getRoleMembersStream only returns users with the role assigned
directly, so exported attributes silently excluded users who have
matchRole via group membership. Filter all realm users with
hasRole() instead, matching the resolution already used for authRole.
2026-07-12 13:07:16 +02:00
5 changed files with 27 additions and 27 deletions

View file

@ -1,12 +1,10 @@
on:
pull_request:
push:
branches:
- main
jobs:
ansible-lint:
name: Verify
test:
name: Test
runs-on: docker
steps:
- uses: actions/checkout@v7
@ -14,6 +12,6 @@ jobs:
run: |
apt update
apt install -y maven
- name: Run maven verify
- name: Run maven verify test
run: |
mvn -f attribute-endpoints-provider --batch-mode --no-transfer-progress verify
mvn -f attribute-endpoints-provider verify test

View file

@ -1,7 +1,7 @@
# Attribute Endpoints Provider - Export User Attributes
This is a Keycloak Provider that exports user profile attribute values.
The selection of attributes and authorization is managed through an endpoint configuration in the Keycloak admin website.
The selection of attributes and authorization is manage through an endpoint configuration.
## Usage
@ -43,7 +43,7 @@ Once all dependencies are met, simply call `make` to build the provider, which s
There's also `make clean` available for removing the output directory.
To add the provider to your Keycloak install, copy `attribute-endpoints-provider/target/attribute-endpoints-provider-1.0-SNAPSHOT.jar` to the Keycloak Provider directory (`/opt/keycloak/providers/`).
To add the provider to your Keycloak install, copy `attribute-endpoints-provider/target/attribute-endpoints-provider-1.0-SNAPSHOT.jar` to the Keycloak Provider directory (`/opt/keycloak/providers/).
## Testing Setup

View file

@ -128,7 +128,6 @@ public class AdminUiPage implements UiPageProvider, UiPageProviderFactory<Compon
.add()
.property()
// keep old name for backwards compatibility
.name("attribute-group")
.label("Attribute Name or Group")
.helpText("The attribute or attribute group to export.")

View file

@ -1,35 +1,36 @@
package de.ccc.hamburg.keycloak.attribute_endpoints;
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;
import com.google.auto.service.AutoService;
@AutoService(RealmResourceProviderFactory.class)
public class AttributeEndpointsResourceProviderFactory implements RealmResourceProviderFactory {
static final String PROVIDER_ID = "attribute-endpoints-provider";
@Override
public RealmResourceProvider create(KeycloakSession keycloakSession) {
return new AttributeEndpointsResourceProvider(keycloakSession);
}
public RealmResourceProvider create(KeycloakSession keycloakSession) {
return new AttributeEndpointsResourceProvider(keycloakSession);
}
@Override
public void init(Config.Scope config) {
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
}
@Override
public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
}
@Override
public void close() {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String getId() {
return PROVIDER_ID;
}
}

View file

@ -24,7 +24,9 @@ import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Stream;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;