Search code examples
asp.netasp.net-core.net-6.0saml-2.0itfoxtec-identity-saml2

How do I translate a .Net Core Startup.cs class to the new .NET Program.cs class?


I'm trying to translate a .NetCore project to a .Net 7 project.

The project uses the ITFoxTec SAML2 library.

The .NetCore project has a Startup.cs file that looks like this:

// .NetCore Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.BindConfig<Saml2Configuration>(Configuration, "Saml2", (serviceProvider, saml2Configuration) =>
    {
        saml2Configuration.AllowedAudienceUris.Add(saml2Configuration.Issuer);

        var httpClientFactory = serviceProvider.GetService<IHttpClientFactory>();
        var entityDescriptor = new EntityDescriptor();
        entityDescriptor.ReadIdPSsoDescriptorFromUrlAsync(httpClientFactory, new Uri(Configuration["Saml2:IdPMetadata"])).GetAwaiter().GetResult();

        saml2Configuration.SingleSignOnDestination = entityDescriptor.IdPSsoDescriptor.SingleSignOnServices.First().Location;
        foreach (var signingCertificate in entityDescriptor.IdPSsoDescriptor.SigningCertificates)
        {
            saml2Configuration.SignatureValidationCertificates.Add(signingCertificate);
        }

        saml2Configuration.SignAuthnRequest = entityDescriptor.IdPSsoDescriptor.WantAuthnRequestsSigned.Value;

        return saml2Configuration;
    });            

    services.AddSaml2();
    services.AddHttpClient();

    services.AddControllersWithViews();
}

And here, I am trying to translate that to a .Net 7 Program.cs like this:

// .NET 7 Program.cs

var builder = WebApplication.CreateBuilder(args);

var configuration = builder.Configuration;

builder.Services.AddRazorPages();

builder.Services.Configure<Saml2Configuration>(configuration.GetSection("Saml2"));

builder.Services.Configure<Saml2Configuration>(saml2Configuration =>
{
    saml2Configuration.AllowedAudienceUris.Add(saml2Configuration.Issuer);

    var entityDescriptor = new EntityDescriptor();
    entityDescriptor.ReadIdPSsoDescriptorFromUrl(new Uri(configuration["Saml2:IdPMetadata"]));
    saml2Configuration.SingleSignOnDestination = entityDescriptor.IdPSsoDescriptor.SingleSignOnServices.First().Location;
    saml2Configuration.SignatureValidationCertificates.AddRange(entityDescriptor.IdPSsoDescriptor.SigningCertificates);

});

builder.Services.AddSaml2();

var app = builder.Build();

However, whenever I run it, I am getting this error:

InvalidOperationException: Unable to resolve service for type 'ITfoxtec.Identity.Saml2.Saml2Configuration' while attempting to activate 'JMUSAMLConnector.Controllers.AuthController'.
Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)

My AuthController is trying to use it like this:

using ITfoxtec.Identity.Saml2;
using ITfoxtec.Identity.Saml2.Schemas;
using ITfoxtec.Identity.Saml2.MvcCore;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using JMUSAMLConnector.Identity;
using System.Security.Authentication;

namespace JMUSAMLConnector.Controllers
{
    [AllowAnonymous]
    [Route("Auth")]
    public class AuthController : Controller
    {
        const string relayStateReturnUrl = "ReturnUrl";
        private readonly Saml2Configuration config;

        public AuthController(Saml2Configuration config)
        {
            this.config = config;
        }

Solution

  • try changing this:

    private readonly Saml2Configuration config;
    
    public AuthController(Saml2Configuration config)
    {
       this.config = config;
    }
    

    to :

    private readonly Saml2Configuration _config;
    
    public AuthController(IOptions<Saml2Configuration> options)
    {
       _config = options.Value;
    }