Veilige ontwikkeling met toepassingen met één pagina (SPA's)

Bij het ontwikkelen van cloudeigen gedistribueerde systemen kan het beveiligen van dergelijke systemen een nieuwe complexiteitslaag introduceren.

On-premises systemen zijn afhankelijk van de beveiligingsgrenzen die het interne netwerk biedt en gebruiken de adreslijstservices voor gebruikersbeveiliging. Ze kunnen vele jaren zonder problemen worden uitgevoerd binnen deze beveiligde omgeving. Een overstap naar de cloud kan nieuwe beveiligingsrisico's met zich meebrengen. In dit artikel worden de hulpprogramma's beschreven die u kunt gebruiken om deze risico's te beperken.

Een van deze hulpprogramma's is toegangsbeheer. Toegangsbeheer identificeert gebruikers en bepaalt wat ze kunnen doen bij interactie met een toepassing.

Toegangsbeheer bestaat uit twee delen:

  • Verificatie identificeert de gebruiker.
  • Autorisatie bepaalt wat de gebruiker in de toepassing kan doen.

OAuth, een open framework, helpt bij het aanpakken van deze uitdagingen en biedt een protocol dat ontwikkelaars kunnen gebruiken bij het bouwen van hun systemen. OAuth 2.0 is de huidige standaard.

OAuth 2.0 biedt beveiligde gedelegeerde toegang. Door toegangstokens uit te geven, kunt u toegang van derden tot uw beveiligde resources verlenen zonder referenties op te geven.

Azure Active Directory (Azure AD) is de ingebouwde oplossing van Microsoft voor het beheren van identiteiten in de cloud. Het kan worden geïntegreerd met on-premises systemen, zodat gebruikers een naadloze ervaring hebben bij het openen van beveiligende services in de cloud.

Deze handleiding laat zien hoe u Azure AD en OAuth 2.0 gebruikt om een toepassing met één pagina te beveiligen.

OAuth-stromen

OAuth-stromen hebben betrekking op veel gebruiksgevallen, allemaal met ondersteuning van Azure AD Services. Ontwikkelaars gebruiken deze stromen om een beveiligde toepassing te bouwen, zodat:

  • Gebruikers hebben veilig toegang tot clientsystemen.
  • Gastgebruikers kunnen deelnemen via business-to-business-transacties.
  • Gebruikers kunnen eindgebruikers bereiken via Azure Business to Consumers (Azure B2C).

Diagram met de beveiligde OAuth 2-stroom tussen een native app en een web-API.

Er zijn twee OAuth-stromen: impliciete toekennings- en autorisatiecode. Impliciete toekenning komt het meest voor, maar we raden u aan de autorisatiecodestroom te gebruiken.

Uw toepassing registreren in Azure

Registreer een service-principal voor de gebruikersinterface en API met behulp van Azure AD Directory in de Azure Portal.

  1. Meld u aan bij Azure Portalen zoek naar App-registraties.

  2. Selecteer Nieuwe registratie.

    Schermopname van de pagina App-registratie met Nieuwe registratie geselecteerd.

  3. Als u een nieuwe toepassing wilt registreren, hebt u het volgende nodig:

    • De weergavenaam voor de toepassing.
    • Het ondersteunde accounttype.
    • Het toepassingstype: Web, SPA of openbare client/native (mobiel en desktop).
    • De omleidings-URI. Wanneer de gebruiker is geverifieerd, wordt het resultaat door Azure AD omgeleid naar de client.
      • Een voorbeeld voor lokale ontwikkeling is http://localhost:4200 .
      • Een voorbeeld voor productie is ' https://portal.contoso.com '.

    Schermopname van het venster Een toepassing registreren.

  4. Selecteer Registreren.

  5. Zodra de registratie is voltooid, selecteert u Overzicht en selecteert u vervolgens de naam van uw toepassing naast Beheerde toepassing in de lokale map.

    Schermopname van de pagina Overzicht met de naam van de toepassing geselecteerd.

  6. Selecteer Eigenschappen, schakel Gebruikerstoewijzing vereist in op Ja om de toegangsmachtigingen voor de toepassing in te stellen en selecteer vervolgens Opslaan.

    Schermopname van de pagina Eigenschappen met Gebruikerstoewijzing vereist ingeschakeld.

  7. Selecteer Gebruikers en groepen en voeg vervolgens bestaande of nieuwe gebruikers en beveiligingsgroepen toe.

    Schermopname van de pagina Gebruikers en groepen met Gebruiker/groep toevoegen geselecteerd.

  8. Uw gebruikers hebben toegang tot de toepassing via Mijn apps.

Configuratiedetails instellen in de clienttoepassing

Nadat u de app-registratie in Azure hebt maken en configureren, kunt u de configuratiegegevens instellen in de clienttoepassing. Voor een framework met één pagina, zoals Angular, heeft Microsoft de bibliotheek ontwikkeld om u te helpen @Azure/msal-angular Azure AD te integreren in uw clienttoepassing.

  1. Installeer een @Azure/msal-angular bibliotheek.

  2. Configureer de bibliotheek.

    • De protectedResourceMap bevat een lijst met beveiligde resources en hun scopes in een matrix: [[beveiligde resource], [scopes voor resource]].
    • De clientID en , de authority tenant-id, worden geleverd aan het configuratieobject.
    • Voor beveiligde HTTP-aanvragen voegt de client een nieuwe header-eigenschap in met de naam Autorisatie. Het bevat het bearer-token voor de geverifieerde gebruiker. Het bearer-token biedt de downstream OAuth 2.0-service een beveiligd toegangspunt. Het kan metagegevens voor de service bevatten bij het autoriseren van de aanvraag.
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
        }
    };
}

