Misja: uwierzytelniać klientów korzystających z Google Apps za pomocą SAML i Active Directory Federation Services.

Niestety Google nie udostępnia Federation Metadata więc trzeba ręcznie skonfigurować Relying Partner Trust.

Opis do tego jest niemalże wszędzie, jednak gdyby ktoś nie mógł tego znaleźć:

Po stronie Google ustawiamy:

  1. Sign-in page URL https://naszadomena.com/adfs/ls  
  2. Sign-out page URL https://naszadomena.com/adfs/ls/?wa=wsignoutcleanup1.0  
  3. Change password URL https://nasza_strona_do_zmiany_hasla.naszadomena.com  

Przy czym ostatnie pole jest nieobowiązkowe, nawet nigdy nie widziałem żeby gdzieś była użyta jego wartość.

Dodatkowo należy zaimportować certyfikat używany przez ADFS do podpisywania tokenów (token-signing) wyciągnięty wcześniej za pomocą konsoli MMC dla ADFS 2.0

Warto też zaznaczyć "Use a domain specific issuer " żeby zapytania przychodziły z adresu  https://www.google.com/a/naszadomena.googleapps.pl/acs zamiast z https://google.com

Po stronie ADFS trzeba dodać nowy Relying Party Trust:

Wybieramy ręczne wpisanie danych

  1. Profil ADFS 2.0
  2. Pomijamy certyfikaty (zostaną użyte domyślne)
  3. Włączamy protokół SAML i jako service URL wpisujemy:  https://www.google.com/a/naszadomena.googleapps.pl/acs 
  4. Jako relying trust identifier podajemy:  https://www.google.com/a/naszadomena.googleapps.pl/acs

Do Relying Party Trust dodajemy Claim rules wysyłający LDAP atrybut e-mail jako Name ID.

I tyle.Powinno działać, no prawie działa bo wylogowanie jest nieprzewidywalne. Raz wylogowuje poprawnie, raz pojawia się komunikat błędu ADFS, innym razem pojawia się błąd na stronie Google. Zero determinizmu, zdarzenia wydają się być całkowicie losowe.

Problem wynika prawdopodbnie z tego, że Google źle przygotowuje zapytanie SAML do wylogowania i parametry są niewłaściwie parsowane. Tudzież ADFS nie do końca jest zgodny ze standardem i nie potrafi wyciągnąć informacji z prawidłowego zapytania generowanego przez Google. W wyniku czego nie udaje się wygasić poprawnie wszystkich cookies, u klienta. Tutaj należy pamiętać, że funkcja wylogowywania w SAML jest opcjonalna :-)

W każdym razie przeładowanie strony https://adfs.naszadomena.pl/adfs/ls/?wa=wsignoutcleanup1.0 bez  dodatkowych parametrów wylogowuje skutecznie.

Jako, że nie udało mi się znaleźć rozwiązania zastosowałem proste obejście polegające na tym, że w przypadku błędu wylogowywania przekierowuję ponownie na stronę wylogowania. Co prawda można się trochę zapętlić ale jak narazie nie udało mi się doprowadzić to takiej sytuacji.

Do pliku error.aspx.cs dodałem (kod jest zależny od wersji językowej serwera ADFS, pewnie można sprawdzać sam kod błędu ale tego nie testowałem)

if (Exception.Message == "MSIS7055: Not all SAML session participants logged out properly. It is recommended to close your browser.")
    {
        Response.Redirect("?wa=wsignoutcleanup1.0");
    }

Zmodyfikowany plik znajduje się załączniku error.aspx.cs