-
Notifications
You must be signed in to change notification settings - Fork 40
Updated UID generation in DefaultClaimUidExtractor #52
Conversation
return new string[] | ||
{ | ||
"sub", | ||
subClaim.Value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment #30 (comment) mentions the claim and issuer... @blowdart want to explain exactly what to do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'd take the claim value, and the claim issuer (the Issuer property on the claim), and safely concatenate them (basically you do len(value)+value+len(issuer)+issuer), then either put that in the token, or a SHA256 hash of the concatenated value.
This basically means that if, for example, facebook and google issued the same sub claim value, you could still tell them apart, because the issuer is different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well these 2-string
arrays are run through a SHA256 hash soon after this method returns. Questions:
- Should they be 3-
string
arrays, adding the issuer? - Use
Issuer
orOriginalIssuer
from theClaim
?
⌚ |
{ | ||
// Arrange | ||
var identity = new ClaimsIdentity(); | ||
identity.AddClaim(new Claim("fooClaim", "fooClaimValue")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Please avoid "foo" and similar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our tests use foo
in thousands of places, what's wrong with it? It at least makes it clear that it's an arbitrary value...
Updated. |
Need to add more tests. Will do it once the updated design is accepted. |
@@ -66,7 +66,12 @@ public AntiforgeryToken GenerateCookieToken() | |||
if (identity != null && identity.IsAuthenticated) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we still check this now that you're checking User?.Identities
? Seems redundant and unnecessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that if Identity
is equal to the first member of Identities
where IsAuthenticated
is true
, existing code was 🆗. (I'm not sure whether "primary" in the Identity
doc comment means IsAuthenticated
or something else.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked at the code. It does not check for IsAuthenticated
. It simply selects first non-null identity. https://github.com/dotnet/corefx/blob/master/src/System.Security.Claims/src/System/Security/Claims/ClaimsPrincipal.cs
⌚ |
var nameIdentifierClaim = claimsIdentity.FindFirst( | ||
claim => string.Equals(ClaimTypes.NameIdentifier, claim.Type, StringComparison.Ordinal)); | ||
if (nameIdentifierClaim != null && !string.IsNullOrEmpty(nameIdentifierClaim.Value)) | ||
if (claimsIdentities == null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the IEnumerable<T>
be null
in real scenarios?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure. But I guess returning null is better than just letting it blow up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't add these kind of checks just because. It may mislead developers down the road if it's not a real scenario. Check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, this isn't a real scenario since the caller checks exactly this condition. Just Debug.Assert()
.
⌚ |
Updated. |
@@ -60,16 +61,17 @@ public AntiforgeryToken GenerateCookieToken() | |||
}; | |||
|
|||
var isIdentityAuthenticated = false; | |||
var identity = httpContext.User?.Identity as ClaimsIdentity; | |||
var authenticatedIdentity = httpContext.User?.Identities?.FirstOrDefault(c => c.IsAuthenticated == true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're trying hard to optimize Antiforgery. Don't introduce Linq here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also,
- Can
Identities
really benull
? Check the real code and don't check here unless it's a real scenario. - Lots of boilerplate around
authenticatedIdentity
repeated in two methods. Suggest a helper method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can Identities really be null?
You are right. It can never be null. An empty list is always allocated.
⌚ |
Updated. |
@@ -60,16 +61,17 @@ public AntiforgeryToken GenerateCookieToken() | |||
}; | |||
|
|||
var isIdentityAuthenticated = false; | |||
var identity = httpContext.User?.Identity as ClaimsIdentity; | |||
var authenticatedIdentity = httpContext.User != null ? GetAuthenticatedIdentity(httpContext.User) : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the ternary and have GetAuthenticatedIdentity()
return null
when passed null
.
"LOCAL AUTHORITY", | ||
ClaimTypes.Name, | ||
"claimName", | ||
"LOCAL AUTHORITY", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test demonstrates the behaviour I complained about here. Should never mix claims from multiple identities in the same UID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⌚ |
Updated. |
using System.Security.Claims; | ||
|
||
namespace Microsoft.AspNetCore.Antiforgery.Internal | ||
{ | ||
/// <summary> | ||
/// This interface can extract unique identifers for a claims-based identity. | ||
/// This interface can extract unique identifers for a list of claims-based identities. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a ClaimsPrincipal
Debug.Assert(claimsPrincipal != null); | ||
|
||
var uniqueIdentifierParameters = GetUniqueIdentifierParameters(claimsPrincipal.Identities); | ||
if (uniqueIdentifierParameters == null) | ||
{ | ||
// Skip anonymous users |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix this comment. Never reach here if the principal isn't logged in somehow.
|
49f6321
to
8d6950e
Compare
Updated and Rebased. |
Ping @blowdart |
Works for me. Might need more kittens though. |
8d6950e
to
220479c
Compare
Issue - #30
@blowdart @rynowak