Autentizace uživatelů v ASP.NET aplikaci pomocí Facebooku

Tomáš Herceg       21.09.2013       ASP.NET WebForms, HTTP/HTML       14096 zobrazení

V poslední době stále častěji tvůrci webových aplikací opouštějí vlastní autentizaci pomocí jména a hesla a umožňují svým uživatelům přihlašovat se pomocí účtu na sociálních sítích nebo pomocí jiných služeb, například Microsoft Live ID. V tomto článku si ukážeme napojení ASP.NET aplikace na přihlašování pomocí Facebooku pomocí knihovny Microsoft Web Pages OAuth.

Využít pro přihlašování účty na sociálních sítích může být dobrá alternativa ke klasickému přihlašování řešenému vlastními silami. Pro uživatele je poměrně nepraktické pamatovat si pro každý web přihlašovací jméno a heslo, a jen velmi málo uživatelů používá pro každou službu různá hesla, což má nepříznivé bezpečnostní dopady. Spousta webů totiž ukládá hesla do databáze v plaintextu a v případě, že by se k databázi někdo dostal, hrozí, že se nabourá i do jiných aplikací. Pravděpodobnost, že uživatel používá stejné jméno a heslo i jinde, není zrovna malá, ne každý si zapamatuje 150 různých hesel a ne každý na správu hesel používá aplikaci (KeePass, Roboform apod.).

Navíc ve spoustě aplikací nepotřebujeme o uživateli vědět mnoho údajů. Často nám stačí pouze určit, že je to ten samý uživatel, co minule, a občas někde potřebujeme zobrazit jeho obrázek a jméno. V takovém případě je zbytečné a pracné implementovat vlastní mechanismy zakládání uživatelských účtů, proceduru pro změnu a obnovení ztraceného hesla atd. Přihlašování pomocí Facebooku nebo jiné sociální sítě či služby tedy může být v mnoha případech užitečné jak pro uživatele (nemusí si pamatovat nové heslo), tak pro vývojáře aplikace (nemusí trávit čas implementací).

Dobrá zpráva je, že přihlašování nejčastějších sociálních sítí a služeb již řeší jedna knihovna z frameworku ASP.NET Web Pages. Třídy, které tuto funkcionalitu zajišťují, můžeme pochopitelně použít i v ASP.NET WebForms či MVC.

 

Jak přihlašování pomocí externího účtu funguje?

V případě klasického přihlašování pomocí Forms autentizace (komponenta Login v ASP.NET) je princip jasný – uživatel zadá jméno a heslo přímo na našem webu, tlačítkem udělá postback, komponenta Login pomocí membership providera (nebo v události OnLoggingIn) zjistí, jestli je jméno a heslo správné, a pokud ano, vystaví uživateli autentizační ticket. Ticket je zašifrovaná a digiálně podepsaná hodnota, která obsahuje uživatelské jméno a datum platnosti a typicky se ukládá do cookies.

Dokud uživatel v HTTP požadavcích posílá platný ticket, ASP.NET aplikace jej považuje za přihlášeného, a fungují nám všechny mechanismy funkcí Membership.GetUser() počínaje, přes Page.User.Identity.IsAuthenticated až po komponenty LoginView a LoginStatus.

Přihlašování pomocí Facebooku (anebo jiných služeb používajících OAuth autentizaci) funguje takto:

  1. Přesměrujeme uživatele na přihlašovací stránku, která je na doméně facebook.com. Typicky v URL této stránky pošleme adresu, kam nás má Facebook vrátit v případě, že se přihlašování podaří.
  2. Uživatel se na této stránce přihlásí, Facebook ověří, jestli je jméno a heslo správné, ještě si typicky od uživatele nechá potvrdit, že chce povolit určitá oprávnění vaší aplikaci.
  3. Následně je uživatel přesměrován zpět do naší aplikace na cílovou stránku a v URL parametrech najdeme informace o tom, zda-li se přihlášení povedlo. V URL také najdeme takzvaný access token, což je autentizační ticket Facebooku. Tento token se nám bude hodit, pokud budeme chtít číst nějaká data z Facebook Graph API – například jméno aktuálního uživatele, seznam přátel atd.
  4. V neposlední řadě v URL najdeme zakódované ID uživatele, které používá Facebook. Podle něj dohledáme uživatele v databázi naší aplikace a přihlásíme jej tak, že mu vystavíme klasický autentizační ticket. Tím zajistíme kompatibilitu s předchozím postupem. Jediný údaj, který pro vystavení autentizačního ticketu potřebujeme, je uživatelské jméno. V případě, že naše aplikace nemá v databázi tabulku uživatelů a nepoužívá ani membership providera, můžeme jako uživatelské jméno použít rovnou ID uživatele z Facebooku.

 

