italia / cie-aspnetcore

AspNetCore Remote Authenticator for CIE 3.0
https://github.com/danielegiallonardo/cie-aspnetcore
MIT License
17 stars 4 forks source link

Errore generico durante l'autenticazione #15

Closed gianlucabertani closed 11 months ago

gianlucabertani commented 11 months ago

Buongiorno,

stiamo cercando di integrare le funzionalità di autenticazione CIE in un'applicazione AspNetCore, che già fornisce l'autenticazione via SPID con la libreria equivalente SPID AspNetCore e basata sull'esempio SPID.AspNetCore.WebApp. L'autenticazione con SPID funziona correttamente ed è in produzione da tempo, ma l'autenticazione con CIE va sempre in errore con un messaggio Errore generico. Prova ad autenticarti più tardi. che non ci dice nulla su dove sia il problema.

Per fare l'integrazione abbiamo introdotto due azioni aggiuntive di login e logout per CIE nell'HomeController, e aggiornato lo Startup.cs in modo da introdurre anche l'autenticazione via CIE. La ConfigureServices di Startup.cs risulta così:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();

            services
                .AddAuthentication(o => {
                    o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    o.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    o.DefaultChallengeScheme = SpidDefaults.AuthenticationScheme;
                })
                .AddSpid(o => {
                    o.Events.OnAuthenticationFailed = async (s) => await s.HttpContext.RequestServices.GetRequiredService<SpidEventLogger>().AuthenticationFailed(s);
                    o.Events.OnAuthenticationSuccess = async (s) => await s.HttpContext.RequestServices.GetRequiredService<SpidEventLogger>().AuthenticationSuccess(s);
                    o.Events.OnMessageReceived = async (s) => await s.HttpContext.RequestServices.GetRequiredService<SpidEventLogger>().MessageReceived(s);
                    o.Events.OnRedirectToIdentityProvider = async (s) => await s.HttpContext.RequestServices.GetRequiredService<SpidEventLogger>().RedirectToIdentityProvider(s);
                    o.Events.OnRemoteSignOut = async (s) => await s.HttpContext.RequestServices.GetRequiredService<SpidEventLogger>().RemoteSignOut(s);
                    o.Events.OnTokenCreating = async (s) => await s.HttpContext.RequestServices.GetRequiredService<SpidEventLogger>().TokenCreating(s);
                    o.LoadFromConfiguration(Configuration);
                })
                .AddCie(o => {
                    o.Events.OnAuthenticationFailed = async (s) => await s.HttpContext.RequestServices.GetRequiredService<CieEventLogger>().AuthenticationFailed(s);
                    o.Events.OnAuthenticationSuccess = async (s) => await s.HttpContext.RequestServices.GetRequiredService<CieEventLogger>().AuthenticationSuccess(s);
                    o.Events.OnMessageReceived = async (s) => await s.HttpContext.RequestServices.GetRequiredService<CieEventLogger>().MessageReceived(s);
                    o.Events.OnRedirectToIdentityProvider = async (s) => await s.HttpContext.RequestServices.GetRequiredService<CieEventLogger>().RedirectToIdentityProvider(s);
                    o.Events.OnRemoteSignOut = async (s) => await s.HttpContext.RequestServices.GetRequiredService<CieEventLogger>().RemoteSignOut(s);
                    o.Events.OnTokenCreating = async (s) => await s.HttpContext.RequestServices.GetRequiredService<CieEventLogger>().TokenCreating(s);
                    o.LoadFromConfiguration(Configuration);
                    o.ServiceProvidersMetadataEndpointsBasePath = "/cie-metadata";
                })
                .AddServiceProvidersFactory<CieServiceProvidersFactory>()
                .AddCookie();

            services.AddScoped<SpidEventLogger>();
            services.AddScoped<CieEventLogger>();

            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => false;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddSession(opts =>
            {
                opts.Cookie.SecurePolicy = CookieSecurePolicy.Always;
                opts.Cookie.IsEssential = true; // Make the session cookie Essential
            });
        }

