Listings Reinhardt/Keycloak

Listing 1: Metadatendokument (Beispiel)
{
    "authorization_endpoint": "https://my-login-server/{tenant}/oauth2/authorize",
    "token_endpoint": "https://my-login-server/{tenant}/oauth2/token",
    "token_endpoint_auth_methods_supported":
    [
      "client_secret_post",
      "private_key_jwt",
      "client_secret_basic"
    ],
    "jwks_uri": "https://my-login-server/common/discovery/keys",
    "userinfo_endpoint":"https://my-login-server/{tenant}/openid/userinfo",
    ...
}

-----

Listing 2: OIDC-Claims
{
"family_name": "Alice",
"given_name": "Bob",
"locale": "en-US",
"name": "Bob Alice",
"preferred_username": "bob.alice@sample.com",
"sub": "00a1ike72nxulvxva1s1",
"updated_at": 1490198843,
"zoneinfo": "America/Los_Angeles"
}

-----

Listing 3: docker-compose.yml
keycloak: container_name: keycloak
    image: jboss/keycloak:10.0.1
    depends_on:
      - mysql
    ports:
      - '8888:8080'
    links:
      - mysql
      - maildev
    volumes:
      - ./dist/holisticon/:/opt/jboss/keycloak/themes/holisticon/

-----

Listing 4: pom.xml
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-core</artifactId>
    <version>${keycloak.version}</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-server-spi</artifactId>
    <version>${keycloak.version}</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-server-spi-private</artifactId>
    <version>${keycloak.version}</version>
    <scope>provided</scope>
</dependency>

-----

Listing 5: CustomStorageProviderFactory
import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.storage.UserStorageProviderFactory;
public class CustomStorageProviderFactory implements UserStorageProviderFactory<CustomStorageProvider> {
    static final String PROVIDER_NAME = "CustomDemoProvider";

    @Override
    public CustomStorageProvider create(KeycloakSession keycloakSession, ComponentModel componentModel) {
      return new CustomStorageProvider(keycloakSession, componentModel, new UserRepository());
    }

    @Override
    public String getId() {
      return PROVIDER_NAME;
    }
}

-----

Listing 6: CustomStorageProvider
import org.jboss.logging.Logger;
import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialInput;
import org.keycloak.credential.CredentialInputUpdater;
import org.keycloak.credential.CredentialInputValidator;
import org.keycloak.credential.CredentialModel;
import org.keycloak.models.*;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.user.UserLookupProvider;
import org.keycloak.storage.user.UserQueryProvider;
class CustomStorageProvider implements UserStorageProvider,
    UserLookupProvider, UserQueryProvider, CredentialInputUpdater, CredentialInputValidator {

    private final KeycloakSession session;
    private final ComponentModel model;
    private final UserRepository repository;

    private static final Logger logger = Logger.getLogger(CustomStorageProvider.class);

    public CustomStorageProvider(KeycloakSession session, ComponentModel model, UserRepository repository) {
      this.session = session;
      this.model = model;
      this.repository = repository;
    }
    @Override
    public UserModel getUserById(String id, RealmModel realm) {
      logger.debugv("lookup user by id: realm={0} userId={1}", realm.getId(), id);
      String externalId = StorageId.externalId(id);
      return new UserAdapter(session, realm, model, repository.findUserById(externalId));
    }

    @Override
    public UserModel getUserByUsername(String username, RealmModel realm) {
      logger.debugv("lookup user by username: realm={0} username={1}", realm.getId(), username);
      return new UserAdapter(session, realm, model, repository.findUserByUsernameOrEmail(username));
    }
}