Oidc-client-js: getUser() always return null

Created on 6 Mar 2017  路  12Comments  路  Source: IdentityModel/oidc-client-js

I'm trying to setup an angular 1 app using oidc-client-js to automatically check if a user is logged in or not.
When the user is not logged, the redirection works well, but when it comes back to the application, it ends up in an infinite loop because getUser() always return null.

Here the code I use on application load:

.run(['oidcManager', '$log', function (oidcManager, $log) {
      var userManager = oidcManager.userManager;

      Oidc.Log.logger = $log;
      Oidc.Log.level = Oidc.Log.INFO;

      userManager.getUser().then(function (user) {
        $log.debug('getUser returned', user);

        if (!user) {
          userManager.signinRedirect().then(function() {
            $log.debug("signinRedirect done");
          }).catch(function(err) {
            $log.debug(err);
          });
        } else {
          $log.debug('user', user);
        }
});

But on the logs, I always have

UserManager.getUser
_loadUser
WebStorageStateStore.get user:xxx
no user storageString
user not found in storage
getUser returned null
UserManager.signinRedirect

then logs corresponding to the logging process and then that comes back to getUser and doesn't find it.
When I look in the storage, I can see entries for user, but on the localStorage, not on the sessionStorage, even if I didn't set the userStore option on UserManager constructor.

Is there something wrong with getUser() method? or something wrong in the way I use the lib?

By the way, oidcManager is just a factory wrapping the UserManager like that:
```
angular.module('myApp')
.factory('oidcManager', function ($log) {

    var config = {
          authority: "http://myAuthority",
          client_id: "clientId",
          redirect_uri: "https://localhost:44309/",
          response_type: "id_token token",
          scope: "openid profile offline_access custom"
        },
        userManager = new Oidc.UserManager(config);

    userManager.events.addAccessTokenExpiring(function () {
      $log.debug("token expiring");
    });

    userManager.events.addAccessTokenExpired(function () {
      $log.debug("token expired");
    });

    userManager.events.addSilentRenewError(function (e) {
      $log.debug("silent renew error", e.message);
    });

    userManager.events.addUserLoaded(function (user) {
      $log.debug("user loaded", user);
      userManager.getUser().then(function () {
        $log.debug("getUser loaded user after userLoaded event fired");
      });
    });

    userManager.events.addUserUnloaded(function (e) {
      $log.debug("user unloaded");
    });

    return {
      userManager: userManager
    };
  });

```

question

Most helpful comment

You have to use both, the signinRedirect and the signinRedirectCallback. First you have to do something like that:

this.mgr.signinRedirect().then(function () {
      console.log('signinRedirect done');
    }).catch(function (err) {
      console.log(err);
    });

And when the IDS redirects to your Website, the token and some info is returned as fragment in the URL. You have to pass this fragment to the signinRedirectCallback method, like that:

this.mgr.signinRedirectCallback(url).then(function (loggedUser) { 
   ///// the logged user contains the user info
});

Now, the user is created in the user store and you can use getUser and all the provided functionality.

All 12 comments

userManager.getUser().then(function () {
          $log.debug("getUser loaded user after userLoaded event fired");
        });

should be:

userManager.getUser().then(function (user) {
     if (user) // user is logged in
     else // user is not logged 
});

Yes, it's what I have:

userManager.getUser().then(function (user) {
        $log.debug('getUser returned', user);

        if (!user) {
         //not logged
        } else {
          //logged
        }

and if I reverse the logic like that I have the same result:

      userManager.getUser().then(function (user) {
        if (user) {
          $log.debug('user', user);
        } else {
          userManager.signinRedirect().then(function() {
            $log.debug("signinRedirect done");
          }).catch(function(err) {
            $log.debug(err);
          });
        }
      });

So I think there something wrong with getUser(), because using signinRedirectCallback() that works:

      userManager.signinRedirectCallback().then(function (user) {
        $log.debug("signinRedirectCallback done", user);
      }).catch(function (err) {
        $log.error('error while signinRedirectCallback', err);

        userManager.signinRedirect().then(function() {
          $log.debug("signinRedirect done");
        }).catch(function (err) {
          $log.error('error while signinRedirect', err);
        });
      });

Not sure then, you will have to do some debugging.

we also have similar issue when getUser returns null, but didn't have enough time to investigate it

@mathilde-pellerin any update?

Sorry, I didn't have time to investigate neither. I use this workaround which is less clean than getUser() but works:

          signIn: function () {
            return $q(function (resolve, reject) {
              userManager.signinRedirectCallback().then(function () {
                resolve();
              }).catch(function (err) {
                $log.debug('User not logged', err);

                userManager.signinRedirect().then(function () {
                  $log.debug("signinRedirect done");
                  resolve();
                }).catch(function (err) {
                  reject();
                  $log.error('error while signinRedirect', err);
                });
              });
            });
          }

Encountering the same problem now. Will try to investigate more.
I get this error in the console 'user not found in storage'

You have to use both, the signinRedirect and the signinRedirectCallback. First you have to do something like that:

this.mgr.signinRedirect().then(function () {
      console.log('signinRedirect done');
    }).catch(function (err) {
      console.log(err);
    });

And when the IDS redirects to your Website, the token and some info is returned as fragment in the URL. You have to pass this fragment to the signinRedirectCallback method, like that:

this.mgr.signinRedirectCallback(url).then(function (loggedUser) { 
   ///// the logged user contains the user info
});

Now, the user is created in the user store and you can use getUser and all the provided functionality.

@franpsif thanks!
The part of putting the url here this.mgr.signinRedirectCallback(url) helped me move forward. :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tomeinar picture tomeinar  路  3Comments

primozs picture primozs  路  3Comments

pottabathini picture pottabathini  路  5Comments

iXmonvi33 picture iXmonvi33  路  4Comments

arnaldo-infinite picture arnaldo-infinite  路  4Comments