Krok 1: Přidání knihovny Microsoft WebPages OAuth

Nejprve musíme do projektu přidat knihovnu Microsoft Web Pages OAuth. Nejjednodušší způsob je použít balíčkovací systém NuGet (je součást Visual Studia 2012, do verze 2010 je jej potřeba doinstalovat). Stačí pravým tlačítkem kliknout na projekt v Solution Exploreru a zvolit Manage NuGet Packages. Nalevo zvolíme sekci Online a do vyhledávacího okénka v pravém horním rohu napíšeme “web pages”.

Přidání balíčku Web Pages OAuth

Instalace chvíli trvá, neboť knihovna má poměrně dost závislostí. NuGet stáhne všechny potřebné knihovny a dá je do referencí projektu.

 

Krok 2: Založení aplikace na Facebooku

Abychom se proti Facebooku mohli autentizovat, musíme dále založit novou aplikaci a získat Application ID a Application Secret. Přihlaste se tedy na portál http://developer.facebook.com a nahoře klikněte na záložku Apps. Dále klikněte na tlačítko Vytvořit novou aplikaci. Je třeba zadat název aplikace, který se bude zobrazovat uživatelům, a dále unikátní id aplikace, které mělo obsahovat jen malá písmena.

Vytvoření aplikace

Po proklikání průvodce (bude chtít ještě opsat text z obrázku) se nám vytvoří nová aplikace. Protože budeme přihlašování testovat, je vhodné jej hned povolit a zadat doménu, na níž aplikace poběží. Protože si s tím budeme hrát na localhostu, jako adresu pro návrat zadáme URL, na níž nám aplikace běží ve Visual Studiu, v mém případě tedy http://localhost:52522/Login.ashx. Login.ashx bude handler, na který nás Facebook přesměruje, a kde zjistíme, jak operace dopadla.

Nastavení přihlašování

Nyní pro nás budou důležitá pole App ID a App Secret, které budeme potřebovat v následujícím kroku. App Secret uchovávejte v tajnosti, pokud by došlo k jeho kompromitaci, vyresetujte jej příslušným odkazem a upravte v aplikaci.

 

Krok 3: Registrace providera v aplikaci

Do naší webové aplikace přidáme soubor Global.asax (pravým tlačítkem klikneme na projekt, zvolíme Add New Item a v seznamu vybereme Global Application Class). Upravíme metodu Application_Start následujícím způsobem:

protected void Application_Start(object sender, EventArgs e)
{
    RegisterAuthenticationProviders();
}

/// 
/// Registers the authentication providers.
/// 
private void RegisterAuthenticationProviders()
{
    Microsoft.Web.WebPages.OAuth.OAuthWebSecurity.RegisterFacebookClient("sem doplnit appId", "sem doplnit appSecret", "Facebook");
}

Nezapomeňte do kódu doplnit správné AppId a AppSecret z kroku 2, doporučuji tyto hodnoty dát do konfiguračního souboru, třeba do sekce appSettings. Pro účely ladění budete možná chtít používat jinou Facebook aplikaci než pro produkční prostředí, například kvůli nastavení domén a cílové stránky po přihlášení.

 

Krok 4: Přihlašovací stránka

Nyní místo přihlašovacího dialogu (nebo vedle něj, pokud chcete zachovat obě možnosti) umístíme tlačítko, které nás přesměruje na přihlašovací stránku Facebooku. Toto tlačítko bude volat následující funkci.

protected void FacebookLink_OnClick(object sender, EventArgs e)
{
    Microsoft.Web.WebPages.OAuth.OAuthWebSecurity.RequestAuthentication("Facebook", "~/Login.ashx");
}

Prvním parametrem funkce je ID providera, v našem případě Facebook. Knihovna Web Pages OAuth totiž podporuje kromě Facebooku další sítě, například Twitter nebo Windows Live ID. Druhým parametrem je URL, na níž máme být po příhlášení navráceni.

Tato funkce přesměruje uživatele na web Facebooku, kde se přihlásí, a následně nás vrátí zpět do naší aplikace, kde musíme výsledek přihlášení zpracovat.

Pozor, Facebook kontroluje, že se chcete vrátit na stejnou stránku, která je uvedena v detailu aplikace. Do returnUrl ale můžete přidávat URL parametry, což se hodí, pokud potřebujete přenést nějaké informace přes proces přihlášení.

 

