Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keycloak JavaScript API to get current logged in user

We plan to use keycloak to secure a bunch of web apps, some written in Java, some in JavaScript (with React).

After the user is logged in by keycloak, each of those web apps needs to retrieve the user that is logged in and the realm/client roles that the user has.

  • For Java apps, we tried the keycloak Java API (request -> KeycloakSecurityContext -> getIdToken -> getPreferredUsername/getOtherClaims). They seem to work fine
  • For JavaScript apps, we tried the following code, but could not get Keycloak to init successfully (Note this is in web app code after the user is already authenticated by keycloak, the app is only trying to retrieve who logged in with what roles):

    var kc = Keycloak({
        url: 'https://135.112.123.194:8666/auth',
        realm: 'oneRealm',
        clientId: 'main'
    }); 
    
    //this does not work as it can't find the keycloak.json file under WEB-INF
    //var kc = Keycloak('./keycloak.json'); 
    
    kc.init().success(function () {
        console.log("kc.idToken.preferred_username: " + kc.idToken.preferred_username);
        alert(JSON.stringify(kc.tokenParsed)); 
        var authenticatedUser = kc.idTokenParsed.name; 
        console.log(authenticatedUser);  
    }).error(function () {
        window.location.reload();
    });
    

I assume it would be fairly common that web apps need to retrieve current user info. Anyone knows why the above code didn't work?

Thanks.

like image 352
Alex Avatar asked Jul 10 '17 18:07

Alex


2 Answers

    <script src="http://localhost:8080/auth/js/keycloak.js" type="text/javascript"></script>
<script type="text/javascript">
const keycloak = Keycloak({
    "realm": "yourRealm",
    "auth-server-url": "http://localhost:8080/auth",
    "ssl-required": "external",
    "resource": "yourRealm/keep it default",
    "public-client": true,
    "confidential-port": 0,
    "url": 'http://localhost:8080/auth',
    "clientId": 'yourClientId',
    "enable-cors": true
});
const loadData = () => {
    console.log(keycloak.subject);
    if (keycloak.idToken) {
        document.location.href = "?user="+keycloak.idTokenParsed.preferred_username;
        console.log('IDToken');
        console.log(keycloak.idTokenParsed.preferred_username);
        console.log(keycloak.idTokenParsed.email);
        console.log(keycloak.idTokenParsed.name);
        console.log(keycloak.idTokenParsed.given_name);
        console.log(keycloak.idTokenParsed.family_name);
    } else {
        keycloak.loadUserProfile(function() {
            console.log('Account Service');
            console.log(keycloak.profile.username);
            console.log(keycloak.profile.email);
            console.log(keycloak.profile.firstName + ' ' + keycloak.profile.lastName);
            console.log(keycloak.profile.firstName);
            console.log(keycloak.profile.lastName);
        }, function() {
            console.log('Failed to retrieve user details. Please enable claims or account role');
        });
    }
};
const loadFailure =  () => {
     console.log('Failed to load data.  Check console log');
};
const reloadData = () => {
    keycloak.updateToken(10)
            .success(loadData)
            .error(() => {
                console.log('Failed to load data.  User is logged out.');
            });
}
keycloak.init({ onLoad: 'login-required' }).success(reloadData);
</script>

simple javascript client authentication no frameworks. for people who are still looking...

like image 200
Keshav Sharma Avatar answered Nov 05 '22 15:11

Keshav Sharma


Your code asks the Keycloak client library to initialize, but it doesn't perform a login of the user or a check if the user is already logged in.

Please see the manual for details: http://www.keycloak.org/docs/latest/securing_apps/index.html#_javascript_adapter

What your probably want to do:

  • Add check-sso to the init to check if the user is logged in and to retrieve the credentials keycloak.init({ onLoad: 'check-sso' ... }). You might even use login-required.

  • Make sure that you register a separate client for the front-end. While the Java backend client is of type confidential (or bearer only), the JavaScript client is of type public.

You find a very minimal example here: https://github.com/ahus1/keycloak-dropwizard-integration/blob/master/keycloak-dropwizard-bearer/src/main/resources/assets/ajax/app.js

Alternatively you can register a callback for onAuthSuccess to be notified once the user information has been retrieved.

Once you use Keycloak in the front-end, you will soon want to look in bearer tokens when calling REST resources in the backend.

like image 35
ahus1 Avatar answered Nov 05 '22 16:11

ahus1