Forums / SmartComponent Library - Developer Forum / Oauth2 / IAuthenticationService login challenge with username

Oauth2 / IAuthenticationService login challenge with username

8 posts, 0 answered
  1. Bronco Oostermeyer
    Bronco Oostermeyer avatar
    5 posts
    Registered:
    30 Jan 2019
    05 Feb
    Link to this post
    For a customer I'm busy creating an IAuthenticationService implementation (to Keycloak to be precise). The reason is that customer want to be able to login to the SmartComponent Library application with their windows credentials. Active Directory (AD) is the Authentication Provider in this case (in other words, Keycloak acts as facade for AD, Keycloak returns a JWT). This Login works. There's however one challenge. The AD username is not the same as the App's username. My idea was to store the App username as property in AD. Now, the IAuthenticationService:ValidateUser returns true, but I have to set the username somewhere to what AD returned (in a claim of the JWT).

    I have to set the Session:Username somewhere (in ValidateUser, but am afraid that it is overwritten later on by the framework).

    How to do this? 
  2. Mike Fechner
    Mike Fechner avatar
    263 posts
    Registered:
    14 Sep 2016
    05 Feb in reply to Bronco Oostermeyer
    Link to this post
    What is the user name send in the client principal? The AD's or the application's user name? 

    We need the application's user name somewhere. If the client principal's user name is not the application's user name, then you should be sending that as an additional attribute in the CP. And then you should be implementing your own RestServerSessionActivator service. As that's taking in our case the user name from the client-principal.
  3. Bronco Oostermeyer
    Bronco Oostermeyer avatar
    5 posts
    Registered:
    30 Jan 2019
    05 Feb in reply to Mike Fechner
    Link to this post
    I didn't follow the entire flow but I assume the CP comes into play *after* successful login. 
    For the record, my custom ValidateUser looks like:

        METHOD PUBLIC LOGICAL ValidateUser(credentials AS IUserCredentials):
            
            DEFINE VARIABLE authenticator AS KeycloakAuthenticator NO-UNDO.
            DEFINE VARIABLE response AS AuthenticationReponse NO-UNDO.
            DEFINE VARIABLE username AS CHARACTER NO-UNDO.
            
            authenticator = NEW KeycloakAuthenticator().
            response = authenticator:DirectGrantLogin(credentials:UserName, credentials:Password).
            
            username = response:JWT:GetClaim('exspect_username').
            // SessionManager:UserName = username.   would be nice
            
            RETURN response:Authenticated.

        END METHOD.

    code is not complete yet, but the username variable has application's username, credentials the AD username. Now, since ValidateUser just returns true (or false) I don't quite know what to do with username (i.e. the application username). 
  4. Mike Fechner
    Mike Fechner avatar
    263 posts
    Registered:
    14 Sep 2016
    05 Feb in reply to Bronco Oostermeyer
    Link to this post
    Correct the client-principal is available only after successful login. 

    In PASOE hybrid realm implementations, the login request is not yet part of the later authenticated session (could also be done on a different PASOE, aka OE authentication gateway).

    Hence, we need all information in the client-principal. And that'll be processed in the RestServerSessionAuthenticator implementation. 
  5. Bronco Oostermeyer
    Bronco Oostermeyer avatar
    5 posts
    Registered:
    30 Jan 2019
    05 Feb in reply to Mike Fechner
    Link to this post
    OK, let me rephrase. How do I get the application username in the CP in this case? I have it available at the end of ValidateUser, but then what?
  6. Mike Fechner
    Mike Fechner avatar
    263 posts
    Registered:
    14 Sep 2016
    05 Feb in reply to Bronco Oostermeyer
    Link to this post
    IMHO that must happen within keycloak. The Hybrid realm does not create the CP on the ABL side. The ABL IHybridRealm implementation does not have access to the CP in either read or write mode. 

    And then later (with the first real request) the CP is already sealed. 

    In between is magic in the spring framework. 

    When we're using the securable product for authentication, that product has be capability of mapping the user credentials user for authentication to an entity name which is the user name in the CP.
  7. Bronco Oostermeyer
    Bronco Oostermeyer avatar
    5 posts
    Registered:
    30 Jan 2019
    05 Feb in reply to Mike Fechner
    Link to this post
    Well, this is the fat client talking to a apsv pasoe with:

    http.all.authmanager=local
    client.login.model=anonymous

    so imho the CP stuff is happening in SCL somewhere.
    SessionManager:Login(poUserCredentials AS IUserCredentials) is my suspect.

  8. Bronco Oostermeyer
    Bronco Oostermeyer avatar
    5 posts
    Registered:
    30 Jan 2019
    05 Feb in reply to Bronco Oostermeyer
    Link to this post
    Turned out to be (much) simpler than I expected, after a successful login you can rewrite the username of the credentials object:
        METHOD PUBLIC LOGICAL ValidateUser(credentials AS IUserCredentials):
            
            DEFINE VARIABLE authenticator AS KeycloakAuthenticator NO-UNDO.
            DEFINE VARIABLE response AS AuthenticationReponse NO-UNDO.
            DEFINE VARIABLE username AS CHARACTER NO-UNDO.

            authenticator = NEW KeycloakAuthenticator().
            response = authenticator:DirectGrantLogin(credentials:UserName, credentials:Password).
            
            username = response:JWT:GetClaim('exspect_username').
            credentials:UserName = username.
            
            RETURN response:Authenticated.

        END METHOD.

8 posts, 0 answered