Krok 5: Dokončení přihlášení

Přidáme do projektu handler Login.ashx (pravým tlačítkem na projekt, Add New Item a vybrat Generic Handler) a do metody ProcessRequest umístíme následující kód:

var result = Microsoft.Web.WebPages.OAuth.OAuthWebSecurity.VerifyAuthentication();
if (result.IsSuccessful)
{
    // přihlášení úspěšné
    var userId = result.ProviderUserId;
    // TODO: dohledat uživatele v databázi podle ID, případně mu založit účet

    // přihlásit uživatele
    FormsAuthentication.SetAuthCookie(username, true);
    context.Response.Redirect("~/Default.aspx");
}
else
{
    // přihlášení se nezdařilo
    context.Response.Redirect("~/LoginFailed.aspx");
}

Nejprve zavoláme funkci VerifyAuthentication, která se podívá do URL a rozparsuje parametry. Ve vlastnosti result.IsSuccessful pak zjistíme, zda-li jsme byli přihlášeni úspěšně. Logika, co dál dělat, pak už závisí na naší aplikaci.

Pokud máme někde v databázi seznam uživatelů, pak podle result.ProviderUserId, což je unikátní ID uživatele v rámci Facebooku, najdeme příslušného uživatele a pomocí funkce FormsAuthentication.SetAuthCookie mu vygenerujeme do cookie autentizační ticket, čímž jej přihlásíme. Pokud se přes Facebook přihlásil uživatel, kterého ještě neznáme, měli bychom mu účet založit, to opět závisí na logice aplikace. Je také možné, že v databázi seznam uživatelů vůbec uchovávat nechcete, pak stačí uživatele přihlásit a jako uživatelské jméno do funkce SetAuthCookie klidně můžeme přiřadit např. result.ProviderUserId. Tady chování záleží na aplikaci samotné.

Pokud se přihlášení nezdařilo, je vhodné o tom uživatele informovat a nabídnout mu, aby to zkusil znovu. V ukázce kódu přesměrujeme na stránku LoginFailed.aspx.

 

Krok 6: Zjištění jména uživatele a profilového obrázku

Zjistit URL profilového obrázku uživatele není nic těžkého, URL je v následujícím formátu:

var userImageUrl = "https://graph.facebook.com/" + result.ProviderUserId + "/picture?type=large";

Velikost obrázku určujete parametrem type – přípustné hodnoty jsou square, small, normal a large, podrobněji je to popsáno
v dokumentaci Facebooku.

Ke zjištění jména uživatele musíme použít Graph API – v dokumentaci se dočteme, že údaje o aktuálním uživateli najdeme na adrese https://graph.facebook.com/me. Pro použití této adresy ale musíme poslat ještě access token, což se dělá přidáním parametru access_token do URL. Pokud na takovouto adresu uděláme GET požadavek, Facebook nám vrátí informace o aktuálním uživateli (podle access tokenu) ve formátu JSON. Pak už jen stačí vytáhnout atribut name z odpovědi Facebooku a máme vyhráno.

Access token najdeme v proměnné result.ExtraData pod klíčem accesstoken.

// získat access token, který se používá pro dotazy v Graph API
var accessToken = result.ExtraData["accesstoken"];

// stáhnout detaily o aktuálním uživateli
var wc = new WebClient();
var data = wc.DownloadString("https://graph.facebook.com/me?access_token=" + accessToken);
                
// rozparsovat
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
dynamic parsed = serializer.DeserializeObject(data);
var userDisplayName = parsed["name"] as string;

Pokud potřebujete s Graph API komunikovat i jinde, než jen v handleru Login.ashx, je potřeba si access token někam uložit. Doporučuji jej uložit do databáze k příslušnému uživateli.

Pokud si chcete práci s Graph API usnadnit, doporučuji přidat do projektu NuGet balíček Facebook (www.facebooksdk.net). Zaslání požadavku a deserializaci JSONu za vás udělá sám a na jeden řádek kódu.

 

Přepnutí do produkčního prostředí

Jakmile budete mít aplikaci hotovou a nasazenou na finální URL, vraťte se na http://developer.facebook.com a přepněte aplikaci ze sandbox módu do ostrého režimu. Dále pak upravte adresu v sekci Přihlašování.

 

Podpora dalších sociálních sítí

