We have a multi-tenant setup where we store SAML config data in a local database. When using local service provider login, it works great, for example the flow is:
- Enter their email address into out platform
- That checks if they are using SSO and sets the config accordingly using await _samlServiceProvider.SetConfigurationIDAsync(email) which calls the method GetLocalServiceProviderConfigurationAsync from within our CustomConfigurationResolver class- all well and good.
- That happily redirects to, for this example. Azure login page where they login
- Microsoft then redirect back to our AssertionConsumerService URL and calls our OnGetCallbackAsync in the ExternalLogin class
- We then decide what to do with this user after using ConfigurationId (email address in our case) to check their account etc - all working great!
- After the “App” is selected from the Microsoft portal, it asks for appropriate authentication, all good so far
- MS then calls our application’s GetLocalServiceProviderConfigurationAsync again but this time with a null in the ConfigurationId (email in our case), when I would expect (although this is where my knowledge is breaking down) it to call GetPartnerIdentityProviderConfigurationAsync with the signature ConfigurationId (email in our case) and partner name, but this method never gets called.
Our Startup class has:
services.AddSaml();
services.AddTransient<ISamlConfigurationResolver, Classes.Account.CustomConfigurationResolver>();
services.AddAuthentication()
Apologies if we have missed something obvious but any advice would be appreciated.
Thanks.
Jim.
UPDATE
Within the CustomConfigurationResolver class when the GetLocalServiceProviderConfigurationAsync gets called first using IdP initiated and, because we are passed a null, we have no choice but to return an empty (not null) instance of LocalServiceProviderConfiguration. When doing so the GetPartnerIdentityProviderConfigurationAsync does actually then get called but an Id of null (don’t know why). The Partner name however does contain a value we can use but ideally we would also like the Id (email address in our case).
We then find their record and populate and return PartnerIdentityProviderConfiguration, but the ExternalLogin class is not called when we would next expect it to.
UPDATE 2
So when I hard code the LocalServiceProviderConfiguration in the GetLocalServiceProviderConfigurationAsync method in the CustomConfigurationResolver class it works fine and logs in perfectly using IdP, but this is impossible to populate whilst the ConfigurationId is null and I cannot obtain that information from the database.
UPDATE 3 - WORKING
Leaving post up in case it helps anyone else / or someone can correct our process.
It seems we HAVE to have something in the LocalServiceProviderConfiguration, but it only needs to be the Name and the AssertionConsumerServiceUrl properties. These are static across our multi-tenancy so if the ConfigurationId being passed in is null we simply create a new instance of LocalServiceProviderConfiguration and populate those two properties. With that done, all works = phew!