Zie Zelfstudie: Gebruikers aanmelden en de Microsoft Graph-API aanroepen vanuit een Angular-toepassing met één pagina (SPA) met behulp van de auth-codestroomvoor meer informatie over het configureren van een Angular-bibliotheek.

De toepassingsverificatie testen

Test het verificatieproces door een gebruiker met toegang te hebben en een gebruiker zonder toegang zich aan te melden bij de client.

De gebruiker meldt zich aan bij de toepassing en wordt omgeleid naar de Azure AD-tenant.

  • Als de gebruiker geldig is, wordt deze geverifieerd en aangemeld.
  • Als de gebruiker niet geldig is, retourneert de toepassing een fout.

Een beveiligde resource of resourceserver gebruiken

Als u een beveiligde resource wilt gebruiken, maakt u een andere app-registratie. Nadat de app-registratie is voltooid, wijzigt de API het bearer-token om toegang toe te staan.

De API beschikbaar maken

  1. Maak nog een app-registratie in Azure.

  2. Selecteer Een API beschikbaar maken en selecteer vervolgens Een bereik toevoegen.

    Schermopname van de pagina Een API beschikbaar maken met Een bereik toevoegen geselecteerd.

  3. Voer de URI van de toepassings-id in en selecteer Opslaan en doorgaan. Deze machtiging wordt gebruikt door de API om de aanvraag te valideren.

    Schermopname van het venster Een bereik toevoegen met een URI voor toepassings-id ingevoerd en Opslaan en doorgaan geselecteerd.

  4. Configureer de bereiknaam en toestemmingsgegevens. Als u Alleen beheerders selecteert, kunnen alleen beheerders toestemming verlenen voor de directory.

    Schermopname van het venster Een bereikconfiguratie toevoegen met ingevoerde voorbeeldwaarden.

De API toevoegen aan de app-registratie

Nu u uw machtigingen hebt gedefinieerd en de API beschikbaar hebt gemaakt, moet u de API toevoegen aan de app-registratie voor de client.

  1. Selecteer in uw app-registratie API-machtigingen en vervolgens Een machtiging toevoegen.

    Schermopname van de pagina API-machtigingen met Een machtiging toevoegen geselecteerd.

  2. Selecteer Mijn API's en selecteer vervolgens de API-registratie die u hebt gemaakt.

    Schermopname van het tabblad Mijn API's met de API geselecteerd.

  3. Selecteer het bereik dat u hebt gemaakt om de API-machtiging beschikbaar te maken en selecteer vervolgens Machtigingen toevoegen.

    Schermopname van het geselecteerde bereik met de knop Machtigingen toevoegen geselecteerd.

De API is nu toegevoegd aan de toepassing. Aangezien u mogelijk opnieuw toestemming moet verlenen voor toegang tot de API, kunt u overwegen beheerders toestemming te geven zodat gebruikers niet opnieuw hoeven te worden geconfigureerd.

Schermopname van de API die is toegevoegd aan de toepassing.

De API toevoegen aan de beveiligde resourcekaart

Nu de configuratie in de Azure Portal voltooid is, kan de UI-client de resource gebruiken. Voeg de API toe aan het beveiligde resourcekaart om ervoor te zorgen dat de gebruikersinterface het juiste bearer-token voor de API-aanvraag koppelt.

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']]
];

