Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Conversation

Tratcher
Copy link
Member

@Tratcher Tratcher commented Feb 2, 2018

#1609 @leastprivilege @brockallen how does this look? It covers your asks in three parts:

  • Clear the JWT claims type map.
  • Map all claims
  • bulk delete protocol claims

@Tratcher Tratcher self-assigned this Feb 2, 2018
/// Maps all values from the json user data as claims, excluding duplicates.
/// </summary>
/// <param name="collection"></param>
public static void MapAllClaims(this ClaimActionCollection collection)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shorten to MapAll to be consistent with all the other methods that don't have Claims suffix?

/// </summary>
/// <param name="collection"></param>
/// <param name="claimTypes"></param>
public static void DeleteClaims(this ClaimActionCollection collection, params string[] claimTypes)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

People have been very confused by Remove vs Delete. We need to avoid aggravating that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could also just change DeleteClaim to take a params string[] right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory, but it would be binary breaking.

// Avoid adding a claim if there's a duplicate name and value. This often happens in OIDC when claims are
// retrieved both from the id_token and from the user-info endpoint.
var duplicate = false;
foreach (var existingClaim in identity.FindAll(pair.Key))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: can you something like this?

var duplicate = identity.FindFirst(c => c.Key == pair.Key && string.Equals(c.Value, claimValue, StringComparison.Ordinal) != null


foreach (var claimType in claimTypes)
{
collection.Add(new DeleteClaimAction(claimType));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider enhancing DeleteClaimAction type to take a list of claims so you don't have to add one action per type?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance wise it's the same, you still need to loop through all of the names.

Adding them individually preserves the functionality of methods like ClaimActionsCollection.Remove(claimType) that removes the action by name.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure that's exactly the behavior that's confusing today.

options.ClaimActions.Remove("something") you would think is the same as options.ClaimActions.DeleteClaim("something").

I think this api should be mostly focusing on making it easy to do the common things.

MapJsonKey
MapAll
Delete

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The list of delegate/actions is fine as an implementation detail, but I really don't think generally developers should have to understand/deal with that... when all they want to do is include/ignore some set of claims. Only someone who is trying to plug in a complex mapping should have to understand the whole claim action stuff

@leastprivilege
Copy link
Contributor

Clear the JWT claims type map.

Maybe I am missing something - but this is only done in the sample. Not in the handler...I want this to be turned off by default. Your default mapping can do the conversion from standard to propriety if that is a requirement.

Map all claims
bulk delete protocol claims

Can't we make that one operation like

MapAll(params string[] filterList)

o.ClaimActions.Clear();
o.ClaimActions.MapAllClaims();
// Note some of these protocol claims also show up in the user info
o.ClaimActions.DeleteClaims("aud", "iss", "iat", "nbf", "exp", "aio", "c_hash", "uti", "nonce");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RemoveProtocolClaims
MapAllUserInfo

@leastprivilege
Copy link
Contributor

just to be really clear

this

var handler = new JwtSecurityTokenHandler();
handler.InboundClaimTypeMap.Clear();
o.SecurityTokenValidator = handler;

is not really an improvement over just turning of the inbound claims mapping globally via their static DefaultInboundClaimTypeMap.

I would like to see no claims mapping at all.

@Tratcher Tratcher added this to the 2.1.0-preview2 milestone Mar 13, 2018
@Tratcher Tratcher changed the base branch from dev to release/2.1 March 16, 2018 19:16
@Tratcher Tratcher force-pushed the tratcher/allclaims branch from b6a8979 to b6e905d Compare March 16, 2018 22:30
@Tratcher
Copy link
Member Author

@leastprivilege @brockallen Updated. MapAllExcept combines both operations like you asked.

@Tratcher Tratcher changed the title [WIP] Add ClaimActions for bulk add and remove Add ClaimActions for bulk add and remove Mar 16, 2018
@brockallen
Copy link

Thanks. Will investigate.

@leastprivilege
Copy link
Contributor

..and what about the claim type mappings - will this be turned off at the handler level by default?

@Tratcher
Copy link
Member Author

That's a breaking change, I can't do that right now.

@Tratcher
Copy link
Member Author

@leastprivilege @brockallen please review this week or we'll need to close this PR.

@brockallen
Copy link

I have a VM with preview-1. I assume I can just pull the source for this and test that.

@leastprivilege
Copy link
Contributor

That's a breaking change, I can't do that right now.

Two things you can do:

  • Do the mapping of standard to proprietary claims in the default claim actions
  • Allow setting/clearing the inbound claim type map directly on the OIDC handler options

@Tratcher
Copy link
Member Author

@brockallen the code should even work against 2.0 RTM.

@Tratcher
Copy link
Member Author

@leastprivilege

Do the mapping of standard to proprietary claims in the default claim actions

I don't follow. Can you give an example?

Allow setting/clearing the inbound claim type map directly on the OIDC handler options

So the code you want to simplify is:

                var handler = new JwtSecurityTokenHandler();
                handler.InboundClaimTypeMap.Clear();
                o.SecurityTokenValidator = handler;

Down to something like o.InboundClaimTypeMap.Clear();? That might be doable but it would rely on downcasting ISecurityTokenValidator SecurityTokenValidator to it's default type JwtSecurityTokenHandler.

@brockallen
Copy link

@brockallen the code should even work against 2.0 RTM.

Even easier. I'll do it first thing tomorrow.

@leastprivilege
Copy link
Contributor

leastprivilege commented Mar 21, 2018

I don't follow. Can you give an example?

Well - you could have a MakeYourClaimsWorse (naming is up to you ;)) option. And when it is set - whenever you run a claim action, you use the dictionary provided by the JwtSecurityTokenHandler to do a mapping if present. If not you use the raw claim types.

This way the mapping behavior would be an OIDC handler thing...

@brockallen
Copy link

I was unable to get this branch working on either 2.0 or 2.1-preview-1. Mainly build issues on the Security repo.

@Tratcher
Copy link
Member Author

@brockallen no need to build this repo, you should be able to copy the MapAllClaimsAction class directly into your app. You could also copy the new extension methods if you like.


public override void Run(JObject userData, ClaimsIdentity identity, string issuer)
{
foreach (var pair in userData)
Copy link

@brockallen brockallen Mar 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I use the new MapAll I get a null reference exception on userData. Implicit flow only in my client, BTW: ResponseType="id_token".

@brockallen
Copy link

brockallen commented Mar 21, 2018

I think all these new helpers should all call Clear on the ClaimsActions. For example:

options.ClaimActions.MapAllExcept("aud", "iss", "iat", "nbf", "exp", "aio", "c_hash", "uti", "nonce")

Still doesn't allow amr through. I had to call:

options.ClaimActions.Clear();
options.ClaimActions.MapAllExcept("aud", "iss", "iat", "nbf", "exp", "aio", "c_hash", "uti", "nonce");

to get amr, and so then it makes the MapAllExcept name not make much sense.

Same goes for MapAll -- all by itself it doesn't really do much.

@brockallen
Copy link

brockallen commented Mar 21, 2018

And just to repeat since I don't know if you saw it:

When I use the new MapAll I get a null reference exception on userData. This fails when I have an implicit flow only client, meaning ResponseType="id_token".

Actually, any of these new helpers fail with the same null ref exception for "id_token" only client.

@Tratcher Tratcher force-pushed the tratcher/allclaims branch from b6e905d to c02d783 Compare March 21, 2018 21:43
@Tratcher
Copy link
Member Author

Updated

@brockallen
Copy link

Cool, thanks. I think with those changes, this now becomes a nice one-liner to allow controlling which claims are kept/removed. There's of course the claim type map issue, but that's another topic/thread I assume?

@Tratcher
Copy link
Member Author

Tratcher commented Mar 21, 2018

Agreed, the type map is orthogonal.

@Tratcher
Copy link
Member Author

@HaoK please sanity check

public static void MapAllExcept(this ClaimActionCollection collection, params string[] exclusions)
{
collection.Clear();
collection.Add(new MapAllClaimsAction());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should call MapAll

@Tratcher
Copy link
Member Author

@leastprivilege second guessing the mappings is problematic, you're better off clearing JWT's mappings. I'm going to merge this PR as your suggestions along that line are independent. I'll file a new issue to simplify clearing the JWT type map.

@Tratcher Tratcher force-pushed the tratcher/allclaims branch from c02d783 to 90064ce Compare March 21, 2018 23:36
@Tratcher Tratcher merged commit 90064ce into release/2.1 Mar 22, 2018
@Tratcher Tratcher deleted the tratcher/allclaims branch March 22, 2018 16:37
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants