Vandaag gaan we onder de motorkap van Keycloak kijken en ons verdiepen in aangepaste mappings, extensies en integraties. Maak je klaar, want dit wordt een wilde rit!

TL;DR

We duiken diep in de aanpassing van Keycloak en behandelen:

  • Aangepaste gebruikersattribuut mappings
  • Het bouwen van Keycloak extensies (SPIs)
  • Het implementeren van aangepaste authenticatiestromen
  • Integratie met externe systemen

Als je klaar bent om van Keycloak je persoonlijke auth-speeltuin te maken, lees dan verder!

Aangepaste Gebruikersattribuut Mappings: Omdat Eén Maat Niet Voor Iedereen Geschikt Is

Laten we eerlijk zijn, de standaard gebruikersattributen in Keycloak zijn ongeveer zo spannend als vanille-ijs. Maar wees gerust! We kunnen het opfleuren met aangepaste attribuut mappings.

Aangepaste Attributen Toevoegen

Laten we eerst een aangepast attribuut aan onze gebruikers toevoegen. In de Keycloak beheerdersconsole:

  1. Ga naar Gebruikers > Attributen
  2. Voeg een nieuw attribuut toe, bijvoorbeeld "favoriteProgLanguage"

Nu gaan we dit toewijzen aan een claim in het JWT-token. Ga naar Clients > [Jouw Client] > Client Scopes > Dedicated scope > Mapper toevoegen > Door Configuratie > Gebruikersattribuut.

Vul de details in:

  • Naam: Favoriete Programmeertaal
  • Gebruikersattribuut: favoriteProgLanguage
  • Token Claim Naam: fav_lang

Voilà! Nu, wanneer een gebruiker inlogt, zal hun JWT hun favoriete programmeertaal bevatten. Want waarom niet?

Aangepaste Protocol Mapper

Maar wacht, er is meer! Wat als we wat fancy verwerking op onze attributen willen doen voordat ze het token bereiken? Maak kennis met aangepaste protocol mappers.

Laten we een mapper maken die onze favoriete taal omzet naar hoofdletters (omdat schreeuwen over onze liefde voor Python volkomen normaal is).


public class UppercaseLanguageMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {

    public static final String PROVIDER_ID = "uppercase-language-mapper";

    @Override
    public String getDisplayCategory() {
        return TOKEN_MAPPER_CATEGORY;
    }

    @Override
    public String getDisplayType() {
        return "Uppercase Language Mapper";
    }

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

    @Override
    protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
        UserModel user = userSession.getUser();
        String favLang = user.getFirstAttribute("favoriteProgLanguage");
        if (favLang != null) {
            token.getOtherClaims().put("FAV_LANG", favLang.toUpperCase());
        }
    }
}

Dat noem ik pas een aangepaste mapping! Je favoriete taal zal van de daken geschreeuwd worden (of in ieder geval vanuit je JWT).

Keycloak Extensies: Omdat Je Soms de Regels Moet Breken

De uitbreidbaarheid van Keycloak is als een speeltuin voor auth-nerds. Laten we een eenvoudige SPI (Service Provider Interface) bouwen die een aangepaste actie toevoegt aan de authenticatiestroom.

Een Aangepaste Authenticator Maken

Stel je voor dat we een authenticator willen toevoegen die controleert of het wachtwoord van de gebruiker hun gebruikersnaam bevat (een beveiligingsfout). Hier is een vereenvoudigde versie:


public class UsernamePasswordValidator implements Authenticator {

    @Override
    public void authenticate(AuthenticationFlowContext context) {
        UserModel user = context.getUser();
        CredentialInput input = context.getHttpRequest().getDecodedFormParameters().getFirst(CredentialForm.PASSWORD);
        
        if (input.getValue().contains(user.getUsername())) {
            context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, 
                context.form().setError("passwordContainsUsername").createErrorPage());
            return;
        }
        
        context.success();
    }

    // ... andere vereiste methoden
}

Nu moet je deze authenticator registreren bij Keycloak en toevoegen aan je authenticatiestroom. Je gebruikers zullen je later bedanken (of je nu vervloeken, dat is een gok).