Wanneer uw clienttoepassing toegang probeert te krijgen tot de resource, wordt de MSAL-clientbibliotheek geverifieerd bij Azure AD via een verborgen iframe en wordt vervolgens een bearer-token voor de resource retourneert. Het bearer-token wordt alleen toegevoegd voor aanvragen die overeenkomen met het eindpunt, in dit geval https://localhost:5001/api/weatherforecast .

Als de API die u hebt geconfigureerd met de relevante app-registraties een Bearer-token met een ongeldige URI voor de toepassings-id ontvangt, wordt de aanvraag afgewezen en wordt een 401-bericht door onbevoegden weergegeven.

In het volgende voorbeeld is de back-endservice geschreven in .NET Core. In het voorbeeld ziet u de configuratie-eigenschappen voor de API. De ClientId heeft de URI van de toepassings-id in de vorm van 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"
},

Binnen de opstartklasse van de .NET Core-API worden het verificatieschema en de opties toegevoegd aan de methode voor het configureren van services.

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

Wanneer de client de API aanroept, wordt het bearer-token toegevoegd aan de aanvraag.

Schermopname van het bearer-token dat is toegevoegd aan de aanvraag.

U kunt naar jwt.ms en het bearer-token in een door mensen leesbare indeling plakken.

Schermopname van het Bearer-token in een voor mensen leesbare indeling.

U kunt zien dat de API-URI zich in de eigenschap aud . Deze eigenschap identificeert de beoogde ontvanger van het token, uw API. Als uw API niet de beoogde ontvanger is, wordt de aanvraag automatisch met een 401 HTTP-antwoord afgewezen.

De scp eigenschap bevat de set scopes die door uw toepassing worden blootgesteld. Als er ongeldige scopes worden toegevoegd via de client, retourneert Azure AD een fout met het aanvragen van verdere autorisatie voor het bereik.

Schermopname van de tokeneigenschappen in het jwt.ms bestand.

Het toepassingsmanifest gebruiken om autorisatie verder te definiëren

Verdere autorisatieprocedures worden geïmplementeerd met behulp van het toepassingsmanifest voor de registratie van de API-app. Omdat u gebruikers expliciet hebt gedefinieerd, kunt u meer autorisatieniveaus toevoegen en alleen leden van een specifieke beveiligingsgroep toegang geven tot gevoeligere resources.

  1. Selecteer Manifest in uw app-registratie.

    Schermopname van de manifestpagina.

  2. Bewerk waar nodig de sleutelwaardeparen van het JSON-object.

Over het algemeen kunt u het beste alleen SecurityGroup uitgeven. Als u All gebruikt, worden beveiligingsgroepen, Azure AD-rollen en distributiegroepen uitgezonden. Het token heeft een setlimiet van 200 en als deze limiet is bereikt, wordt er een uitvalclaim toegevoegd. De claim wijst naar het Graph eindpunt om de lijst met groepen voor de gebruiker op te halen.

Na de configuratie heeft het jwt-token een nieuwe eigenschap, , die de unieke object-ID's bevat die kunnen worden gebruikt om autorisatie groups af te dwingen.

De API kan worden geconfigureerd met een beleid dat zoekt naar een vereiste claim en waarde voor op rollen gebaseerde autorisatie via de beleids-handler.

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();
}

Aan de controller voor de API kunnen de relevante toeschrijvingen worden toegevoegd. Deze kenmerken bieden meer beveiliging en helpen te bevestigen dat de geverifieerde personen zijn gemachtigd voor toegang tot de beveiligde resource.

[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
    });
}

Er kunnen meer rollen worden gemaakt met het toepassingsmanifest dat uniek is voor de app-registratie. Vervolgens kunnen er meer groepen worden gemaakt binnen de context van de toepassing.

Schermopname van een voorbeeld van een appRole die is toegevoegd aan het manifest.

U kunt bijvoorbeeld een aangepaste rol met de naam AppAdmin maken die uniek is voor de registratie van de toepassing. Met behulp van de build van bedrijfstoepassing kunt u gebruikers of beveiligingsgroepen toewijzen aan die rol.

Wanneer u de beveiligde resource aanroept na de configuratiewijziging, heeft het bearer-token de eigenschap roles binnen het bearer-token.

Schermopname van de eigenschap role in het bearer-token.

De API wordt geconfigureerd met behulp van de opbouwer van beleid onder Services configureren.

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

De beveiligde route maakt gebruik van het autorisatiebeleid om ervoor te zorgen dat de geverifieerde gebruiker de relevante rol heeft voordat de aanvraag wordt autoriseren.

Volgende stappen