Le due azioni aggiuntive di login/logout con CIE nell'HomeController risultano così:

        public IActionResult CieLogin()
        {
            IPAddress remoteAddress = HttpContext.Connection.RemoteIpAddress;
            string sessionID = HttpContext.Session.Id ?? "null";

            __log.Info($"[Session {sessionID}] CIE login action requested from IP " + remoteAddress);

            return Challenge(new AuthenticationProperties { RedirectUri = "/home/loggedin" }, CieDefaults.AuthenticationScheme);
        }

        public IActionResult CieLogout()
        {
            IPAddress remoteAddress = HttpContext.Connection.RemoteIpAddress;
            string sessionID = HttpContext.Session.Id ?? "null";

            __log.Info($"[Session {sessionID}] CIE logout action requested from IP " + remoteAddress);

            return SignOut(new AuthenticationProperties { RedirectUri = "/home/loggedout" }, CieDefaults.AuthenticationScheme);
        }

La nostra aspettativa è che la libreria di autenticazione usi gli stessi punti di ritorno (/home/loggedin e /home/error) di SPID, dove abbiamo il codice di estrazione dei dati dell'utente e di redirect alle fasi successive dell'applicazione.

Purtroppo, come anticipato, l'autenticazione via CIE cade sempre nel caso /home/error con questo messaggio Errore generico. Prova ad autenticarti più tardi., e non capiamo dove sia il problema. L'applicazione è registrata correttamente sul portale di Federazione e per i test usiamo una carta da un kit di test ufficiale.

Le versioni delle librerie che stiamo usando sono:

Potete aiutarci? In alternativa, avete un esempio funzionante di applicazione AspNetCore che integra entrambe le librerie? Grazie in anticipo.

danielegiallonardo commented 11 months ago

Salve, riuscite ad estrarre maggiori informazioni sull'errore lanciato, magari usando l'evento OnAuthenticationFailed?

gianlucabertani commented 11 months ago

Nell'AuthenticationFailed vediamo la stessa eccezione che poi ci arriva nella /home/error, la riporto qui:

18/12/2023 17:27:56.549 ERROR [19] SPID Authentication failed: SpidException - Errore generico. Prova ad autenticarti più tardi.
SPID.AspNetCore.Authentication.Exceptions.SpidException: Errore generico. Prova ad autenticarti più tardi.
   at SPID.AspNetCore.Authentication.Helpers.BusinessValidation.ValidationCondition(Func`1 condition, SpidException error)
   at SPID.AspNetCore.Authentication.Saml.SamlHandler.ValidateAuthnResponse(ResponseType response, AuthnRequestType request, IdentityProvider identityProvider, String serializedResponse)
   at SPID.AspNetCore.Authentication.SpidHandler.ValidateAuthenticationResponse(ResponseType response, AuthnRequestType request, AuthenticationProperties properties, String idpName, String serializedResponse)
   at SPID.AspNetCore.Authentication.SpidHandler.HandleRemoteAuthenticateAsync()

La cosa strana, però, è che si tratta di un'eccezione SPID, mentre invece stiamo testando l'autenticazione con CIE (l'authentication scheme che passiamo è CieDefaults.AuthenticationScheme, come si può vedere dalle due azioni che ho riportato pi sopra). Inoltre l'evento ci arriva sullo SpidEventLogger, invece che sul CieEventLogger.

Spero che questo sia utile. Se ci sono altre informazioni che possono servire dal context fammi sapere che le riporto. Intanto grazie.

danielegiallonardo commented 11 months ago

Fate attenzione alle URL di ritorno configurate nei metadata di CIE. Sembra che puntino alle url di SPID (dal momento che risponde l'authenticator di SPID). Gli endpoint riportati in SingleSignOnService e SingleLogoutService dei metadata, dovrebbero essere diversi tra SPID e CIE, e dovrebbero puntare alle diverse callback, i cui default sono /signin-spid, /signout-spid, /signin-cie e /signout-cie

gianlucabertani commented 11 months ago

Ok, grazie, probabilmente il problema è proprio quello. Ti chiedo però dove configurare questi end-point, perché per SPID vedo due parametri nell'appsettings.json:

  "Spid": {
    [...]
    "CallbackPath": "/sso",
    "RemoteSignOutPath": "/slo"
    [...]

ma per CIE non vedo due parametri equivalenti. Forse sono nascosti?

gianlucabertani commented 11 months ago

Scusa, ho visto ora che è scritto nella documentazione. Ignora il messaggio precedente.

gianlucabertani commented 11 months ago

Il problema era quello. Risolto tutto, grazie mille! 🙌🏼