fbpx
devstyle.pl - Blog dla każdego programisty
devstyle.pl - Blog dla każdego programisty
6 minut

Social-logowanie w .NET. Po co, dlaczego i jak?


11.04.2017

Po dziś dzień standardowym “pierwszym krokiem” przy tworzeniu wielu aplikacji jest wygenerowanie tabeli Users z kolumnami Username i Password. Ewentualnie, jeśli ktoś jest bardziej wniknięty, to jeszcze Salt. Po co?

Jak to po co? Żeby dać użytkownikom możliwość zalogowania się do aplikacji, prawda? Czyli UWIERZYTELNIENIA. Ale… to chyba najgorszy możliwy sposób.

Dlaczego tego nie robić?

Czy jesteś w stanie zagwarantować, że Twoje dane są tak bezpieczne jak że aż bardzo bezpieczne?
Czy chcesz pisać masę kodu odpowiedzialną za ustawianie, resetowanie i przypominanie haseł?
Czy umiesz zaimplementować tzw. muti-factor authentication (czyli logowanie z pomocą jednorazowych generowanych haseł albo SMSów)?
Czy masz czas na radzenie sobie z niedocierającymi mailami?

Ja, pisząc aplikację prezentującą informacje o Uczestnikach Daj Się Poznać 2017 odpowiedziałem sobie szczerze: nie, nie, i nie. I jeszcze raz NIE.

Alternatywa

Przecież KTOŚ już to zrobił! Niejeden system zaimplementował to wszystko i ma rzesze ludzie dbających o to, by to działało. Ba, te systemy mają miliony użytkowników, na co dzień weryfikujących poprawność wszystkich tych mechanizmów. I ja mogłem tego użyć. Za friko.

W tym tekście przedstawiam krok po kroku “jak zaimplementować logowanie ‘social providerem’ w swojej aplikacji .NET“. Po więcej mięska, z tłem, teorią itd. odsyłam do podcasta: DevTalk#18 – O tożsamości z Tomaszem Onyszko. Bardzo polecam.

Wiele osób ma konto na Facebooku, Google, Twitterze czy MS Live. A jeśli targetujemy programistów to także na GitHub. Nie ma absolutnie żadnego sensu w wymyślaniu koła na nowo. I dodatkowo zmuszaniu ludzi do zakładania kolejnego konta w kolejnym miejscu w internecie.

Jak?

Poniżej w kilku prostych krokach dodamy możliwość uwierzytelnienia się w aplikacji .NETowej (webowej) poprzez Facebook, Google i GitHub. Tak jak można to zrobić na stronie DSP’17.

SimpleAuthentication

Po pierwsze: znajdujemy odpowiednią bibliotekę, która poradzi sobie z kodem infrastrukturalnym. Można to napisać samemu (robiłem to i polecam, fajna zabawa) ale raczej w hobbystycznie, a nie produkcyjnie. W .NET z pomocą przychodzi SimpleAuthentication (kiedyś: World Domination). Działa świetnie, gdy już poradzimy sobie z nienajlepszą dokumentacją i dość mylącymi “projekcikami pobocznymi”.

Wystarczy:

Install-Package SimpleAuthentication.Core

A potem połączenie z odpowiednim frameworkiem. W moim przypadku:

Install-Package SimpleAuthentication.Mvc4

Ewentualnie możemy dorzucić kilka dodatkowych “providerów”, tzw. “extrasów”. Na przykład integracja z GitHubem jest dostępna w tym pakiecie:

Install-Package SimpleAuthentication.ExtraProviders

Login URL

Strona zalogowania jest banalnie prosta, wystarczy wylistować listę wspieranych linków… i ewentualnie podpiąć je pod jakieś ikonki. Facebook będzie wyglądał tak:

<a href="@Url.RedirectToProvider("facebook")"><img src="/Content/social-img/facebook_32.png" alt="Login with your Facebook account." /></a>

I wsio. Wygeneruje to taki URL:

http://example.com/authentication/redirect/facebook

Obsługą tego żądania, odpowiednim redirectem, zajmie się już biblioteka. Użytkownik zostanie przekierowany na stronę Facebooka (albo innego providera), gdzie zaakceptuje co jest do zaakceptowania. A potem wróci do nas i musimy go przytulić, implementując interfejs IAuthenticationCallbackProvider. Przykłady znajdziesz tutaj, na WIKI. Albo poniżej (z tym że to nie robi niczego sensownego):

public class MyAuthenticationCallbackProvider : IAuthenticationCallbackProvider
{
    public ActionResult Process(HttpContextBase context, AuthenticateCallbackData model)
    {
        return new RedirectResult("/", true);
    }

    public ActionResult OnRedirectToAuthenticationProviderError(HttpContextBase context, string errorMessage)
    {
        return new RedirectResult("/", true);
    }
}