Aangepaste Authenticatielogica: Omdat Je Soms Een Speciale Sneeuwvlok Moet Zijn

Stel dat je bedrijf een supergeheime authenticatiemethode heeft met een magische 8-bal en een kop koffie. Wees gerust, Keycloak heeft je gedekt!

Een Aangepaste Authenticatiestroom Implementeren

Hier is een voorproefje van hoe een aangepaste authenticatiestroom eruit zou kunnen zien:


public class CoffeeAuthenticator implements Authenticator {

    @Override
    public void authenticate(AuthenticationFlowContext context) {
        if (isCoffeeBrewed() && magicBallSaysYes()) {
            context.success();
        } else {
            context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, 
                context.form().setError("needMoreCoffee").createErrorPage());
        }
    }

    private boolean isCoffeeBrewed() {
        // Implementeer je koffie-controlelogica hier
        return true;  // Optimisten, verenigt u!
    }

    private boolean magicBallSaysYes() {
        // Raadpleeg de magische 8-bal
        return Math.random() > 0.5;  // 50/50 kans, lijkt legitiem
    }

    // ... andere vereiste methoden
}

Onthoud, met grote macht komt grote verantwoordelijkheid. Gebruik deze kennis verstandig, anders eindig je met een authenticatiesysteem dat alleen werkt voordat de koffie op is.

Integreren met Externe Systemen: Goed Samenwerken met Anderen

Keycloak hoeft geen eenzame wolf te zijn. Laten we eens kijken hoe we het goed kunnen laten samenwerken met externe systemen.

Aangepaste Gebruikersopslagprovider

Stel je voor dat je gebruikersgegevens hebt opgeslagen in een legacy-systeem dat ponskaarten gebruikt (omdat waarom niet?). Hier is een vereenvoudigd voorbeeld van hoe je dat met Keycloak zou kunnen integreren:


public class PunchCardUserStorageProvider implements UserStorageProvider, UserLookupProvider, CredentialInputValidator {

    private PunchCardSystem punchCardSystem;

    @Override
    public UserModel getUserByUsername(String username, RealmModel realm) {
        PunchCardUser punchCardUser = punchCardSystem.findUserByHoles(username);
        if (punchCardUser != null) {
            return new UserAdapter(session, realm, model, punchCardUser);
        }
        return null;
    }

    @Override
    public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
        if (!supportsCredentialType(input.getType())) return false;

        return punchCardSystem.validateCard(user.getUsername(), input.getChallengeResponse());
    }

    // ... andere vereiste methoden
}

Nu kan je vintage ponskaartsysteem gebruikers authenticeren in Keycloak. Welkom in de 21e eeuw... soort van.

De Conclusie: Keycloak is Jouw Oester

We hebben slechts het oppervlak bekrast van wat mogelijk is met Keycloak-aanpassing. Van het aanpassen van gebruikersattributen tot het bouwen van volledige authenticatieproviders, Keycloak biedt een robuust platform om je auth-systeem naar wens aan te passen.

Onthoud, met grote macht komt grote verantwoordelijkheid (en mogelijk grote hoofdpijn). Test grondig, documenteer religieus, en moge de auth-goden je gunstig gezind zijn.

Belangrijkste Leerpunten:

  • Aangepaste attribuut mappings geven flair aan je tokens
  • SPIs openen een wereld van uitbreidbaarheid
  • Aangepaste authenticatiestromen maken unieke (en mogelijk cafeïnehoudende) auth-logica mogelijk
  • Integratie met externe systemen is mogelijk, zelfs voor de meest verouderde systemen

Ga nu op pad en pas aan! En onthoud, als iemand vraagt waarom je een week hebt besteed aan het implementeren van een koffie-gebaseerd authenticatiesysteem, zeg dan gewoon dat het voor "verbeterde beveiliging" is. Ze zullen het helemaal geloven.

"De enige manier om geweldig werk te doen, is door te houden van wat je doet." - Steve Jobs

(Hij had het waarschijnlijk niet over Keycloak-aanpassing, maar we kunnen doen alsof.)

Veel programmeerplezier, en moge je tokens altijd geldig zijn en je koffie altijd sterk!