Säker utveckling med ensidesapplikationer (SPA)

När du utvecklar molnbaserade distribuerade system kan skydd av sådana system leda till ett nytt lager av komplexitet.

Lokala system förlitar sig på de säkerhetsgränser som det interna nätverket tillhandahåller och använder katalogtjänsterna för användarsäkerhet. De kan köras i många år i den här säkra miljön utan problem. Att flytta till molnet kan leda till nya säkerhetsrisker. I den här artikeln beskrivs de verktyg som du kan använda för att minska riskerna.

Ett sådant verktyg är åtkomstkontroll. Åtkomstkontroll identifierar användare och reglerar vad de kan göra när de interagerar med ett program.

Åtkomstkontrollen kan ha två delar:

  • Autentiseringen identifierar användaren.
  • Auktorisering avgör vad användaren kan göra i programmet.

OAuth, ett öppet ramverk, hjälper till att hantera dessa utmaningar och tillhandahåller ett protokoll som utvecklare kan använda när de skapar sina system. OAuth 2.0 är den aktuella standarden.

OAuth 2.0 ger säker delegerad åtkomst. Genom att utfärda åtkomsttoken kan du auktorisera åtkomst från tredje part till dina skyddade resurser utan att ange autentiseringsuppgifter.

Azure Active Directory (Azure AD) är Microsofts inbyggda lösning för att hantera identiteter i molnet. Den integreras med lokala system så att användarna får en sömlös upplevelse vid åtkomst till skyddstjänster i molnet.

Den här guiden visar hur du använder Azure AD och OAuth 2.0 för att skydda en ensidesapplikation.

OAuth-flöden

OAuth-flöden omfattar många användningsfall, som alla backas upp av Azure AD-tjänster. Utvecklare använder dessa flöden för att skapa ett säkert program, så att:

  • Användare kan komma åt klientsystem på ett säkert sätt.
  • Gästanvändare kan delta via transaktioner mellan företag.
  • Användare kan kontakta slutanvändarna via Azure Business to Consumers (Azure B2C).

Diagram som visar det säkra OAuth 2-flödet mellan en inbyggd app och ett webb-API.

Det finns två OAuth-flöden, implicit beviljande och auktoriseringskod. Implicit beviljande är det vanligaste, men vi rekommenderar att du använder auktoriseringskodflödet.

Registrera ditt program i Azure

Registrera ett huvudnamn för tjänsten för användargränssnittet och API:et med hjälp av Azure AD Directory i Azure Portal.

  1. Logga in på Azure Portaloch sök sedan efter Appregistreringar.

  2. Välj Ny registrering.

    Skärmbild som visar sidan Appregistrering med Ny registrering valt.

  3. Om du vill registrera ett nytt program behöver du:

    • Visningsnamnet för programmet.
    • Kontotypen som stöds.
    • Programtyp: Webb, SPA eller offentlig klient/intern (mobil och stationär dator).
    • Omdirigerings-URI. När användaren autentiseras omdirigerar Azure AD resultatet till klienten.
      • Ett exempel på lokal utveckling är http://localhost:4200.
      • Ett exempel på produktion är " https://portal.contoso.com ".

    Skärmbild som visar fönstret Registrera ett program.

  4. Välj Register (Registrera).

  5. När registreringen är klar väljer du Översiktoch sedan ditt programnamn bredvid Hanterat program i den lokala katalogen.

    Skärmbild som visar sidan Översikt med programnamnet valt.

  6. Välj Egenskaper,växla Användartilldelning krävs till Ja för att ange åtkomstbehörigheter för programmet och välj sedan Spara.

    Skärmbild som visar sidan Egenskaper med Användartilldelning krävs aktiverat.

  7. Välj Användare och grupperoch lägg sedan till befintliga eller nya användare och säkerhetsgrupper.

    Skärmbild som visar sidan Användare och grupper med Lägg till användare/grupp valt.

  8. Användarna kan komma åt programmet via Mina appar.

Konfigurera konfigurationsinformation i klientprogrammet

När du har skapat och konfigurerat appregistreringen i Azure kan du konfigurera konfigurationsinformationen i klientprogrammet. För ett ensidesramverk som Angular har Microsoft utvecklat biblioteket @Azure/msal-angular som hjälper dig att integrera Azure AD i klientprogrammet.

  1. Installera ett @Azure-/msal-angular-bibliotek.

  2. Konfigurera biblioteket.

    • protectedResourceMapinnehåller en lista över skyddade resurser och deras omfång i en matris: [[skyddad resurs], [omfång för resurs]].
    • och clientIDauthority , som är klientorganisations-ID, levereras till konfigurationsobjektet.
    • För skyddade HTTP-begäranden infogar klienten en ny rubrikegenskap med namnet Authorization (Auktorisering). Den innehåller en bearer-token för den autentiserade användaren. Bearer-token ger den underordnade OAuth 2.0-tjänsten en säker ingångspunkt. Den kan innehålla metadata för tjänsten när du auktoriserar begäran.