To jest moment, w którym otrzymujemy informację: “tak, to faktycznie jest ziomeczek posiadający konto na portalu X“. Dostaniemy też jakieś ID, username, czasami e-mail, czasami link do fotki… I musimy coś z tym zrobić.

CO zrobić? To zależy. Ja dodaję te dane do własnej bazki, by mieć “na później”. Prawdopodobnie przyda się też wygenerować cookie… czyli zaimplementować nad tym mechanizem normalne Forms Authentication. Ale to nie jest temat na dzisiaj.

Bo jeszcze nie koniec!

Social apps

Skąd Facebook, Google, GitHub czy Twitter wiedzą jaka strona żąda uwierzytelnienia? Z przesłanych tajnych wartości, tzw. “KEY” oraz “SECRET”. Wartości te generowane są dla APLIKACJI.

Chcesz umożliwić zalogowanie się u Ciebie przez Facebooka? Musisz pójść pod ten adres i stworzyć własną aplikację na Facebooku! GitHub? To będzie TUTAJ. A dla Google: TUTAJ.

Nadajemy własną nazwę, dorzucamy ikonkę. Ustawiamy “redirect URL”, czyli dokładny adres, pod którym nasza aplikacja czeka na zalogowanych userów. W moim przypadku, na przykład dla Google, jest to: http://uczestnicy.dajsiepoznac.pl/authentication/authenticatecallback?providerkey=google .

Uwaga: localhost nie wszędzie działa! I czasami można zdefiniować tylko jeden taki URL, więc najwygodniej jest po prostu od razu pchać to do testów na jakiś hosting, pod jakąś domenę.

Z ustawień aplikacji kopiujemy wygenerowane wartości KEY i SECRET i w jakiś sposób transportujemy je do własnego web.configa. Można je tam po prostu wkleić, ale wtedy trzeba uważać na pushe do publicznych repo :).

Kolejne kroki

Najlepsze w całej procedurze jest to, że to już wszystko. Koniec. F5 i działa.

Ktoś zapomniał hasła? Nie interesuje mnie to, hasła nie ma u mnie. Ktoś chce hasło zmienić? Niech idzie tam, gdzie je definiował. Wreszcie: z mojej aplikacji nastąpi wyciek danych? No szkoda, wstyd i w ogóle, ale… nikomu szkoda się nie stanie, bo nie przechowuję żadnych wrażliwych danych!

Polecam, zachęcam, pozdrawiam, całuję.

Notify of
Michal Dymel

Fajny wpis.
Niestety nie wszyscy mają konta na portalach, jak mają to mogą mieć akurat w takim, którego nie zaimplementowaliśmy, a nawet jeśli to mogą nie chcieć przekazywać dodatkowych danych (np. fotki). Wtedy mamy do wyboru – albo świadomie rezygnujemy z takich użytkowników (w przypadku DSP pewnie spokojnie można było tak zrobić), albo jednak implementujemy obsługę również u siebie. Wtedy zamiast robić to samemu, lepiej wykorzystać jeden z dostępnych frameworków, np. ASP.NET Identity Framework.

Tomek Onyszko

Hej Michał, Jako że już mnie Maciek wywołał do tablicy trochę to odpowiem :) – nie, wtedy też nie musisz trzymać rzeczy u siebie albo przynajmniej nie robić tego samodzielnie, kilka alternatyw 1. Bierzesz wspaniały projekt jakim jest Identity Server i implementujesz to w ramach swojego projektu. Wtedy oprócz tego wszystkiego co napisał Maciek masz też zapewnioną obsługę lokalnych kont (albo możesz ją sam zbudować) -> dalej, doczytaj -> https://github.com/IdentityServer 2. Bierzesz na tapetę wspaniałą usługę jaką jest Auth0 – jest płatna ale … whoo hoo – do 7k userów jest free -> https://auth0.com/pricing zapewnia Ci też obsługę lokalnych kont… Read more »

Michal Dymel

Dzieki :) Tak, w nowym projekcie uzywam wlasnie IdentityServer + IdentityFramework (post coming ;)). Właśnie o to mi chodziło w ostatnim zdaniu, że lepiej nie robić tego samodzielnie :) A co do zmuszania usera do założenia konta gdzieś… Uważam, że nie wszędzie to przejdzie. Jeśli robisz produkt/usługę, którą chcesz sprzedawać, pewnie będziesz chciał mieć pełną kontrolę nad ‘flow’ użytkownika w rejestracji i optymalizować go tak, żeby mieć jak największą konwersję i sprzedaż. Wymuszanie zostawiania maila gdzieć trochę się z tym kłóci… Poza tym, nie każdy user będzie chciał to zrobić, a Ty w takim przypadku zdecydowanie chcesz każdego usera i… Read more »

Tomek Onyszko

