0

I am using IdentityServer4 with two external Idp's, one with WSFederation (ADFS) and one with SAML.

For the SAML implementation I use the commercial product ComponentSpace SAML 2 for ASP.Net Core. I use the middleware-based config.

Logging it with both Idp's works perfectly, but now I have the situation where, depending on the client, I need to pass extra parameters to the SAML AuthnRequest. I know how to pass this extra parameter in the request (I can use the OnAuthnRequestCreated from the middleware), but what I don't know is how to test at that point from where the request is coming, i.e. from which client.

I have control of the client so I could also pass extra acr_values (which I think can be used to pass custom data), but again I don't know how to get them in the OnAuthnRequestCreated event as shown in the code below.

Any help would be much appreciated.

services.AddSaml(Configuration.GetSection("SAML"));

services.AddAuthentication()
            .AddWsFederation("adfs", options =>
            {
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                //...rest of config (SSO is working)
            })
            .AddSaml("saml", options =>
            {
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                //...rest of config (SSO is working)

                options.OnAuthnRequestCreated = request =>
                {                      
                    //Here I would need to know from which client the request is coming (either by client name or url or acr_values or whatever)
                    //to be able to perform conditional logic. I've checked on the request object itself but the info is not in there

                    return request;
                };
            });
tjeuten
  • 649
  • 9
  • 28

2 Answers2

1

The request parameter is the SAML AuthnRequest object. It doesn't include client information etc.

Instead of the OnAuthnRequestCreated event, in your Startup class you can add some middleware as shown below. You can call GetRequiredService to access any additional interfaces (eg IHttpContextAccessor) you need to retrieve the client information.

app.Use((context, next) =>
{
    var samlServiceProvider =
        context.RequestServices.GetRequiredService<ISamlServiceProvider>();

    samlServiceProvider.OnAuthnRequestCreated += authnRequest =>
    {
        // Update authn request as required.

        return authnRequest;
    };

    return next();
});
ComponentSpace
  • 1,287
  • 6
  • 9
0

Thanks ComponentSpace for the reply. I didn't get it to work directly with your solution by using app.Use((context, next)) => ... but your comment on GetRequiredService pointed me into the direction to find the solution like below. Basically I'm getting the IHttpContextAccessor which I can then use to parse the query string. I then get the ReturnUrl from this query string and use the IIdentityServerInteractionService to get the AuthorizationContext object, which contains what I need to build my custom logic.

So thanks again for pointing me into the right direction.

//build and intermediate service provider so we can get already configured services further down this method
var sp = services.BuildServiceProvider();

services.AddAuthentication()
            .AddSaml("SamlIdp", options =>
            {
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

                options.OnAuthnRequestCreated = request =>
                {
                    var httpContextAccessor = sp.GetService<IHttpContextAccessor>();
                    var queryStringValues = HttpUtility.ParseQueryString(httpContextAccessor.HttpContext.Request.QueryString.Value);

                    var interactionService = sp.GetService<IIdentityServerInteractionService>();
                    var authContext = interactionService.GetAuthorizationContextAsync(queryStringValues["ReturnUrl"]).Result;

                    //authContext now contains client info and other useful stuff to help build further logic to customize the request

                    return request;
                };
            });
tjeuten
  • 649
  • 9
  • 28