export const protectedResourceMap: [string, string[]][]] = [
    ['https://graph.microsoft.com/v1.0/me', ['user.read']],
    ['https://localhost:5001/api/weatherforecast', ['api://ae05da8f-07d0-4ae6-aef1-18a6af68e5dd/access_as_user']]
];

function MSALConfigFactory(): Configuration {
    return {
        auth: {
            clientId: 'eba23c0b-1e86-4f68-b1d2-9c54d96083de',
            authority: 'https://login.microsoftonline.com/1c302616-bc6a-45a6-9c07-838c89d55003',
            redirectUri: 'http://localhost:4200',
            validateAuthority: true,
            postLogoutRedirectUri: 'http://localhost:4200',
            navigateToLoginRequestUrl: true
        },
        cache: {
            cacheLocation: 'sessionStorage',

            storeAuthStateInCookie: false //set to false, not ie 11
        }
    };
}

Mer information om hur du konfigurerar ett Angular-bibliotek finns i Självstudie: Logga in användare och anropa Microsoft Graph API från en Angular-ensidesapplikation (SPA) med hjälp av auth-kodflöde.

Testa programautentisering

Testa autentiseringsprocessen genom att ha en användare med åtkomst och en användare utan åtkomst försöker logga in på klienten.

Användaren loggar in i programmet och omdirigeras till sin Azure AD-klientorganisation.

  • Om användaren är giltig autentiseras den och loggas in.
  • Om användaren inte är giltig returnerar programmet ett fel.

Använda en skyddad resurs eller resursserver

Om du vill använda en skyddad resurs skapar du en ny appregistrering. När appregistreringen är klar ändrar API:et bearer-token för att tillåta åtkomst.

Exponera API:et

  1. Skapa en till appregistrering i Azure.

  2. Välj Exponera ett APIoch välj sedan Lägg till ett omfång.

    Skärmbild som visar sidan Exponera ett API med Lägg till ett omfång valt.

  3. Ange URI för program-IDoch välj sedan Spara och fortsätt. Den här behörigheten används av API:et för att verifiera begäran.

    Skärmbild som visar fönstret Lägg till ett omfång med en AURI för program-ID angivet och Spara och fortsätt markerat.

  4. Konfigurera omfångsnamnet och medgivandeinformationen. Om du väljer Endast administratörerkan endast administratörer bevilja medgivande för katalogen.

    Skärmbild som visar fönstret Lägg till en omfattningskonfiguration med angivna exempelvärden.

Lägga till API:et i appregistreringen

Nu när du har definierat dina behörigheter och exponerat API:et måste du lägga till API:et i appregistreringen för klienten.

  1. I appregistreringen väljer du API-behörigheteroch sedan Lägg till en behörighet.

    Skärmbild som visar sidan API-behörigheter med Lägg till en behörighet markerad.

  2. Välj Mina API:eroch välj sedan den API-registrering som du skapade.

    Skärmbild som visar fliken Mina API:er med API:et valt.

  3. Välj det omfång som du skapade för att exponera API-behörigheten och välj sedan Lägg till behörigheter.

    Skärmbild som visar det valda omfånget med knappen Lägg till behörigheter markerad.

Nu läggs API:et till i programmet. Eftersom du kan behöva bevilja medgivande igen för åtkomst till API:et bör du överväga att bevilja administratörsmedgivande så att användarna inte behöver rekognosering.

Skärmbild som visar api:et som lagts till i programmet.

Lägga till API:et i den skyddade resurskartan

Nu när konfigurationen i Azure Portal är klar kan UI-klienten använda resursen. Lägg till API:et i den skyddade resurskartan för att se till att användargränssnittet bifogar rätt bearer-token för API-begäran.

export const protectedResourceMap: [string, string[]][] = [
    ['https://graph.microsoft.com/v1.0/me', ['user.read']],
    ['https://localhost:5001/api/weatherforecast', ['api://eba23c0b-1e86-4f68-b1d2-9c54d96083de/access_as_user']]
];

När klientprogrammet försöker komma åt resursen autentiserar MSAL-klientbiblioteket till Azure AD via en dold iframe och returnerar sedan en bearer-token för resursen. Bearer-token läggs bara till för begäranden som matchar slutpunkten, i det här fallet https://localhost:5001/api/weatherforecast.

Om API:et som du konfigurerade med relevanta appregistreringar tar emot en bearer-token med en ogiltig program-ID-URI avvisar det begäran och returnerar ett meddelande om 401 –obehörig.

I följande exempel är backend-tjänsten skriven i .NET Core. Exemplet visar konfigurationsegenskaperna för API:et. ClientIdhar program-ID-URI i form av api://{clientId} .

"AzureAD": {
  "Instance": "https://login.microsoftonline.com/",
  "Domain": "yourName.onmicrosoft.com",
  "TenantId": "1c302616-bc6a-45a6-9c07-838c89d55003",
  "ClientId": "api://ae05da8f-07d0-4ae6-aef1-18a6af68e5dd"
},

