Den ultimata utvecklarguiden till BankID
Att sätta upp en autentiseringslösning med hjälp av BankID kan vara något av en skrämmande uppgift om man ska vara ärlig. Det är väl dokumenterat, men det är många steg som måste göras, både i form av kod och i form av mer administrativa uppgifter för att få till en fungerande lösning. När du som utvecklare börjar läsa dokumentationen kring vad som krävs, så inser du snabbt att det kommer ta ett tag att få till på ett säkert och stabilt sätt. Det är där Active Login kommer in. Active Login är en smidig lösning för att snabbt komma igång med BankID autentisering och signering för .NET.
Men även om både BankID och Active Login är väl dokumenterade, så kan det vara lite struligt att komma igång. Av den anledningen så tänkte vi skriva en steg för steg beskrivning av vad som behövs göras för att få det att fungera.
Denna guide är framtagen av Active Solution, konsultbolaget bakom Open Source-projektet Active Login och inte skriven av BankID officiellt. Notera att Active Login ständigt utvecklas och det är inte garanterat att guiden nedan alltid stämmer överens med senaste versionen av Active Login.
Komma igång
Active Login kan användas på ett flertal vis. Men de 2 vanligaste är att antingen implementera Active Login i en fristående applikation, eller att integrera det med IdentityServer. Den här artikeln kommer visa båda delarna.
Innan vi sätter igång, så kan det dock vara värt att säga att bara för att det finns en beskrivning av hur man gör här, och att Active Login löser det flesta delarna av BankID integrationen, så innebär det inte att man inte bör läsa igenom BankID’s egna dokumentation också. För även om Active Login är byggt för att följa deras standarder och rekommendationer, så är det trots allt du som implementerar och använder det som är ytterst ansvarig. Denna guide tar inte upp alla aspekter, utan är et tbra komplement till den dokumentation kring Active Login som finns på GitHub och Active Login - Documentation.
Och med den disclaimern ur värden, så är det äntligen dags att ta en titt på hur man implementerar BankID autentisering med Active Login.
NuGet-paket
Det första steget är att sätta upp en ASP.NET Core applikation. För den här demon så har jag skapat en ny tom ASP.NET Core applikation I Visual Studio 2022.
När vi väl har en applikation som behöver BankID autentisering, så är det dags att installera ett antal NuGet paket. Och med ett antal menar jag 3. De är
ActiveLogin.Authentication.BankId.AspNetCore
ActiveLogin.Authentication.BankId.QRCoder
ActiveLogin.Authentication.BankId.UAParser
Ska vi vara helt ärliga så behövs strikt sett bara ActiveLogin.Authentication.BankId.AspNetCore
paketet, men det är lika bra att ta alla 3 för att få full funktionalitet.
AddAuthentication
Med dessa på plats är det dags att sätta upp ASP.NET Core autentisering med hjälp av Active Login. Det görs med följande kod i ConfigureServices metoden i Program.cs
services.AddBankId(bankId => {
bankId.AddDebugEventListener();
bankId.UseQrCoderQrCodeGenerator();
bankId.UseUaParserDeviceDetection();
bankId.UseSimulatedEnvironment();
});
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie();
.AddBankIdAuth(bankId => {
bankId.AddSameDevice();
bankId.AddOtherDevice();
})
.AddCookie();
De här raderna kod börjar med att konfigurera de inställnignar och tjänster som behövs för att BankID ska fungera, detta med AddBankId()
. Sen lägger vi till autentiseringsstöd i applikationen, och lägger till både BankID, med hjälp av AddBankIdAuth()
, och cookie autentisering, med hjälp av AddCookies()
.
Det finns ett par saker som kan vara värt att ta en titt på i den här koden. För det första så kan vi se att vi skickar in CookieAuthenticationDefaults.AuthenticationScheme
till AddAuthentication()
. Detta konfigurerar lösningen till att använda cookie autentisering som standard. Detta behövs då BankID bara är en autentisering, dvs det verifierar att användaren är den hen säger att hen är. För att faktiskt behålla användaren inloggad så måste systemet använda cookie autentisering.
Den andra delen som är intressant att ta en titt på är så klart AddBankId()
. Den här metoden är ansvarig för att lägga till Active Logins BankID implementation som ett autentiserings schema.
Konfiguration
På grund av den stora mängd konfiguration som kan göras för detta, så använder Active Login ett “builder pattern” för att sätta upp konfigurationen. Det innebär att man får in ett “builder objekt” på vilket man anropar metoder för att sätta upp konfigurationen. Precis som man gör i till exempel ConfigureServices()
metoden själv.
Med hjälp av “buildern” lägger vi sedan till en Debug lyssnare som ger oss användbara loggar under utvecklingen av systemet. Sedan lägger vi till en QrCoder-baserad Qr kods generator som används för att rendera Qr koder vid inloggning. Efter den lägger vi till en “user agent” parser som kan räkna ut vilken type av enhet och webläsare som används för att se till att man kan starta BankID appen på rätt sätt.
Miljö
Sen är det dags att välja miljö att jobba i. Active Login stödjer 3 miljöer, Simulated, Test och Production. Simulated innebär att man inte gör någon riktigt integration. Detta gör det möjligt att lösningen visa hur flödet ser ut och fungerar med hjälp av en simluerad miljö. I princip innebär det bara att BankID inloggningen stegar igenom alla stegen utan att man behöver göra något, och till sist returneras en hårdkodad användare.
För det första steget i den här demon så har vi valt att köraden simluerade miljön och anropar därför UseSimulatedEnvironment()
.
Scheman
Till sist är det dags att lägga till de faktiska autentiserings scheman som skall användas. Detta görs under AddBankIdAuth().
Active Login stödjer även signering och där ser registreringen av scheman aningen annorlunda ut. Vi anropar AddSameDevice()
, som erbjuder användaren att logga in på samma enhet som hen befinner sig, och AddOtherDevice()
, som erbjuder användaren att logga in på en annan enhet än den nuvarande.
Eftersom vår lösning vill, precis som de flesta lösningar, erbjuda både inloggning på samma enhet, och på en annan enhet, så anropas vi båda två.
Dessa metoder har ett flertal överlagringar som erbjuder oss att finjustera hur de fungerar. Men för den här demon klarar vi oss med standard värdena.
MVC
När vi fått autentiseringen konfiugurerad är det bara en fråga om att sätta upp ASP.NET MVC. Det gör vi med följande kod:
services.AddControllersWithViews(config =>
{
config.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
och
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
i Configure metoden.
Med den grundläggande konfigurationen på plats i Program.cs
så kan vi sätta upp en HomeController.cs
. I Index actionen så returnerar vi helt enkelt bara en vy
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
Vyn i sig är enkel. Det enda som egentligen är viktigt, förutom det vi vill visa på sidan, är att vi inkluderar Bootstrap 4 i vår layout. Så vår layout vy (_Layout.cshtml) ser ut som följer
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" >
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>
och vår Index.cshtml
ser ut så här:
@if (User.Identity.IsAuthenticated)
{
<h1>Välkommen @User.Identity.Name</h1>
<a href="/Account/Logout" class="btn btn-primary">Logga ut</a>
}
else
{
<a href="/Account/Login?scheme=bankid-samedevice" class="btn btn-primary">Logga in med Bank ID på den här enheten</a><br />
<a href="/Account/Login?scheme=bankid-otherdevice" class="btn btn-primary">Logga in med Bank ID på en annan enhet</a>
}
Inloggning
Det är nästan allt som behövs. Det enda som saknas nu, är en AccountController.cs
som kan hantera Logga in“_ och Logga ut länkarna.
Så för att hantera detta så skapar vi en AccountController med 2 actions. Login och Logout.
public class AccountController : Controller
{
public IActionResult Login(string scheme)
{
return Challenge(new AuthenticationProperties { RedirectUri = "/" }, scheme);
}
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync();
return Redirect("/");
}
}
Som synes här så görs det inte så mycket. Det enda som egentligen görs är att vi anropar de inbyggda autentiseringsmetoderna Challenge()
för att skapa en autentiserings "challenge”, och och HttpContext.SignOutAsync()
för att logga ut.
Med det på plats är det bara att starta applikationen och prova att logga in och logga ut.
Testsmiljö - Certifikat
När vi har tröttnat på att se applikationen logga in och ut med hjälp av den simulerade miljön, så är det dags att sätta upp en testmiljö. Detta har tradionellt inneburit att vi införskaffat ett testcertifikat för att kunna kommunicera med BankID, samt ett test BankID som låter oss autentisera oss mot BankIDs testmiljö. Men sedan version 6.0.0 av Active Login finns ni certifikaten för test inbäddade i projektet.
Anledningen till behov av certifikatshantering är att vi inte litar på utfärdaren av certifikatet som anänds för TLS i BankIDS API. Det är utfärdat av BankID och inte av en av våra betrodda CAs. Så för att kunna använda det så måste vi lita på utfärdaren, på ett eller annat vis.
Använda testmiljön
Nu när vi har både CA certet och certet för testmiljön, så är det bara att konfigurera om Active Login till att använda test miljön istället för den simulerade. Det gör vi relativt enkelt genom att ersätta UseSimulatedEnvironment()
med UseTestEnvironment()
.
BankID i testmiljön
Nu är lösningen klar för att kunna testas mot BankIDs testmiljö. Men tyvärr är vår utvecklingsmiljö inte konfigurerad för det. Testmiljön godkänner bara BankIDn som är utfärdade av testmiljön. Så vi kan inte använda vårt vanliga BankID för våra tester. Istället behöver vi konfigurera an BankID app till att använda test certifikat. Och tyvärr funkar BankID appen antingen för produktionsmiljön eller för testmiljön. Den akn inte köra mot båda. Så om du använder BankID till vardags, så är det lättast att se till att du gör testningen på en separat enhet. Det innebär att man antingen behöver en separat mobil/platta för testning av Mobilt BankID, eller en dator som inte använder BankID appen till vardags. Eller båda delarna.
Eftersom jag normalt använder Mobilt BankID till allt, så har jag valt att installera och konfigurera BankID appen på min utvecklingsdator. Det gör man på följande vis.
Först måste man ladda ner och installera BankID appen, vilket man kan göra från https://install.bankid.com/. Efter den installerats behöver man starta appen en gång för att få den färdiguppsatt, innan man stänger av den igen. När appen har stängts av behöver man öppna Utforskaren och gå till %APPDATA%\BankID\Config. I den mappen behöver man sedan skapa en fil som heter CavaServerSelector.txt och som innehåller testen “kundtest” (utan dubbel-fnuttar). Därefter kan man starta upp BankID appen igen.
Kommentar: Om du behöver använda BankID appen för både produktion- och testmiljön, så finns det information om hur du backar upp och återställer dina cert i https://www.bankid.com/assets/bankid/rp/how-to-get-bankid-for-test-v1.7.pdf
Nu när vi har en BankID app som är konfigurerad för att använda BankIDs testmiljö, så är det dags att lägga till ett test BankID. Det gör man genom att surfa till https://demo.bankid.com/. Väl där så klickar man på “Log in” i “Log in with a Production-BankID” sektionen. Därefter loggar man in med Mobilt BankID för att identifiera sig. Detta leder en till en sida där man kan välja att utfärda ett test BankID. Kom bara ihåg att välja “BankID på fil” om du ska använda det på den lokala datorn, inte på en mobil.
När test BankIDt har utfärdats och finns I BankID appen är det bara att starta applikationen I Visual Studio och prova att logga in med knappen “Logga in med BankID på den här enheten”. Detta bör leda till att BankID appen poppar upp och ber om ditt lösenord, följt av att du får se hälsningen som bekräftar att du är inloggad.
Använda BankIDs produktionsmiljö
Att sätta upp Active Login för användning med produktionsmiljön är i sig inte specielt annorlunda än att sätta upp det för test. Den stora skillnaden är att klient certifikatet måste beställas av en leverantör, vilket kan ta ett par dagar, och att den publika nyckeln för CA certet är annorlunda men även den finns inbäddad och aktiveras när du väljer produktionsmiljön.
Därefter är det i huvudsak en fråga om att byta ut UseTestEnvironment()
mot UseProductionEnvironment()
.
Det är dock viktigt att inse att test certifikatet är känslig information, dvs det är inte godkänt att bara lägga den på disk på servern. Istället bör den hanteras som en alla andra känsliga uppgifter och antingen placeras i certifikats hanteringen på servern, eller i en tjänst som Azure KeyVault.
Väljer man att ha sin applikation i Azure så är KeyVault det naturliga valet. Dessutom finns det ett NuGet paket som heter ActiveLogin.Authentication.BankId.AzureKeyVault
som gör det extremt lätt och smidigt att hämta sitt certifikat från KeyVault.
Fullständig kod
När du är klar bör du ha ett projekt som ser ut något i stil med vår exempel på GitHub som heter "Standalone.MvcSample".
IdentityServer
Till sist känns det vettigt att skriva ett par rader om integration med Duende IdentityServer med tanke på det är väldigt många som använder denna mjukvara.
Som tur är så bygger IdentityServer till stor del på den inbyggda autentideringen i .NET Core. Detta gör att det är extremt lätt att lägga till externa autentiserings scheman så som Facebook och Twitter. Men även BankID med hjälp av Active Login.
Till stor del är det identiskt med det som redan visats. Ända skillnaden är anropen till AddSameDevice()
och AddOtherDevice()
. Eftersom IdentityServer bygger på att man först loggas in med en temporär inloggning, och sedan “förflyttas” till en permanent, så innebär det att vi inte kan låta Active Login logga in användaren med hjälp av cookie autentisering. Istället måste vi se till att användaren blir inloggad med ett schema som heter IdentityServerConstants.ExternalCookieAuthenticationScheme
. Det är dock relativt enkelt att ordna. Allt som behövs är att vi lägger till en konfigurationscallback som sätter SigninScheme
.AddSameDevice(options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; })
.AddOtherDevice(options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; })
I övrigt är allt mer eller mindre identiskt med det vi redan gått igenom.
Förhoppningsvis har den här artikeln gjort det lite lättare att förstå hur man sätter upp BankID autentisering med Active Login i ASP.NET Core. Det är inte nödvändigtvis speciellt svårt att sätta sig in i om man jobbat med ASP.NET Core autentisering tidigare. Men det är ett par steg som kanske inte är helt lätta att få grepp om när man läser dokumentationen från Active Login och BankID själva.
Support
Tycker du att BankID är intressant för din app eller webb men tycker allt det tekniska ovan inte är för dig? Våra konsulter hjälper dig gärna med att komma igång och förvalta din inloggningslösning. Läs mer om vårt paket “Säker Bankinloggning” här.