[keycloak-dev] Integration with GuardianKey

Alexis Almeida alexis.almeida at gmail.com
Tue Feb 19 00:31:26 EST 2019


Hi Paulo!

I had this same problem and to solve it I did this:

private AuthenticatorConfigModel getConfig(KeycloakSession session,
String providerId) {
    logger.info("Getting config for: " + providerId);
    AuthenticatorConfigModel configModel = null;

    RealmModel realm = session.getContext().getRealm();
    String flowId = realm.getBrowserFlow().getId();

    return getConfig(realm, flowId, providerId);

}

private AuthenticatorConfigModel getConfig(RealmModel realm, String
flowId, String providerId) {
    logger.info("Getting config for: " + flowId);

    AuthenticatorConfigModel configModel = null;

    List<AuthenticationExecutionModel> laem =
realm.getAuthenticationExecutions(flowId);

    for (AuthenticationExecutionModel aem : laem) {
        logger.info("aem: " + String.format("%s, %s, %s, %s",
aem.getFlowId(), aem.getId(),
                aem.isEnabled(),aem.isAuthenticatorFlow()));
        if (aem.isAuthenticatorFlow()) {
            logger.info("flow: " + aem.getFlowId());
            configModel = getConfig(realm, aem.getFlowId(), providerId);
            if (configModel!= null) return configModel;
        } else if (aem.getAuthenticator() != null &&
aem.getAuthenticator().equals(providerId)) {
            logger.info("authenticator: " + aem.getAuthenticator());
            configModel =
realm.getAuthenticatorConfigById(aem.getAuthenticatorConfig());
            break;
        }
    }
    return configModel;
}

Best regards

Alexis


Em dom, 17 de fev de 2019 às 22:11, Paulo Angelo <pa at pauloangelo.com>
escreveu:

