vrijdag 10 mei 2013

Autorisatie met ACS (Deel 1)

In de vorige blog heb je kunnen lezen hoe je ACS gebruiksklaar maakt voor jouw web site, zodat alleen aangemelde gebruikers op de web site kunnen komen. In dit deel gaat het over wat een gebruiker mag op jouw site, ofwel autorisatie. In principe ga je op dezelfde manier te werk als de uitsmijter bij de nachtclub, je checkt het paspoort op bepaalde kenmerken, in dit geval het geboortejaar van de bezoeker. Heeft de bezoeker de gewenste leeftijd, dan mag hij door anders wordt hij vriendelijk doch dringend verzocht op te hoepelen. Claims zijn eigenlijk de persoonskenmerken in het paspoort. Grofwef bestaat zo'n claim uit een type en een bijbehorende waarde. Een aantal veelvoorkomende claimtypes zijn:

"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" 
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth"
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender"

Een Security Token Service (STS) kan een aantal deze claims aanleveren, maar garanties zijn er niet. Zo zal Live ID alleen de "nameidentifier" meeleveren, terwijl Google ook het email-adres en naam zal leveren.
Welke claims een STS aanlevert, kun je eenvoudig onderzoeken met de web applicatie die we in de vorige blog hebben gemaakt. We breiden de controller uit met het volgende code:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        ClaimsIdentity claims = User.Identity as ClaimsIdentity;
        return View(claims);
    }
}
ClaimsIdentity komt uit de namespace System.Security.Claims, de nieuw te gebruiken namespace in .NET Framework 4.5 (was Microsoft.IdentityModel.Claims).
De bijbehorende View kan er dan als volgt uitzien:

@using System.Security.Claims
@model ClaimsIdentity

<h1>My Claims</h1>
<table>
    <thead>
        <tr>
            <th>Type</th>
            <th>Value</th>
        </tr>
    </thead>
    <tbody>
        @foreach (Claim claim in Model.Claims)
        {
            <tr>
                <td>@claim.Type</td>
                <td>@claim.Value</td>
            </tr>
        }
    </tbody>
</table>

Het resultaat voor de diverse providers is in afbeelding 1 te bewonderen. (Ooooh, wat ben ik hiervoor diep door het stof gegaan. Ik heb een Facebook account aangemaakt om dit te kunnen demonstreren :-()


Afbeelding 1. De claims, zoals die standaard door de verschillende STS's wordt aangeboden.
Deze claims zijn op zich vrij nutteloos als je een beetje autorisatie wilt bedrijven. Gelukkig kun je in ACS de claimset verrijken (de visum stempels in je paspoort) met extra claims. Om deze claims toe te voegen, ga je via de Azure Portal naar het ACS configuratiescherm. Selecteer hieruit het menu Rule Group en vervolgens een reeds bestaande Rule Group. Het leidt je naar het venster in afbeelding 2.


Afbeelding 2. Rules aanmaken.
In het "Add Claim Rule" kun je nu nieuwe claims definieren (afbeelding 3).

Afbeelding 3. Een rule aanmaken.

Het werkt als volgt: Als (If) via Facebook (Input claim issuer) een gebruiker met email-adres (Input claim type emailaddress) bla@bla.nl (Input claim value) binnenkomt, maak voor hem dan (Then) een nieuwe claim aan van type "role" (Output claim type) en geef die claim de waarde (Output claim value) "User" (Natuurlijk mag je hier alles verzinnen wat je te binnen schiet). Vergeet de Description niet, ook al is die optioneel. Wanneer je nu de applicatie weer start, zie je het volgende (afbeelding 4)


Afbeelding 4. Het resultaat van de claimverrijking. De claim "role" met waarde "User" is erbij gekomen.
We zouden nu in de MVC Action die claims kunnen uitvlooien en op basis daarvan besluiten of de gebruiker erin mag, maar WIF heeft iets veel mooiers hiervoor. Je kunt vrij eenvoudig een autorisatiemodule schrijven die zich in de request pipeline van IIS nestelt. Het komt erop neer dat je een nieuwe class erft van de class ClaimsAuthorizationManager (voeg hiervoor eerst een referentie naar System.IdentityModel en System.IdentityModel.Services toe) en overschrijf de CheckAccess methode. Deze methode retourneert "true" wanneer de aan een bepaalde conditie is voldaan, in dit geval de aanwezigheid van een bepaalde claim en "false" wanneer de gebruiker niet door mag gaan.

public class MyAuthorizationManager : ClaimsAuthorizationManager
{
    public override bool CheckAccess(AuthorizationContext context)
    {
        string requestedResource = context.Resource.First().Value;

        bool hasAccess = context.Principal.HasClaim(ClaimTypes.Role, requestedResource);
        return hasAccess;
     }
}

Deze class moeten we vervolgens in de request pipeline pluggen. Dat gaat via de web.config

<system.identityModel>
  <identityConfiguration>
    <claimsAuthorizationManager type="MyAuthorizationManager, MvcApplication1"/>
  </identityConfiguration>
</system.identityModel>

Tenslotte is het nog een kwestie van MVC Actions voorzien van het ClaimsPrincipalPermission attribuut. Let hierbij op het Resource attribuut. Dit attribuut wordt in de ResourceManager gebruikt om de bezoeker te testen.

[HandleError(View="Permissions")]
public class HomeController : Controller
{
    [ClaimsPrincipalPermission(SecurityAction.Demand, Operation="Open", Resource = "User")]
    public ActionResult Index()
    {
        ClaimsIdentity claims = User.Identity as ClaimsIdentity;
        return View(claims);
    }
    [ClaimsPrincipalPermission(SecurityAction.Demand, Operation = "Open", Resource = "Admin")]
    public ActionResult AdminSite()
    {
        return View();
    }
}

En dat is dan alles. De rest is claims instellen in Azure (alsof het niks is).

Dit is voor kleine organisaties met heel weinig mensen nog wel te doen, maar voor iets grotere bedrijven is dit eigenlijk een gebed zonder einde. In dat geval is het wellicht handiger om ADFS als STS in te zetten. Soms kom je ook oplossingen tegen waarbij men eigen STS-services gaat schrijven. Vaak wordt er dan een kopie van zo'n custom STS, zoals die WIF 3.5 en 4.0 werd bijgeleverd, gemaakt. Niet doen. Die custom STS is niet bedoeld voor productie-omgevingen. In Visual Studio 2012 zijn die templates dan ook verdwenen. In het volgende artikel zal ik aangeven hoe je de claimset (paspoort), die je terugkrijgt van ACS, kunt verrijken met informatie uit jouw database (het plaatsen van de visumstempels).

Geen opmerkingen:

Een reactie posten