-
Notifications
You must be signed in to change notification settings - Fork 408
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement lazy ClaimsIdentity creation from ValidatedToken on SAML an…
…d SAML2 on the new validation model (#3051) * Implemented the claimsidentity creation methods to allow ValidatedToken to lazily create the claims when accessed in SAML and SAML2 token handlers * Added tests, updated returned ValidatedToken to generate the right ClaimsIdentity * Addressed PR feedback
- Loading branch information
Showing
10 changed files
with
383 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
src/Microsoft.IdentityModel.Tokens.Saml/Saml/SamlSecurityTokenHandler.ClaimsIdentity.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Security.Claims; | ||
using Microsoft.IdentityModel.Logging; | ||
|
||
#nullable enable | ||
namespace Microsoft.IdentityModel.Tokens.Saml | ||
{ | ||
/// <summary> | ||
/// A <see cref="SecurityTokenHandler"/> designed for creating and validating Saml Tokens. See: http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf | ||
/// </summary> | ||
public partial class SamlSecurityTokenHandler : SecurityTokenHandler | ||
{ | ||
internal override ClaimsIdentity CreateClaimsIdentityInternal(SecurityToken securityToken, ValidationParameters validationParameters, string issuer) | ||
{ | ||
return CreateClaimsIdentity((SamlSecurityToken)securityToken, validationParameters, issuer); | ||
} | ||
|
||
internal ClaimsIdentity CreateClaimsIdentity(SamlSecurityToken samlToken, ValidationParameters validationParameters, string issuer) | ||
{ | ||
if (samlToken == null) | ||
throw LogHelper.LogArgumentNullException(nameof(samlToken)); | ||
|
||
if (samlToken.Assertion == null) | ||
throw LogHelper.LogArgumentNullException(LogMessages.IDX11110); | ||
|
||
var actualIssuer = issuer; | ||
if (string.IsNullOrWhiteSpace(issuer)) | ||
actualIssuer = ClaimsIdentity.DefaultIssuer; | ||
|
||
IEnumerable<ClaimsIdentity> identities = ProcessStatements( | ||
samlToken, | ||
actualIssuer, | ||
validationParameters); | ||
|
||
return identities.First(); | ||
} | ||
|
||
/// <summary> | ||
/// Processes all statements to generate claims. | ||
/// </summary> | ||
/// <param name="samlToken">A <see cref="SamlSecurityToken"/> that will be used to create the claims.</param> | ||
/// <param name="issuer">The issuer.</param> | ||
/// <param name="validationParameters">The <see cref="TokenValidationParameters"/> to be used for validating the token.</param> | ||
/// <returns>A <see cref="IEnumerable{ClaimsIdentity}"/> containing the claims from the <see cref="SamlSecurityToken"/>.</returns> | ||
/// <exception cref="SamlSecurityTokenException">if the statement is not a <see cref="SamlSubjectStatement"/>.</exception> | ||
internal virtual IEnumerable<ClaimsIdentity> ProcessStatements(SamlSecurityToken samlToken, string issuer, ValidationParameters validationParameters) | ||
{ | ||
if (samlToken == null) | ||
throw LogHelper.LogArgumentNullException(nameof(samlToken)); | ||
|
||
if (validationParameters == null) | ||
throw LogHelper.LogArgumentNullException(nameof(validationParameters)); | ||
|
||
var identityDict = new Dictionary<SamlSubject, ClaimsIdentity>(SamlSubjectEqualityComparer); | ||
foreach (SamlStatement? item in samlToken.Assertion.Statements) | ||
{ | ||
if (item is not SamlSubjectStatement statement) | ||
throw LogHelper.LogExceptionMessage(new SamlSecurityTokenException(LogMessages.IDX11515)); | ||
|
||
if (!identityDict.TryGetValue(statement.Subject, out ClaimsIdentity? identity)) | ||
{ | ||
identity = validationParameters.CreateClaimsIdentity(samlToken, issuer); | ||
ProcessSubject(statement.Subject, identity, issuer); | ||
identityDict.Add(statement.Subject, identity); | ||
} | ||
|
||
if (statement is SamlAttributeStatement attrStatement) | ||
ProcessAttributeStatement(attrStatement, identity, issuer); | ||
else if (statement is SamlAuthenticationStatement authnStatement) | ||
ProcessAuthenticationStatement(authnStatement, identity, issuer); | ||
else if (statement is SamlAuthorizationDecisionStatement authzStatement) | ||
ProcessAuthorizationDecisionStatement(authzStatement, identity, issuer); | ||
else | ||
ProcessCustomSubjectStatement(statement, identity, issuer); | ||
} | ||
|
||
return identityDict.Values; | ||
} | ||
} | ||
} | ||
#nullable restore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
src/Microsoft.IdentityModel.Tokens.Saml/Saml2/Saml2SecurityTokenHandler.ClaimsIdentity.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System.Security.Claims; | ||
using Microsoft.IdentityModel.Logging; | ||
|
||
#nullable enable | ||
namespace Microsoft.IdentityModel.Tokens.Saml2 | ||
{ | ||
/// <summary> | ||
/// A <see cref="SecurityTokenHandler"/> designed for creating and validating Saml2 Tokens. See: http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf | ||
/// </summary> | ||
public partial class Saml2SecurityTokenHandler : SecurityTokenHandler | ||
{ | ||
internal override ClaimsIdentity CreateClaimsIdentityInternal(SecurityToken securityToken, ValidationParameters validationParameters, string issuer) | ||
{ | ||
return CreateClaimsIdentity((Saml2SecurityToken)securityToken, validationParameters, issuer); | ||
} | ||
|
||
internal ClaimsIdentity CreateClaimsIdentity(Saml2SecurityToken samlToken, ValidationParameters validationParameters, string issuer) | ||
{ | ||
if (samlToken == null) | ||
throw LogHelper.LogArgumentNullException(nameof(samlToken)); | ||
|
||
if (samlToken.Assertion == null) | ||
throw LogHelper.LogArgumentNullException(LogMessages.IDX13110); | ||
|
||
if (validationParameters == null) | ||
throw LogHelper.LogArgumentNullException(nameof(validationParameters)); | ||
|
||
string actualIssuer = issuer; | ||
if (string.IsNullOrWhiteSpace(issuer)) | ||
actualIssuer = ClaimsIdentity.DefaultIssuer; | ||
|
||
ClaimsIdentity identity = validationParameters.CreateClaimsIdentity(samlToken, actualIssuer); | ||
|
||
ProcessSubject(samlToken.Assertion.Subject, identity, actualIssuer); | ||
ProcessStatements(samlToken.Assertion.Statements, identity, actualIssuer); | ||
|
||
return identity; | ||
} | ||
} | ||
} | ||
#nullable restore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.