I startklassen för .NET Core-API:et läggs autentiseringsschemat och -alternativen till i metoden konfigurera tjänster.

services.Addauthentication(AzureADDefaults.BearerAuthenticationScheme).AddAzureADBearer(options => Configuration.Bind("AzureAD",
  options));

När klienten anropar API:et läggs bearer-token till i begäran.

Skärmbild som visar den bearer-token som lagts till i begäran.

Du kan gå till jwt.ms och klistra in bearer-token i ett format som kan läsas av människor.

Skärmbild som visar bearer-token i ett format som kan läsas av människor.

Du kan se att API-URI:n finns i aud egenskapen . Den här egenskapen identifierar den avsedda mottagaren av token, vilket är ditt API. Om ditt API inte är den avsedda mottagaren avvisar det automatiskt begäran med ett 401 HTTP-svar.

Egenskapen scp innehåller den uppsättning omfång som exponeras av ditt program. Om ogiltiga omfång läggs till via klienten returnerar Azure AD ett fel som begär ytterligare auktorisering för omfång.

Skärmbild som visar tokenegenskaperna i jwt.ms filen.

Använda applikationsmanifestet för att ytterligare definiera auktorisering

Ytterligare auktoriseringsmetoder implementeras med hjälp av applikationsmanifestet för API-appregistreringen. Eftersom du uttryckligen har definierat användare kan du lägga till ytterligare auktoriseringsnivåer och endast tillåta att medlemmar i en viss säkerhetsgrupp får åtkomst till känsligare resurser.

  1. I din appregistrering väljer du Manifest.

    Skärmbild som visar manifestsidan.

  2. Redigera nyckel/värde-paren för JSON-objektet efter behov.

I allmänhet är det bäst att bara utfärda SecurityGroup . Om du använder All genereras säkerhetsgrupper, Azure AD-roller och distributionsgrupper. Token har en fast gräns på 200, och om gränsen nås läggs ett överbefordran till. Anspråket pekar på Graph slutpunkten för att hämta listan över grupper för användaren.

Efter konfigurationen har jwt-token en ny egenskap, , som innehåller de unika objekt-ID:na som kan användas för groups att framtvinga auktorisering.

API:et kan konfigureras med en princip som söker efter ett nödvändigt anspråk och värde för rollbaserad auktorisering via principhanteraren.

public void ConfigureServices(IServiceCollection services)
{

    services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme).AddAzureADBearer(options => Configuration.Bind("AzureAD",
      options));

    services.AddAuthorization(options =>
    {

        options.AddPolicy("DensuAegisReportsAdmin", policyBuilder =>
        {
            policyBuilder.RequireClaim("groups", "ebde25e7-d254-474e-ae33-cd491aa98ebf"); //This would be an environment variable
        });
});

    JWTSecurityTokenHandler.DefaultMapInboundClaims = false;
    services.AddCors();

    services.AddControllers();
}

Kontrollanten för API:et kan ha relevanta attributioner tillagda. Dessa attribut ger bättre säkerhet och hjälper till att bekräfta att autentiserade personer har behörighet att komma åt den skyddade resursen.

[Route("admin")]
[Authorize("DensuAegisReportsAdmin")]
public IActionResult GetForcastsForAdmin()
{
    var user = User.Claims;

    var groups = User.Claims.Where(c => c.Type == "groups").Select(c => c.Value).ToList();
    var userName = UserClaims.Where(c => c.Type == "unique_name").Select(c => c.Value).FirstOrDefault();
    // SecurityGroup = groups
    var rng = new Random();
    var forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)],

    })
    .ToArray();

    return Ok(new
    {
        User = userName
        ,
        SecurityGroup = groups
        ,
        Forcasts = forecasts
    });
}

Fler roller kan skapas med programmanifestet som är unika för appregistreringen. Sedan kan fler grupper skapas i kontexten för programmet.

Skärmbild som visar ett exempel på en appRole som lagts till i manifestet.

Du kan till exempel skapa en anpassad roll med namnet AppAdmin som är unik för programregistreringen. Med hjälp av enterprise-programbygget kan du tilldela användare eller säkerhetsgrupper till rollen.

När du anropar den skyddade resursen efter konfigurationsändringen har bearer-token roles egenskapen inuti bearer-token.

Skärmbild som visar rollegenskapen i bearer-token.

API:et konfigureras med hjälp av principbyggaren under Konfigurera tjänster.

            // Adding authorization policies that enforce authorization using Azure AD roles.
            services.AddAuthorization(options =>
            {
                options.AddPolicy(AuthorizationPolicies.AssignmentToAppAdminRoleRequired, policy =>
                  policy.RequireRole(AppRole.AppAdmin));
            });

Den skyddade vägen använder auktoriseringsprincipen för att se till att den autentiserade användaren har rätt roll innan begäran auktoriserars.

Nästa steg