Thursday, June 4, 2020

Corona hobbies

Friday, May 29, 2020

SessionAuthenticationModule::OnAuthenticateRequest is broken

Relying on base class library modules should be safe. Unless it's the SessionAuthenticationModule that misses correct handling of some edge cases. Here's the story.
We use the SessionAuthenticationModule for ages. It's great and reliable in 99.99% of cases. However, there could be a case where there's something wrong with the cookie. The cookie is there but it has been somehow altered in the browser. Either it doesn't contain a valid base64 stream or the stream is valid but there's no XML inside the stream.
The problem is that the SAM first tries to decode the cookie
protected virtual void OnAuthenticateRequest(object sender, EventArgs eventArgs)
{
 HttpApplication httpApplication = (HttpApplication)sender;
 HttpRequest request = HttpContext.Current.Request;
 SessionSecurityToken sessionSecurityToken = null;
 if (!TryReadSessionTokenFromCookie(out sessionSecurityToken) && string.Equals(request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
 {
               ..
Now, guess what happens when TryReadSessionTokenFromCookie throws an exception? Well, the exception is not caught and thus it's escalated to your code. And now
  • what your code does when an exception occurs? You catch it by a top level exception handler and you possibly shows a generic error page.
  • what a user does when they see the error page? They refresh the browser.
  • is the error gone? Nope, the flawed cookie is still there
What you get is a nice stacktrace of the problem
   w System.Convert.FromBase64_Decode(Char* startInputPtr, Int32 inputLength, Byte* startDestPtr, Int32 destLength)
   w System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength)
   w System.Convert.FromBase64String(String s)
   w System.IdentityModel.Services.ChunkedCookieHandler.ReadInternal(String name, HttpCookieCollection requestCookies)
   w System.IdentityModel.Services.ChunkedCookieHandler.ReadCore(String name, HttpContext context)
   w System.IdentityModel.Services.CookieHandler.Read(String name, HttpContext context)
   w System.IdentityModel.Services.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken)
   w System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs)
My first attempt to this was to replace the cookie handler by a custom cookie handler. It's not that obvious how to do that but anyway
public class CustomCookieHandler : System.IdentityModel.Services.CookieHandler
{
    private CookieHandler _handler; // = new ChunkedCookieHandler();

    public CustomCookieHandler(CookieHandler handler)
    {
        if ( handler != null )
        {
            this._handler = handler;

            this.Name       = handler.Name;
            this.Path       = handler.Path;
            this.RequireSsl = handler.RequireSsl;
        }
        else
        {
            throw new ArgumentNullException();
        }
    }

    // public override 

    protected override void DeleteCore(string name, string path, string domain, HttpContext context)
    {
        _handler.Delete(name, path, domain, context);
    }

    protected override byte[] ReadCore(string name, HttpContext context)
    {
        try
        {
            return _handler.Read(name, context);                
        }
        catch
        {
            return null;
        }
    }

    protected override void WriteCore(byte[] value, string name, string path, string domain, DateTime expirationTime, bool secure, bool httpOnly, HttpContext context)
    {
        _handler.Write(value, name, path, domain, expirationTime, secure, httpOnly, context);
    }
}
This could be plugged into the pipeline somewhere early with
FederatedAuthentication.FederationConfigurationCreated +=
        ( s, fede ) =>
        {
            fede.FederationConfiguration.CookieHandler = new CustomCookieHandler(fede.FederationConfiguration.CookieHandler);
        };
Case closed? Not really, looks like the base64 cookie data can be valid but what comes out is not XML and is not parsed! The exception changes to
   w System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, XmlException exception)
   w System.Xml.XmlUTF8TextReader.VerifyNCName(String s)
   w System.Xml.XmlUTF8TextReader.ReadQualifiedName(PrefixHandle prefix, StringHandle localName)
   w System.Xml.XmlUTF8TextReader.ReadStartElement()
   w System.Xml.XmlUTF8TextReader.Read()
   w System.Xml.XmlBaseReader.MoveToContent()
   w System.IdentityModel.Services.SessionAuthenticationModule.GetKeyId(Byte[] sessionCookie)
   w System.IdentityModel.Services.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie)
   w System.IdentityModel.Services.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken)
   w System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs)
What this custom cookie handler should do would be then to make sure whatever is read, can be interpreted as XML further down. But this would slow down the custom cookie handler dramatically! Each time a cookie is read, it would be first tried to contain an XML by my custom code and then read as XML again by the existing code.
An ultimate solution? Delete your SAM cookies in the error page. As simple as that. A side effect is users are logged out of the application after an exception is caught by the top level exception handler.

Thursday, May 21, 2020

Materiały edukacyjne - Repository, Unit of Work

Jak implementować wzorce Repository i Unit of Work żeby architekturze pomagać a nie przeszkadzać?

Corona hobbies

It's not that you should only stay home and work remotely. It's a perfect time to spend time on your hobbies. My primary hobby is music and I wish I could spend more time practicing.

Thursday, May 14, 2020

Materiały edukacyjne - Inversion of Control

O tym czym jest Inversion of Control, czym jest kontener Dependency Inversion, jak go używać, czym jest Service Locator i dlaczego jest antywzorcem i wreszcie, dlaczego ultymatywnym rozwiązaniem dla architektury opartej o DI jest Local Factory.

