Microsoft-authentication-library-for-js: Retrieving user claims

Created on 31 Oct 2017  路  21Comments  路  Source: AzureAD/microsoft-authentication-library-for-js

Version 0.1.3 has been released and I am now importing the library this way :

import { UserAgentApplication } from 'msal';

@navyasric : How can I get the user claims using the approach I described in issue #121 since the classes I redefine are not accessible anymore when using the import statement?

A GetClaimValue(claim: string) : string function on User would be very appreciated.

Thank you!

All 21 comments

I do agree with @davidmorissette. It'll be great if the library could provide some methods to get cached token with claims.

I also think that access to claims or some other way of accessing at least user ID and tenant ID would be essential. Now the User object doesn't contain any identifiers shared with Graph API / MS Graph user profiles (UserPrincipalName doesn't quite work because it's not immutable - or is it even globally unique).

PR #173 created!

Could anyone provide an update regarding this issue? We need to be able to retrieve claims from the token! Thank you.

PR #212 regarding getClaim method on user object.

@TLena @htuomola @davidmorissette @spottedmahn Thanks a lot for your feedback and contribution. We had discussions within our team and unfortunately we cannot add a separate public api getClaim() on user object as then we will have to enable that same api on all other MSAL libraries. Our goal is to expose the same public api interface across all platforms. Instead we decided to expose the idToken object as a public property on the user object. You can then easily use that object to query any claim

 if (this._user.idToken.hasOwnProperty(claim)) {
            return idToken[claim];
     }

I have merged my code change in the dev branch. Please test it and let me know if it solves your issue.

Hi @rohitnarula7176 - thanks for the update. I understand your desire to have the same public api across all MSAL libraries but I don't understand why other libraries wouldn't want this? What am I missing?

I'll give it a try. Thanks for the PR! When can we expect a new version cut and put on NPM?

Hi @rohitnarula7176 - idToken is limited to the claims that are retrieved in its constructor; I think decodedIdToken is what you wanted to expose.

Also, I fully agree with @spottedmahn. I understand the desire to have the same public api across all MSAL librairies but isn't retrieving claims fundamental to oauth?

B2C allows the selection of application claims through custom policies. MSAL should be able to retrieve those claims as it officially supports Microsoft Azure B2C.

Thank you for reconsidering.

I fully agree with @davidmorissette as we also add specific claims via Azure B2C policies for our providers and they are easily retrieved as claims on the token. We've used this with ASP.Net core but after switching over to javascript and msal I was quite surprised that one has to jump through some hoops to do that.

Hi @rohitnarula7176 - I would love to test this and give you any feedback but we pull msal.js from NPM, wondering how I can test this change w/o it being published to NPM.

Any ideas on that? Any chance you can publish a beta to NPM?

@davidmorissette I have made the change in the code such that idToken property exposed on the user object is not limited to the claims that are retrieved in the idToken constructor. The code is in the dev branch. Please check it and confirm. @spottedmahn Thank you for your help. I will let you know if I deploy a beta version on npm.

Hi @rohitnarula7176 - I confirm that was able to retrieve the claims using your last update.

By the way, idToken should be of any type since the purpose here is to call properties that are not strongly defined:
https://stackoverflow.com/questions/18961203/typescript-any-vs-object

@davidmorissette I believe having id_token as Object type is a better and more stricter solution as the id_token is exposed as a JSON object on the user object in the end. Exposing it as any data type would mean it can be string or boolean or anything for that matter which can be misleading. Having it as Object restricts the developer to only query claims that were received in the id_token response at compile time which would not be possible if we change the type to any. Also the object interface in typescript is defined with the property hasOwnProperty which comes in handy with intellisense when you say user.hasOwnProperty('claim'). If we make its type to any, you wont' get any intelliSense for any of the properties. Please let me know if it makes sense.

Hi @rohitnarula7176 - Just to be clear, I am talking about IdToken as Object, not User. Although the Object interface defines an hasOwnProperty function, this code produces an error:

if (idToken.hasOwnProperty('email') {
    const email = idToken['email'];
}

I get a TypeScript error when trying to get the property since the indexer is not defined on Object, unless I cast the idToken to any. That's why I was suggesting that idToken should be of any type.

Can you try and confirm that you don't get any error when doing this?

Thank you!

@davidmorissette I meant id_token as an Object. It was a typo. I did not get any errors with the piece of code you have pasted above. Maybe you have a different compiler option in tsconfig.json like ""suppressImplicitAnyIndexErrors": true,". Can you share your tsconfig as well as the exact error code you get with this code so I can look into this further.

Hey @rohitnarula7176 - wish you could publish to NPM so I can try it out too! 馃槃

@rohitnarula7176 - TS7017 Index signature of object type implicitly has an 'any' type.

Using noImplicitAny option in tsconfig.json can turn off that error since TypeScript tries to implicitly convert Object to any in order to allow the usage of the indexer. I understand the difference between Object and any and in this particular case, I believe any is more appropriate since like I said before, the properties are not strongly defined and Object would therefore restrict their access.

You can experiment with my previous code by switching the noImplicitAny option on and off.

N.B. I use the same tsconfig.json as the one provided by the latest Angular template:

{
    "compileOnSave": false,
    "compilerOptions": {
        "outDir": "./dist/out-tsc",
        "sourceMap": true,
        "declaration": false,
        "moduleResolution": "node",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "target": "es5",
        "typeRoots": [
            "node_modules/@types"
        ],
        "lib": [
            "es2017",
            "dom"
        ]
    }
}

@davidmorissette Thank you for the explanation. I am not able to reproduce this error by switching the noImplicitAny property in tsconfig.json. The only warning I get by using this syntax is "object access via string literals is disallowed" which can be turned off by setting "no-string-literal": false, in tslint.json. I am using the type Object in other instances where the type does not have strongly typed properties and I do not get any compile time or run time errors. If you get any compile time or run time error, can you paste that in this thread. Since idToken is returned as an object, I want to have a solid reason to change its type to any.

@rohitnarula7176 - I realized that there is one difference between the tsconfig.json I copied in my previous message and the one I am using:

strict: true

Do you get the same behavior by switching it on and off? What is your opinion regarding this? Do you intend to use strict mode in MSAL in the future?

@davidmorissette We do not plan to add strict:true to the source code. Please let me know if you have any other concerns besides that. We are planning to release a new version next week.

@rohitnarula7176 - I can always cast to any so it's not an issue. Thank you for help, being able to use the decoded token will be very useful for retrieving claims.

Was this page helpful?
0 / 5 - 0 ratings