Oidc-client-js: How to call UserInfo Endpoint using oidc client ?

Created on 14 Sep 2016  路  15Comments  路  Source: IdentityModel/oidc-client-js

I have a requirement to call the UserInfo Endpoint to get the updated claims, how is this possible using oidc client, what is the method I can use to get the claims ?

question

All 15 comments

It does this automatically at signin time. You can always trigger a silent sign-in to trigger sign-in again in a hidden iframe.

Brock, thanks for your update.

I am using oidc client with Sitecore & Angular, for some reason (Sitecore has different routing technique), the implementation in 'user-manager-sample.js' was not working well.

Then I managed to setup and use the sample 'oidc-client-sample.js'.

If am not using the Oidc.UserManager is there any way we can refresh the user claims ?

I endup with 2 problem using this sample 'oidc-client-sample.js'.

  1. Not able to Refresh the User Claim after profile update
  2. Not able to identify the token timeout.

Can you please suggest a workaround, to make Oidc.OidcClient, renew the token & identify the token timeout.

Check the User properties for expiration, etc: https://github.com/IdentityModel/oidc-client-js/wiki#user

As for refreshing the claims from user info, the only way is to re-issue a signin call. If you just want to access user info directly, then you can call it yourself with the access_token from the User, but this won't update the User profile being managed by the UserManager.

Brok, Sorry to bother again, I am struck with this issue for a while...

I added the below 2 code to the 'oidc-client-sample.js', but when i call the getUser, then user is returned as null, is this right way to call getUser with access_token parameter ?

var mgr = new Oidc.UserManager(settings);

function getUser(accesstoken) {
mgr.getUser({access_token: accesstoken}).then(function(user) {
console.log("got user", user);
}).catch(function(err) {
console.log(err);
});
}

my log says

UserManager.getUser
_loadUser
WebStorageStateStore.get user:https://dev.secure.xxxx.com/core:js.tokenmanager
no user storageString
user not found in storage
got user null

The user needs to login first to get an access token and you need to be requesting "id_token token" if you want authentication and an access token.

All set? Can we close?

Thanks Brock, I managed to figure out the problem, why 'user-manager-sample.js' was not working with Sitecore + Angular Js.

After successful sign-in the response url will be like : http://oidc/user-manager-sample.html#id_token=eyJ0eXAiOiJKV1QiLCJhbGciOi...

But in my code I was getting response like : http://abc.app1.com/login#/id_token=eyJ0eXAiOiJKV1QiLCJhbGciOi...

An extra backslash (login#/id_token) before id_token was getting added to the url ( yet to figure-out whether it is by Sitecore Routing ) , so with UserManger able to call the function signinRedirect, but no other functions are working (like signinRedirectCallback or getUsers) none of the user manager events bind.

After enabling the logs and figured-out in

SigninResponse(url)
this.id_token = values.id_token; // id_token coming as null, when I see the array values , found there is no id_token, but it was there as /id_token.

Then I was thinking to do the following,

Call the signinRedirectCallback with the modified url (removing the backlash before the id_token), like

var modifiedUrl = url.replace("login#/id_token", "login#id_token");
mgr.signinRedirectCallback({ modifiedUrl }).then(function(user) {

but when this value is getting passed, it was always considered as object, not as a string, so in parseUrlFragment method typeof value == 'string' fails & it always over rides the value that is been passed, so again url with backslash was assigned (global.location.href) to value

UrlUtility.parseUrlFragment

if (typeof value !== 'string') {
value = global.location.href;
}

I temporarily commented above 3 lines, so that it will never override the value, now after commenting things work fine.

Is there a better way, to pass the URL in signinRedirectCallback, which will be considered as 'string', can you help me on that ?

Thanks a lot Brock again, for your wonderful patience , time and tremendous support.

When you call signinRedirectCallback you can pass the string instead of the function reading it automatically from the URL. So you can do your own parsing and "fix" it as necessary.

Thanks Brock

Brock, found an issue, still not getting the refreshed claim.

  1. Logged in successful using mgr.signinRedirect(). got first name as 'Siva'
  2. updated the user profile using ids3 and saved (updated first name as 'Siva 123')
  3. I had tried what you have suggested, reissued the sigin in call (mgr.signinRedirect()), even then I am getting the old firstName 'Siva'

As for refreshing the claims from user info, the only way is to re-issue a signin call.

  1. I am not able to understand the below point,

If you just want to access user info directly, then you can call it yourself with the access_token from the User, but this won't update the User profile being managed by the UserManager.

  1. After profile update, called getUser with access_token? Is below right way to call (but this doesn't return the updated profile firstName)?

mgr.getUser({ access_token: accesstoken }).then(function (user) {

  1. But when I signout and signin for the same user, I am getting the firstName as 'Siva 123'.

What is wrong here, can you review & suggest.

mgr.getUser({ access_token: accesstoken }) is wrong -- this API loads the user from the client-side persistence. It does not use the user info endpoint.

If you want to call the user info endpoint manually, you can always try the UserInfoService class. I don't know if I mentioned that before to you. This is the same class that's used internally by UserManager when you're going thru the login process.

As for why you're not getting your updated claism -- I don't know -- inspect the id_token JWT issued by the OP.

Brock, as mentioned, I tried with UserInfoService, I added below code

var UserInfoService = exports.UserInfoService = webpack_require(308);
as well included in exports.default = {

var uifs = new Oidc.UserInfoService(settings);
var claims = uifs.getClaims(accesstoken).then(function (claims) {               
                  console.log("user info claims received, updated profile:", claims);
                  return claims;
              });;

managed to make it work, but this as well returns the claims similar to UserManager getUser claims. (not getting the updated firstname value)

  • Then I was checking what is happening when I call signinSilent

mgr.signinSilent({data:'some data'}).then(function(user) {

  • I don't know, but randomly getting the updated firstname claim, but not sure why, randomly I mean, after updating the firstname, leaving the screen for a while may be 1 or 2 min or more, then when i call

mgr.signinSilent({data:'some data'}).then(function(user) {

then i get the updated claim. wondering what could be the reason!

Also wondering how other's who implemented ids3 are managing to display the updated user profile details, is that am doing different ? appreciate your thoughts.

yet to work on the last point you have mentioned.

Sorry, there sounds like some misconfiguration. I'd try to get one of our samples working the way you want, then try to find out the differences.

One additional information, I tried the above with the oidc/user-manager-sample.html, by including signinSilent. On the IdentityServer Side, using IdentityServer3.Admin & IdentityServer3.EntityFramework.

I managed to implement this in alternate way, after the profile got updated, I returned the profile user firstname & familyname & lastname in the return url, so that consuming application can have the updated value.

This should be fine for now.

Was this page helpful?
0 / 5 - 0 ratings