Knihovna Web Pages OAuth umí i další providery, např. Twitter, LinkedIn, Microsoft Live ID nebo Google ID. Postup je obdobný – v Global.asax použijete k zaregistrování providera příslušnou metodu a zadáte application id a secret, které získáte na následujících stránkách:

A nakonec ve funkci RequestAuthentication do prvního parametru dáte ID providera, kterého chcete použít.

 

V tomto článku jsme si krok za krokem ukázali, jak napojit ASP.NET aplikaci na přihlašování pomocí externích účtů knihovnou Web Pages OAuth. Po návratu z přihlašovací stránky jsme uživateli vystavili klasický autentizační ticket, takže můžeme externí účty kombinovat s klasickým přihlašováním pomocí komponenty Login.

 

hodnocení článku

1 bodů / 1 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Mohlo by vás také zajímat

Tipy a triky pro ASP.NET - díl 2.: Komponenta pro editaci kolekcí pro ASP.NET

V tomto dílu seriálu o vývoji komponent v ASP.NET si ukážeme, jak do komponent deklarovat pokročilejší vlastnosti, jako třeba kolekce nebo šablony. Představíme si také, jak dělat podporu pro design režim a seznámíme se s mnoha dalšími věcmi.

jQuery a ASP.NET - díl 1.: Začínáme s jQuery

jQuery je dnes de facto standardem a ať už se nám to líbí nebo ne, nachází použití ve většině moderních webových aplikací. V tomto dílu si popíšeme základy práce s jQuery pro ty, kteří jej ještě nikdy neviděli.

Windows 8 nově s WinRT

 

 

Nový příspěvek

 

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

Knihovna Microsoft.Owin.Security

Taky jsem si s přihlašováním pomoci Facebooku hrál.

Knihovna DotNetOpenAuth.AspNet, kterou Microsoft.AspNet.WebPages.OAuth používá má jednu nevýhodu. Nejde v ní určit práva - scopes (https://developers.facebook.com/docs/ref....

Vždy je natvrdo použité volání s "email", což nemusí být vždy vyžadováno, a také pokud by jsme potřebovali načít z profilu uživatele další doplňující údaje tak nemůžeme práva přidat.

Ve VS2013 výchozí template bude použita připravovaná nová knihovna Microsoft.Owin.Security resp. Microsoft.Owin.Security.Facebook.

Ta je kompletně přeprogramovaná, používá OWIN (kdo zná tak uvítá) a Claims.

V ní lze při konfiguraci určit jaké scopes chceme použít. Z bezpečnostních důvodů se zde ale již po přihlášení nedostaneme k AccessTokenu, nicméně pokud potřebujeme donačíst další informace, můžeme to provést v OnAuthenticated providera. Viz. příklad:

var options = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions()
{
    AppId = "9999999999999999",
    AppSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType(),
    Scope = "email, user_birthday",
    Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider()
    {
        OnAuthenticated = (context) =>
        {
            string accessToken = context.AccessToken;
            var json = context.User;

            return System.Threading.Tasks.Task.FromResult(0);
        }
    }
};
nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Autentizace pomocí sociálních sítí

Je potřeba dobře zvážit, zda se vyplatí toto implementovat. Mnoho lidí ani v dnešní době nemá založen účet na žádné ze sociálních sítí, především starší uživatelé, kteří si ho pouze k tomuto účelu zcela jistě zakládat nebudou.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Jako alternativa je to super věc, ale určitě bych se bránil plnému nahrazení.

Ze zkušenosti, když ne na začátku, tak v průběhu rozvoje aplikace, stejně časem dojde k tomu, že bude bude třeba držet informace o uživateli, která ani v jedné ze služeb nejsou

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Myslím, že tento způsob přihlášení je vhodné implementovat právě kvůli opačnému problému. Lidé nechtějí mít další účet na nějaké další webové aplikaci. Přihlášení možné dostatečně širokým výběrem třetích stran pak pokryje a usnadní práci velkému množství uživatelů. Z pohledu prodeje to může být zásadní rozdíl - klasicky snadný nákup s co nejmenším počtem vyplňování a přemýšlení má vyšší šanci úspěchu. Rozhodně by ale měla (na většině webů) existovat možnost použít jméno a heslo.

Další zajímavou alternativou je přihlašování jednorázové pomocí odkazu v emailu.

Ale záleží na typu aplikace (cílovka uživatelů), množství času na vývoj atp.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

kladné hodnocení

Sám vyvíjím desktopovou aplikaci komunikující s Facebookem a toto jsem už dávno řešil také, proto mě článek zaujal.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback