Inzicht in de impliciete OAuth2-toekenningsstroom in Azure Active Directory (AD)

Waarschuwing

Deze inhoud is voor het oudere Azure AD v1.0-eindpunt. Gebruik het Microsoft Identity Platform voor nieuwe projecten.

De impliciete OAuth2-toekenning staat bekend als de toekenning met de langste lijst met beveiligingsproblemen in de OAuth2-specificatie. En toch is dat de aanpak die wordt geïmplementeerd door ADAL JS en de methode die we aanbevelen bij het schrijven van SPA-toepassingen. Wat geeft dat? Het is allemaal een kwestie van compromissen: en het blijkt dat impliciete toekenning de beste benadering is die u kunt volgen voor toepassingen die een web-API gebruiken via JavaScript vanuit een browser.

Wat is de impliciete OAuth2-toekenning?

De essentiële OAuth2-autorisatiecodetoekenning is de autorisatietoekenning die gebruikmaakt van twee afzonderlijke eindpunten. Het autorisatie-eindpunt wordt gebruikt voor de interactiefase van de gebruiker, wat resulteert in een autorisatiecode. Het tokeneindpunt wordt vervolgens door de client gebruikt voor het uitwisselen van de code voor een toegangstoken, en vaak ook een vernieuwingstoken. Webtoepassingen moeten hun eigen toepassingsreferenties presenteren aan het tokeneindpunt, zodat de autorisatieserver de client kan verifiëren.

De impliciete OAuth2-toekenning is een variant van andere autorisatietoelagen. Hiermee kan een client een toegangstoken (en id_token bij gebruik van OpenId Connect) rechtstreeks vanaf het autorisatie-eindpunt verkrijgen, zonder contact op te maken met het tokeneindpunt of de client te verifiëren. Deze variant is ontworpen voor javascript-toepassingen die worden uitgevoerd in een webbrowser: in de oorspronkelijke OAuth2-specificatie worden tokens geretourneerd in een URI-fragment. Dat maakt de tokenbits beschikbaar voor de JavaScript-code in de client, maar garandeert dat ze niet worden opgenomen in omleidingen naar de server. In impliciete toekenning van OAuth2 geeft het autorisatie-eindpunt toegangstokens rechtstreeks uit aan de client met behulp van een omleidings-URI die eerder is opgegeven. Het heeft ook het voordeel dat eventuele vereisten voor cross origin-aanroepen worden geëlimineerd, die nodig zijn als de JavaScript-toepassing is vereist om contact op te nemen met het tokeneindpunt.

Een belangrijk kenmerk van de impliciete OAuth2-toekenning is het feit dat dergelijke stromen nooit vernieuwingstokens retourneren aan de client. In de volgende sectie ziet u hoe dit niet nodig is en in feite een beveiligingsprobleem is.

Geschikte scenario's voor de impliciete OAuth2-toekenning

De OAuth2-specificatie verklaart dat de impliciete toekenning is ontworpen om gebruikersagenttoepassingen in te schakelen, dat wil zeggen JavaScript-toepassingen die worden uitgevoerd in een browser. Het definiërende kenmerk van dergelijke toepassingen is dat JavaScript-code wordt gebruikt voor toegang tot serverbronnen (meestal een web-API) en voor het dienovereenkomstig bijwerken van de gebruikerservaring van de toepassing. Denk aan toepassingen zoals Gmail of Outlook Web Access: wanneer u een bericht selecteert in uw Postvak IN, verandert alleen het deelvenster berichtvisualisatie om de nieuwe selectie weer te geven, terwijl de rest van de pagina ongewijzigd blijft. Dit kenmerk is in tegenstelling tot traditionele web-apps op basis van omleiding, waarbij elke gebruikersinteractie resulteert in een postback van een volledige pagina en een volledige paginaweergave van het nieuwe serverantwoord.

Toepassingen die de op JavaScript gebaseerde benadering tot het uiterste hanteren, worden toepassingen met één pagina of SPA's genoemd. Het idee is dat deze toepassingen alleen een eerste HTML-pagina en bijbehorende JavaScript gebruiken, waarbij alle daaropvolgende interacties worden aangestuurd door web-API-aanroepen die worden uitgevoerd via JavaScript. Hybride benaderingen, waarbij de toepassing voornamelijk postback-gestuurd is, maar af en toe JS-aanroepen uitvoert, zijn echter niet ongebruikelijk. De discussie over impliciet stroomgebruik is ook relevant voor deze methoden.

Toepassingen op basis van omleiding beveiligen hun aanvragen doorgaans via cookies, maar die aanpak werkt niet zo goed voor JavaScript-toepassingen. Cookies werken alleen voor het domein waarvoor ze zijn gegenereerd, terwijl JavaScript-aanroepen mogelijk worden omgeleid naar andere domeinen. In feite is dat vaak het geval: denk aan toepassingen die Microsoft Graph API, Office-API, Azure-API aanroepen, allemaal buiten het domein van waaruit de toepassing wordt geleverd. Een groeiende trend voor JavaScript-toepassingen is dat ze helemaal geen back-end hebben, waarbij ze voor 100% afhankelijk zijn van web-API's van derden om hun bedrijfsfunctie te implementeren.

Op dit moment is de voorkeursmethode voor het beveiligen van aanroepen naar een web-API het gebruik van de OAuth2 Bearer-tokenbenadering, waarbij elke aanroep vergezeld gaat van een OAuth2-toegangstoken. De web-API onderzoekt het binnenkomende toegangstoken en verleent toegang tot de aangevraagde bewerking als hierin de benodigde bereiken worden gevonden. De impliciete stroom biedt een handig mechanisme voor JavaScript-toepassingen om toegangstokens voor een web-API te verkrijgen, wat talloze voordelen biedt met betrekking tot cookies:

  • Tokens kunnen betrouwbaar worden verkregen zonder dat er cross origin-aanroepen nodig zijn : verplichte registratie van de omleidings-URI waarnaar tokens worden geretourneerd, garandeert dat tokens niet worden verplaatst
  • JavaScript-toepassingen kunnen zoveel toegangstokens verkrijgen als ze nodig hebben, voor zoveel web-API's waarop ze zijn gericht, zonder beperkingen voor domeinen
  • HTML5-functies zoals sessie- of lokale opslag bieden volledige controle over tokencache en levensduurbeheer, terwijl cookiesbeheer ondoorzichtig is voor de app
  • Toegangstokens zijn niet vatbaar voor CSRF-aanvallen (Cross-site request forgery)

De impliciete toekenningsstroom geeft geen vernieuwingstokens uit, meestal om beveiligingsredenen. Een vernieuwingstoken is niet zo beperkt als toegangstokens, waardoor veel meer vermogen wordt verleend, waardoor veel meer schade wordt toegebracht voor het geval het wordt gelekt. In de impliciete stroom worden tokens geleverd in de URL, waardoor het risico op interceptie groter is dan bij het verlenen van autorisatiecode.

Een JavaScript-toepassing beschikt echter over een ander mechanisme voor het vernieuwen van toegangstokens zonder de gebruiker herhaaldelijk om referenties te vragen. De toepassing kan een verborgen iframe gebruiken om nieuwe tokenaanvragen uit te voeren op het autorisatie-eindpunt van Azure AD: zolang de browser nog een actieve sessie (lees: een sessiecookie) heeft op het Azure AD domein, kan de verificatieaanvraag worden uitgevoerd zonder tussenkomst van de gebruiker.

Dit model biedt de JavaScript-toepassing de mogelijkheid om onafhankelijk toegangstokens te vernieuwen en zelfs nieuwe te verkrijgen voor een nieuwe API (mits de gebruiker hiervoor eerder toestemming heeft gegeven). Dit voorkomt de extra belasting van het verkrijgen, onderhouden en beveiligen van een artefact met een hoge waarde, zoals een vernieuwingstoken. Het artefact dat de stille verlenging mogelijk maakt, de Azure AD sessiecookie, wordt buiten de toepassing beheerd. Een ander voordeel van deze benadering is dat een gebruiker zich kan afmelden bij Azure AD, met behulp van een van de toepassingen die zijn aangemeld bij Azure AD, die worden uitgevoerd op een van de browsertabbladen. Dit resulteert in het verwijderen van de Azure AD sessiecookie en de JavaScript-toepassing verliest automatisch de mogelijkheid om tokens te vernieuwen voor de afgemelde gebruiker.

Is de impliciete toekenning geschikt voor mijn app?

De impliciete toekenning brengt meer risico's met zich mee dan andere subsidies en de gebieden waarop u moet letten, zijn goed gedocumenteerd (bijvoorbeeld Misbruik van toegangstoken om resource-eigenaar te imiteren in impliciete stroom en OAuth 2.0-bedreigingsmodel en beveiligingsoverwegingen). Het hogere risicoprofiel is echter grotendeels te wijten aan het feit dat het is bedoeld om toepassingen in te schakelen die actieve code uitvoeren, geleverd door een externe resource naar een browser. Als u een beveiligd-WACHTWOORDVERIFICATIE-architectuur plant, geen back-endonderdelen hebt of een web-API wilt aanroepen via JavaScript, wordt het gebruik van de impliciete stroom voor het verkrijgen van tokens aanbevolen.

Als uw toepassing een systeemeigen client is, is de impliciete stroom niet geschikt. De afwezigheid van de Azure AD sessiecookie in de context van een systeemeigen client ontneemt uw toepassing de middelen om een langdurige sessie te onderhouden. Dit betekent dat uw toepassing de gebruiker herhaaldelijk vraagt bij het verkrijgen van toegangstokens voor nieuwe resources.

Als u een webtoepassing ontwikkelt die een back-end bevat en een API uit de bijbehorende back-endcode gebruikt, is de impliciete stroom ook niet geschikt. Andere subsidies geven je veel meer macht. De toekenning van OAuth2-clientreferenties biedt bijvoorbeeld de mogelijkheid om tokens te verkrijgen die de machtigingen weerspiegelen die aan de toepassing zelf zijn toegewezen, in tegenstelling tot gebruikersdelegaties. Dit betekent dat de client de mogelijkheid heeft om programmatische toegang tot resources te behouden, zelfs wanneer een gebruiker niet actief bezig is met een sessie, enzovoort. Niet alleen dat, maar dergelijke subsidies bieden hogere veiligheidsgaranties. Toegangstokens worden bijvoorbeeld nooit via de gebruikersbrowser verzonden, ze lopen niet het risico dat ze worden opgeslagen in de geschiedenis van de browser, enzovoort. De clienttoepassing kan ook sterke verificatie uitvoeren bij het aanvragen van een token.

Volgende stappen