Monday, May 4, 2020

OldMusicBox.ePUAP.Client 0.60

Biblioteka kliencka OldMusicBox.ePUAP.Client nad którą pracuję w wolnych chwilach osiągnęła kolejny ważny punkt rozwoju. Do tej pory za pomocą biblioteki możliwe było logowanie przez Profil Zaufany oraz obsługa funkcji do podpisywania dokumentów przez ePUAP.
W wersji 0.60 która została opublikowana na NuGet biblioteka dodaje podstawowy zakres wsparcia w komunikacji z usługą Elektroniczne Skrzynki Podawcze (ePUAP ESP). Podstawowy zakres obejmuje na tę chwilę
  • WS-Skrytka
    • Nadaj
  • WS-Pull
    • DokumentyOczekujace
    • PobierzNastepny
    • PotwierdzOdebranie
  • WS-ZarzadzanieDokumentami
    • DodajDokument
W kolejnych wersjach zostanie dodane wsparcie dla podstawowych usług, w tym WS-Doreczyciel i WS-obslugaUPP.
Przypominam że kod jest publikowany na licencji AGPL i jako taki ma charakter wyłącznie edukacyjny/niekomercyjny. Proszę o kontakt w razie potrzeby wykorzystania tej implementacji do innych celów.

Wednesday, April 29, 2020

Materiały edukacyjne - WPF

Tym razem programowanie pod Windows i wprowadzenie do WPF z przykładami.

Thursday, April 23, 2020

Materiały edukacyjne - wzorce czynnościowe

Nowe materiały edukacyjne dodawane są na bieżąco, dlatego zachęcam do zaglądania na profil na YouTube. Na zachętę - materiał poświęcony wzorcom komunikacyjnym, można dowiedzieć się czym różnią się Mediator, Observer i Event Aggregator. Na deser Memento i pomysł na Undo/Redo.

Wednesday, March 25, 2020

Koronawirus - dodatkowe materiały edukacyjne

Zajęcia stacjonarne w Instytucie informatyki UWr, gdzie pracuję, nie odbywają się z wiadomych powodów. W związku z tym przygotowuję dla studentów materiały online i są one dostępne publicznie.
Aktualnie, w semestrze letnim prowadzę dwa wykłady, Programowanie pod Windows i Projektowanie obiektowe oprogramowania. Zapraszam do obejrzenia materiałów obu wykładów. Jeśli ograniczenia zostaną utrzymane, należy spodziewać się kolejnych wykładów udostępnianych w ten sposób.

Tuesday, February 18, 2020

OldMusicBox.ePUAP.Client released to NuGet

The ePUAP Client has been released to NuGet. It allows your app to perform the SSO but it also shows how to sign arbitrary XML documents using AddDocumentToSigning/GetSignedDocument functions.
The documentation as well as an example application are provided at the GitHub project page.
I hope this would be usedful for anyone who wants to learn how ePUAP integration works. The next step is Węzeł Krajowy.

Monday, February 17, 2020

OldMusicBox.ePUAP.Client milestone reached

I am happy to announce that the ePUAP client library, the OldMusicBox.ePUAP.Client has reached its first important milestone where you can actually single sign on to your app through ePUAP.
This means that all three steps work correctly:
  1. The SAML2 AuthnRequest is correctly issued
  2. The SAML2 ArtifactResolve is correctly issued
  3. The ePUAP getTpUserInfo is correctly called
The road map for few days is:
  • Add support for Single Log Out (LogoutRequest, LogoutResponse)
  • Add support for document signing (tpSigning interface)
  • Release the Client to NuGet
Please note that while the SAML2 component is licensed under the MIT license, the ePUAP Client is licensed under the AGPL-3. However, you are free to download the code and use it according to the license. Any issues or feature requests are welcome.

Tuesday, February 11, 2020

OldMusicBox.ePUAP.Client announcement

I've just created a repo for the upcoming independent .NET ePUAP Client. The goal here is to provide an open source implementation under AGPL-3.0 license. Please keep your fingers crossed and expect working code in a week or two.

Monday, February 10, 2020

OldMusicBox.Saml2 0.65 published

I hereby announce that the very first public version of the SAML2 library has been published on NuGet. This first release contains the core part of the SAML2 client interface, including REDIRECT/POST/ARTIFACT binding and LogoutRequest/LogoutResponse support.
The next step is to build the ePUAP client library on top of this SAML2 implementation. I will officially announce it in a couple of days.

Tuesday, January 28, 2020

An independent SAML2 client/server library

I started to work on an independent SAML2 client/server library that would target classic .NET Framework. The source code is available on GitHub, the repo's name is OldMusicBox.Saml2. I decided to release it under MIT license.
The long-time goal is to cover most SAML2 features and target .NET Core.
The short-time goal is to have basic features quickly so that it's possible to use this in other projects. In particular, based on feedback I get from people, I believe the community needs an independent Profil Zaufany client library. This one, when it's ready, will be released under more strict license (so that I could control where and how it's used). The plan is to make it available in few weeks and somewhere in future add the support of the Krajowy Węzeł Identyfikacji Elektronicznej.