> Thank you Thomas and Alexis!
>
> Another question: In the method "onEvent" of an EventListener, how could I
> get the configuration for one specific Authenticator?
>
> When the Authenticator is triggered (authenticate method), I can access
> its config using:
>
>     Map<String,String> config =
> context.getAuthenticatorConfig().getConfig();
>
> However, the context is not directly available (as expected) when the
> "EventListener.onEvent" is triggered.
>
> I could see in the documentation [1] that, inside the EventListener, I can
> have access to a KeycloakSession and a KeycloakSessionFactory. But I could
> not find the path for one specific Authenticator config. I also saw in docs
> that it is possible to save the configuration for the EventListener, but
> the attributes are the same used in the Authenticator.
>
> Is it possible to retrieve the configuration of a specific Authenticator
> in the flow used by the "event"?
>
> Thank you in advance,
>
> Paulo Angelo
>
> [1]
> https://www.keycloak.org/docs/3.3/server_development/topics/providers.html
>
>
>
> On Sun, Feb 17, 2019 at 6:25 PM Alexis Almeida <alexis.almeida at gmail.com>
> wrote:
>
>> Hi Paulo!
>>
>> In addition to Thomas suggestion, I usually capture the remote IP like
>> this:
>>
>> String ip = context.getSession (). GetContext (). GetConnection ().
>> GetRemoteAddr ();
>>
>> About login status, I think you must to change your approach to get
>> failure
>> login.
>>
>> In the authentication flow, if you put your authenticator provider before
>> "user and password" form this wil not work, because the user is not
>> authenticated yet.
>> If you put it after "user and passwrd" form, you'll only catch success
>> logins.
>>
>> So I think you could implement the EventListener class to get any event
>> type:
>>
>> public class RealmTeste implements EventListenerProvider, Authenticator {
>> ...
>>     public void onEvent(Event event) {
>>         String ip = event.getIpAddress();
>>         if (event.getType().equals("LOGIN_ERROR")) {
>>
>>         }
>>     }
>>     public void onEvent(AdminEvent event, boolean includeRepresentation) {
>>     }
>> ...
>>
>> Regards
>>
>> Aléxis
>>
>>
>> Em dom, 17 de fev de 2019 às 17:45, Thomas Darimont <
>> thomas.darimont at googlemail.com> escreveu:
>>
>> > Hello Paulo,
>> >
>> > in order to get the remote IP address of the request you could either
>> use
>> > the information from "ClientConnection" or look manually in the current
>> > HttpServletRequest,
>> > or HTTP-Headers. This structures can be obtained from the
>> > "ResteasyProviderFactory".
>> >
>> >         // See ResteasyProviderFactory.getContextDataMap() for what's
>> > available.
>> >
>> >         ClientConnection clientConnection =
>> > ResteasyProviderFactory.getContextData(ClientConnection.class);
>> >         clientConnection.getRemoteAddr();
>> >
>> >         HttpServletRequest request =
>> > ResteasyProviderFactory.getContextData(HttpServletRequest.class);
>> >
>> > Cheers,
>> > Thomas
>> >
>> > Am So., 17. Feb. 2019 um 19:47 Uhr schrieb Paulo Angelo <
>> > pa at pauloangelo.com>:
>> >
>> >> Hi All,
>> >>
>> >> The GuardianKey extension for KeyCloak is almost complete! Thank you
>> for
>> >> the given directions.
>> >>
>> >> We have to get the user client IP and the status of the authentication
>> >> attempt (failed/success). For this, we implemented the code below.
>> >> However,
>> >> we are facing Null Pointer exceptions.
>> >>
>> >> public class GuardianKeyAuthenticator implements Authenticator {  //
>> ...
>> >> public void authenticate(AuthenticationFlowContext context) {  // ...
>> >>          // *Trying to get the Client IP address*
>> >>            clientIP =
>> >>
>> >>
>> context.getSession().sessions().getUserSession(context.getAuthenticationSession().getClient().getRealm(),
>> >>
>> >> context.getAuthenticationSession().getClient().getId())
>> >>                                                      .getIpAddress();
>> /*
>> >> getting null pointer exception */
>> >>           // *Trying to get the status for the auth attempt
>> >> (failed/success), this Authenticator should be the last in the flow*
>> >>              failed = context.getStatus().equals(FlowStatus.SUCCESS);
>> /*
>> >> getting null pointer exception */
>> >>        // ...
>> >> } }
>> >>
>> >> Any clue about how we can do this?
>> >>
>> >> Thank you in advance.
>> >>
>> >> Paulo Angelo
>> >>
>> >>
>> >> On Sun, Feb 3, 2019 at 10:21 PM Paulo Angelo <pa at pauloangelo.com>
>> wrote:
>> >>
>> >> > Dmitry and Aléxis,
>> >> >
>> >> > Thank you very much for the directions. We are going to work on it.
>> >> >
>> >> > regards,
>> >> >
>> >> > Paulo Angelo
>> >> >
>> >> > On Sun, Feb 3, 2019 at 8:06 PM Dmitry Telegin <dt at acutus.pro> wrote:
>> >> >
>> >> >> Hello Paulo,
>> >> >>
>> >> >> To add to Alexis's reply, you can use Script authenticator [1]. It's
>> >> >> especially good for prototyping since you don't have to create and
>> >> deploy
>> >> >> the whole provider module.
>> >> >>
>> >> >> Also, you'll need an HttpClient instance to be able to perform
>> external
>> >> >> HTTP requests, see [2] for that.
>> >> >>
>> >> >> [1] https://www.keycloak.org/docs/latest/server_admin/#executions
>> >> >> [2]
>> >> >>
>> >>
>> http://lists.jboss.org/pipermail/keycloak-user/2018-November/016456.html
>> >> >>
>> >> >> Good luck,
>> >> >> Dmitry Telegin
>> >> >> CTO, Acutus s.r.o.
>> >> >> Keycloak Consulting and Training
>> >> >>
>> >> >> Pod lipami street 339/52, 130 00 Prague 3, Czech Republic
>> >> >> +42 (022) 888-30-71
>> >> >> E-mail: info at acutus.pro
>> >> >>
>> >> >> On Sun, 2019-02-03 at 17:46 -0200, Alexis Almeida wrote:
>> >> >> > Hi Paulo,
>> >> >> >
>> >> >> > IMO the simplest way to do this is with an Authenticator Provider.
>> >> >> Please
>> >> >> > see here:
>> >> >> >
>> >> >> >
>> >> >>
>> >>
>> https://www.keycloak.org/docs/latest/server_development/index.html#implementing-an-authenticator
>> >> >> > .
>> >> >> >
>> >> >> > In the authenticate method you can call the GuardianKey and,
>> >> depending
>> >> >> on
>> >> >> > the result, you call a context.success () or context.failure ().
>> >> >> >
>> >> >> > Like this:
>> >> >> >
>> >> >> > public void authenticate(AuthenticationFlowContext context) {
>> >> >> > ...
>> >> >> > if(!GuardianKeyValidation){
>> >> >> >    Response challenge = context.form()
>> >> >> >                 .setError("something")
>> >> >> >                 .createForm("error_page.ftl");
>> >> >> >
>> >> >> >
>> >> context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS,
>> >> >> > challenge);
>> >> >> >    return;
>> >> >> > }
>> >> >> > ...
>> >> >> > context.success();
>> >> >> > }
>> >> >> >
>> >> >> > Aléxis
>> >> >> >
>> >> >> >
>> >> >> > > Em dom, 3 de fev de 2019 às 15:38, Paulo Angelo <
>> >> pa at pauloangelo.com>
>> >> >> > escreveu:
>> >> >> >
>> >> >> > > Hi all,
>> >> >> > >
>> >> >> > > We are trying to integrate KeyCloak with GuardianKey. However,
>> we
>> >> have
>> >> >> > > doubts related to the best way to do this and the best point in
>> the
>> >> >> > > KeyCloak’s code for this integration.
>> >> >> > >
>> >> >> > > GuardianKey is a service to protect systems against
>> authentication
>> >> >> attacks.
>> >> >> > > It uses Machine Learning and analyses the user's behavior,
>> threat
>> >> >> > > intelligence and psychometrics (or behavioral biometrics). The
>> >> >> protected
>> >> >> > > system (in the concrete case, KeyCloak) must send an event via
>> REST
>> >> >> for the
>> >> >> > > GuardianKey on each login attempt. More info at
>> >> >> https://guardiankey.io .
>> >> >> > >
>> >> >> > > The best way to integrate would be on having a hook in the
>> >> procedure
>> >> >> that
>> >> >> > > process the user credentials submission in KeyCloak (the script
>> >> that
>> >> >> > > receives the POST), something such as:
>> >> >> > >
>> >> >> > > if(<POST IN AUTH FORM>) {
>> >> >> > >
>> >> >> > >  boolean loginFailed =  checkLoginInKeyCloak();
>> >> >> > >
>> >> >> > >  GuardianKeyEvent event =
>> >> >> createEventForGuardianKey(username,loginFailed);
>> >> >> > >
>> >> >> > >  boolean GuardianKeyValidation = checkGuardianKeyViaREST(event);
>> >> >> > >
>> >> >> > >  if(GuardianKeyValidation){
>> >> >> > >
>> >> >> > >     // Allow access
>> >> >> > >
>> >> >> > >  } else {
>> >> >> > >
>> >> >> > >     // Deny access
>> >> >> > >
>> >> >> > >  }
>> >> >> > >
>> >> >> > > }
>> >> >> > >
>> >> >> > > Where is the best place to create this integration? Is there a
>> way
>> >> to
>> >> >> > > create a hook for this purpose? Should we create an extension?
>> >> >> > >
>> >> >> > > Any help is welcome.
>> >> >> > >
>> >> >> > > Thank you in advance.
>> >> >> > >
>> >> >> > > Best regards,
>> >> >> > >
>> >> >> > > Paulo Angelo
>> >> >> > > _______________________________________________
>> >> >> > > keycloak-dev mailing list
>> >> >> > > keycloak-dev at lists.jboss.org
>> >> >> > > https://lists.jboss.org/mailman/listinfo/keycloak-dev
>> >> >> >
>> >> >> > _______________________________________________
>> >> >> > keycloak-dev mailing list
>> >> >> > keycloak-dev at lists.jboss.org
>> >> >> > https://lists.jboss.org/mailman/listinfo/keycloak-dev
>> >> >> _______________________________________________
>> >> >> keycloak-dev mailing list
>> >> >> keycloak-dev at lists.jboss.org
>> >> >> https://lists.jboss.org/mailman/listinfo/keycloak-dev
>> >> >
>> >> >
>> >> >
>> >> > --
>> >> >
>> >> > Att,
>> >> >
>> >> > Paulo Angelo
>> >> >
>> >>
>> >>
>> >> --
>> >>
>> >> Att,
>> >>
>> >> Paulo Angelo
>> >> _______________________________________________
>> >> keycloak-dev mailing list
>> >> keycloak-dev at lists.jboss.org
>> >> https://lists.jboss.org/mailman/listinfo/keycloak-dev
>> >
>> >
>> _______________________________________________
>> keycloak-dev mailing list
>> keycloak-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/keycloak-dev
>
>
>
> --
>
> Att,
>
> Paulo Angelo
>


More information about the keycloak-dev mailing list