Użycie zewnętrznego konta nie wyklucza tego, że u siebie przeprowadzasz go przez “flow” rejestracji i zebrania danych u siebie. W przypadku takiego Azure AD B2C możesz zrobić cuda niewidy używając czegoś co się nazywa advanced policy -> https://github.com/Azure-Samples/active-directory-b2c-advanced-policies Przykładowy scenariusz: 1. User loguje się kontem “nie wiadomo skąd” (wiadomo, jeden z twoich idp) 2. Grzecznie prosisz go o uzupełnienie profilu i zgodę na przetwarzanie danych. Zapisujesz to w GraphAPI 3. Sprawdzasz czy masz już go w bazie swojego newsletter, jeżeli nie to pytasz się czy chce dostawać newsletter i jak często 4. Pytasz się grzecznie o numer telefonu i potwierdzasz… Read more »

Michal Dymel

Jasne – jak user ma konto w którymś ze wspieranych przez nas idp, sprawa jest prosta. Jeśli jednak targetujemy w użytkowników z całego świata, można się na tym troche przejechać. Dlatego, moim zdaniem, niektóre serwisy wymagają wsparcia tworzenia konta bezpośrednio u nas.

Marcin

patrze na to Azure AD B2C, i nie widze nigdzie free dla 50k ,
pisze o 500k obiektach free. Ale jak daje kalkulator, to jednak wyswietla ceny. Co robie zle? :)

Tomek Onyszko

https://azure.microsoft.com/en-us/pricing/details/active-directory-b2c/

STORED USER/MONTH
First 50,000 Free

AUTHENTICATIONS/MONTH
First 50,000 Free

Marcin

a widze, dzieki, i chyba zle na cennik patrzylem.
https://azure.microsoft.com/en-us/pricing/calculator/?service=active-directory-b2c

Czy dobrze rozumiem, ze jak chce np aby klient mogl sie logowac przez google, facebook, to mam Multi-Factor Authentications x2 i place 0,06 dolara miesiecznie oprocz tych 50k free userow? :)

Kamil Ławniczak
Kamil Ławniczak

@Michal Dymalel z góry sorry ale niestety dtego typu wymówka, chaczy juz o złą wolę. I Na końcu wyjaśnię dlaczego i nie zamierzam użyć argumentów o pragmatyźmie. Najpierw jednak post. Ale przed jeszcze issue: Panie procencie czemu wciskam małpkę i muszę pisać pełne imię i nazwisko ? ?? Czytelnicy upraszają się o imprułw komentarzy w sprintlogu :) Post: Racja, święta racja ale i gównoracja ponieważ: – Gdy widzę formularze do logowania i http przed adresem, usilnie upraszam o publikację lokalizacji. Atomówka sprawiedliwości już leci… – Do dziś pamiętam, jak najdalej 4 lat wstecz miałem taska “Improvement” polegającego na zabezpieczeniu stringów… Read more »

Tomek Onyszko

Bardzo słuszna uwaga odnośnie audytów, zgodności z wymaganiami itp.

Tomek Onyszko

Za MFA placisz per-auth. Płacisz za auth usera nie za ilość social logins, które ma przypisane. Czyli – user może logować się FB/Google ale po zalogowaniu chcesz na nim wymusić MFA -> 0,03 USD. There is no free lunch jeżeli chodzi o Telco :).

Krystian Kolad
Krystian Kolad

To teraz wyczekiwać posta o Forms Authentication. Bardzo dobry content ;D Pozdrawiam

tomaszk-poz
tomaszk-poz

Takie rzeczy to można robić na publicznych portalach, mam system dla instytucji, gdzie ten numer nie przejdzie, bo a) użytkownicy nie muszą mieć FB/Google/Twittera b) firma może mieć awarię internetu i wtedy klops. Tak więc nie ma co tego przedstawiać jako coś cudownego, bo można wtopić. Poza tym np. ja jako mający konto google nie chciałbym, aby to konto było wiązane z jakimś serwisem, ja tam im nie ufam żadnej ze stron i nie chcę, że informacja gdzieś się plątała po internecie, wolę klasyczne rozwiązanie. Tak wiem, w tym tajnym serwisie mogą dziać się dziwne rzeczy, ale ja do tego… Read more »

Tomek Onyszko

Hej Tomasz, Tak jak napisałeś w większość przypadków, to dotyczy stron dla consumers. Wewnętrz firmy to wygląda inaczej a o takim rozwiązaniu piszesz jako rozwiązaniu u siebie (sądząc po tym braku internetu). Chociaż uwierz – to też się zmienia i coraz częściej częścią firmy jest ktoś, kto nigdy w tej firmie się nie pojawia i w zasadzie potrzebuje dostępu tylko do kilku rzeczy. I usługi pod to też się zmieniają – -taka dygresja. Maciek nie przedstawił tego jako cudownego rozwiązania ale jako rozwiazanie dla konkretnego problemu. Jeżeli nie aplikuje sie do twojej systuacji to OK, ale pomyśl – będziesz budował… Read more »

Kurs Gita

Zaawansowany frontend

Szkolenie z Testów

Szkolenie z baz danych

Facebook

Książka

Zobacz również