SelectIdentityProvider
and GetIdentityProvider
notifications. Anyone can guide me in the right direction would be appreciated. Thank you.
builder.AddSaml2(
saml2Options =>
{
saml2Options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
saml2Options.SPOptions.EntityId = new EntityId(config.Saml2.ServiceProviderEntityId);
saml2Options.SPOptions.ServiceCertificates.Add(certificate);
saml2Options.Notifications.SelectIdentityProvider =
(id, data) => GetProvider(identityProviderStore, id, data, saml2Options, logger);
saml2Options.Notifications.GetIdentityProvider =
(id, data, options) => GetProvider(identityProviderStore, id, data, options, logger);
saml2Options.Notifications.AcsCommandResultCreated =
(commandResult, response) =>
{
if (commandResult.Principal.Identity is ClaimsIdentity identity)
identity.AddClaim(new Claim("in_response_to", response.InResponseTo.Value));
};
});
GetProvider
method looks something like this...
private IdentityProvider GetProvider(IEegIdentityProviderStore identityProviderStore, EntityId id, IDictionary<string,string> data, IOptions options, ILogger logger)
{
Saml2IdentityProvider provider = identityProviderStore.GetSamlProviderByEntityId(id.Id);
if (provider == null)
return null;
idp =
new IdentityProvider(new EntityId(provider.EntityId), options.SPOptions)
{
MetadataLocation = provider.Debug
? provider.DebugMetadataLocation
: provider.MetadataLocation
};
logger.Verbose("Adding Identity Provider: {IdpName}", provider.DisplayName);
if (provider.Debug)
logger.Warning(
"Provider {Provider} is in debug mode, using metadata URL: {MetadataUrl}",
provider.DisplayName,
provider.DebugMetadataLocation);
options.IdentityProviders.Add(idp);
return idp;
}
options.IdentityProviders
collection multiple times. That would also be a problem.
@mlindegarde and @AndersAbel thank you for your input. There are a couple methods there that I don't have a great understanding how they work, in either way here's what I've done adjusting your code to mine. FYI: this project is a legacy Asp.Net Web App (non-MVC).
in my Global.asax
void Application_BeginRequest(object sender, EventArgs e) {
Saml2Config.Initialize();
}
In the Sam2Config
file:
public class Saml2Config {
private static bool _alreadyInitialized;
private static readonly object Lock = new object();
private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
public static void Initialize() {
if (_alreadyInitialized) {
return;
}
lock (Lock) {
if (_alreadyInitialized) {
return;
}
spOptions = Options.FromConfiguration.SPOptions;
// Get list of IdentityProviders
var saml2IdentityProvidersRepository = new Saml2IdentityProvidersRepository();
var saml2IdentityProviders = saml2IdentityProvidersRepository.FindByServiceProviderEntityId(spOptions.EntityId.Id, x => x.Saml2BindingType).OrderBy(x => x.OrderPreference);
Options.FromConfiguration.Notifications.SelectIdentityProvider = (id, data) => GetProvider(saml2IdentityProviders, id, data, Options.FromConfiguration, _logger);
Options.FromConfiguration.Notifications.GetIdentityProvider = (id, data, options) => GetProvider(saml2IdentityProviders, id, data, options, _logger);
saml2IdentityProvidersRepository.Dispose();
_alreadyInitialized = true;
}
}
private static IdentityProvider GetProvider(IQueryable<Saml2IdentityProvider> identityProviderStore, EntityId id, IDictionary<string, string> data, IOptions options, ILogger logger) {
var identityProvider = identityProviderStore.FirstOrDefault(x => x.IsActive && x.IdentityProviderEntityId.Equals(id.Id));
if (identityProvider == null) {
return null;
}
var idpEntityId = new EntityId(identityProvider.IdentityProviderEntityId);
var bindingType = EnumHelper.NumToEnum<Sustainsys.Saml2.WebSso.Saml2BindingType>(identityProvider.Saml2BindingType.Value);
var idp = new IdentityProvider(idpEntityId, options.SPOptions) {
MetadataLocation = identityProvider.MetadataLocation,
LoadMetadata = identityProvider.LoadMetadata,
AllowUnsolicitedAuthnResponse = identityProvider.AllowUnsolicitedAuthnResponse,
Binding = bindingType,
};
options.IdentityProviders.Add(idp);
return idp;
}
/External/Challenge?scheme=${scheme}&idp=${entityId}&returnUrl=${returnUrl}
. Your exact route is probably different than mine, but somewhere you should have a route that starts the SAML2 process.
idp
parameter in the query string is where the entity id value comes from.
idp
value is in the AuthenticationProperties.Items
collection:new AuthenticationProperties
{
RedirectUri = Url.Action(nameof(Callback)),
Items =
{
{ "returnUrl", returnUrl },
{ "scheme", scheme },
{ "idp", idp }
}
}
idp
value in the Items
collection you should get that value in your GetProvider
method. You can then use that value to look up the data in the database.
[16:05:57 Debug] Sustainsys.Saml2.AspNetCore2.Saml2Handler
Expanded Saml2Url
AssertionConsumerServiceUrl: https://localhost:5001/Saml2/Acs
SignInUrl: https://localhost:5001/Saml2/SignIn
LogoutUrl: https://localhost:5001/Saml2/Logout
ApplicationUrl: https://localhost:5001/
AssertionConsumerServiceUrl
is http://auth.my-company/Saml2/Acs
. It's using http
instead of https
. I'm not sure why that is.
Hi @AndersAbel , I am using HTTPModules with Asp.Net 4.6 framework, I have implemented everything but getting the below Error after redirecting from ADFS on Saml2/ACS page.
Server Error in '/' Application.
The Saml2Response must have status success to extract claims.
Saml2 Status Code: Responder
Saml2 Status Message:
Saml2 Second Level Status:
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: Sustainsys.Saml2.Exceptions.UnsuccessfulSamlOperationException: The Saml2Response must have status success to extract claims.
Saml2 Status Code: Responder
Saml2 Status Message:
Saml2 Second Level Status:
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Its been months and not able to find out solution.
Any gentleman can give their suggestion as well, please!
@AndersAbel PLEASE
whenever i am hitting my url https://test.xyz.com it redirects me to ADFS, and there after putting credential SAML2 HTTpModule again redirecting multiple times with different saml request and finally it is giving error as i have written above
Thanks @mlindegarde for your kind response. yes i have changed the configuration, but also i am sure i have cleaned all cookies and session even history as well. but no success.
i asked for adfs log as well from server team.
in the mean while if by chance you get remember the configuration part then please let me know.
thanks once again
Hi everyone i am getting below error, please suggest i am using correct certificate files.
The signature verified correctly with the key contained in the signature, but that key is not trusted.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: Sustainsys.Saml2.Exceptions.InvalidSignatureException: The signature verified correctly with the key contained in the signature, but that key is not trusted.
Hi @AndersAbel , Regarding above certificate validation issue.
I am getting response successfully from ADFS server (as i checked in one of the chrome extension) but due to certificate validation method called i am not getting response in thread principle claims.
please suggest me that how can i resolve this.
Can i stop certificate validation part by changing in some configuration.
using latest stable version of SAML.HttpModule.
I will be grateful if you will revert me on my issue.
Hello @AndersAbel ,
First of all, it's a very kind of you that you given time to reply me.
But as I have matched again both the public certificate and the token signing certificate The IDP Certificate which is coming in response from ADFS are identical to what i have configured in my application as an idp certificate as you can see in the image above.
The only things new i have found is my ADFS contains 2 token signing certificate 1 is newer which i am using and other is older one which is not in use anymore.
Please help me if there is any suggestion or guidance.
(i am using chrome 3rd party extension named "SAML message decoder")