samlidentityserver4component-space

Identityserver4 with ComponentSpace SAML 2 get custom parameters during request


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;
                };
            });

Solution

  • 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;
                    };
                });