ADAL-apps vinden nadat de recommendations API verdwijnt

10-12-2025 · Samantha Kloos-Kilkens

Op 15 december 2025 haalt Microsoft de ADAL to MSAL Recommendations API weg, het Graph-endpoint achter de aanbeveling "Migrate from ADAL to MSAL" in Entra ID. ADAL wordt sinds juni 2023 niet meer ondersteund en apps die het nog gebruiken blijven gewoon werken, dus in veel tenants was die aanbeveling het enige dat nog naar ze wees. In deze blog: wat er verdwijnt, hoe je dezelfde lijst uit de sign-in logs haalt met KQL of Graph PowerShell, en hoe ik de resultaten verdeel over je eigen ontwikkelaars, een leverancier of degene die de client beheert.

Een stapel gekleurde diskettes Foto: Curated Lifestyle via Unsplash

Wat er op 15 december stopt

De aankondiging staat als entry van september 2025 in What's new for Microsoft Entra. De kop zegt "Microsoft Authentication Library to MSAL", een typfout voor ADAL, dus zoek op de pagina naar de datum en niet naar de naam. Volgens de entry stopt de ADAL to MSAL Recommendations API op 15 december 2025, hoef je niets te doen om hem uit te zetten, en kun je het gebruik van authenticatiebibliotheken blijven volgen door de sign-in logs via Microsoft Graph te bevragen: de gegevens staan in authenticationProcessingDetails onder de key "Azure AD App Authentication Library".

In Graph heet de aanbeveling adalToMsalMigration. Alles wat je hebt gebouwd op GET https://graph.microsoft.com/beta/directory/recommendations/{tenantId}_adalToMsalMigration/impactedResources, bijvoorbeeld een dashboard of een job die tickets aanmaakt voor app-eigenaren, verliest zijn bron. De entry heeft het alleen over de API. Wat er met de aanbeveling in het admin center gebeurt staat er niet in, en de Learn-pagina van de aanbeveling zelf noemt de retirement helemaal niet. Ik zou er dus ook niet op rekenen dat de weergave in de portal blijft bestaan.

Hoe de aanbeveling werkte is nuttig om te weten, want dat is de logica die je zelf gaat nabouwen. Hij keek dagelijks naar ADAL-tokenaanvragen over de afgelopen 30 dagen en markeerde elke app die via ADAL een token aanvroeg als ADAL-applicatie, ook apps die ADAL en MSAL naast elkaar gebruiken. Een app ging op completed na 30 dagen zonder ADAL-aanvraag en kwam terug op active zodra er weer een binnenkwam.

Waarom ADAL-apps nog steeds aandacht verdienen

De MSAL-migratiepagina is duidelijk over de ondersteuning: alle support en ontwikkeling voor ADAL, inclusief security fixes, is op 30 juni 2023 gestopt, en sinds juni 2020 zijn er geen features meer bijgekomen. Dezelfde pagina zegt dat bestaande ADAL-apps blijven werken, en dat is precies waarom ze er nog zijn. Er gaat niets stuk, dus niemand maakt er een ticket voor.

Het praktische probleem zit in de vergelijkingstabel verderop op die pagina. ADAL ondersteunt geen continuous access evaluation, geen token protection en niet de authentication broker waar device-based Conditional Access op leunt. Dat zijn juist de maatregelen die de meeste identity-teams nu uitrollen, en een ADAL-client voor een resource is wat doorgaans eindigt als permanente uitzondering in de policy die ze had moeten afdwingen. Het identity-team heeft die lijst, met een eigenaar per app, dus nodig voor zijn eigen Conditional Access-plannen, wat de ontwikkelaars er verder ook mee doen.

Waar de bibliotheek in de sign-in logs staat

Elk sign-in-record heeft authenticationProcessingDetails, een verzameling key/value-paren. Als Entra ID kan zien welke bibliotheek het token aanvroeg, heeft een van die paren de key "Azure AD App Authentication Library", met een waarde die de bibliotheekfamilie, de bibliotheek en de versie noemt. Microsofts eigen Sign-ins workbook filtert op waarden waar "ADAL" in staat en neemt het vierde en vijfde woord van de waarde als ADAL-versie, wat je een idee geeft van het formaat.

Een paar dingen die de What's new-entry niet vermeldt. De property bestaat alleen op de beta signIn-resource; de v1.0-resource heeft hem niet, dus in PowerShell heb je Get-MgBetaAuditLogSignIn uit Microsoft.Graph.Beta.Reports nodig in plaats van Get-MgAuditLogSignIn. List signIns geeft bovendien alleen interactieve sign-ins terug, tenzij je filtert op signInEventTypes. ADAL-clients vernieuwen tokens meestal stil en daemons gebruiken client credentials, dus het grootste deel van wat je zoekt staat bij de non-interactive en service principal sign-ins. Het workbook kijkt naar alle drie, en voor zover ik kan zien deed de aanbeveling dat ook.

Beide routes hieronder vereisen Entra ID P1 of P2: Graph heeft dat nodig om sign-in logs te lezen, en de diagnostic setting die ze naar Log Analytics stuurt ook. Entra bewaart sign-ins 30 dagen bij P1 en P2 volgens de referentie voor dataretentie, wat overeenkomt met het venster van de aanbeveling. Een app die alleen aan het eind van de maand of het kwartaal draait heeft meer historie nodig, nog een reden om de logs in een workspace te hebben.
Diagram met ADAL-tokenaanvragen die in drie Entra sign-in-logstromen terechtkomen, het pad via de recommendations API dat op 15 december 2025 stopt, en de KQL- en Graph-routes die het vervangen, eindigend in een indeling naar de tenant die eigenaar is van de app.

KQL voor Log Analytics of Sentinel

Gaan je sign-in logs al naar een Log Analytics-workspace (alle drie de sign-in-categorieën, niet alleen SignInLogs), dan levert deze query één rij per app op, met de geziene bibliotheekversies, de soorten sign-ins en de tenant die eigenaar is van de app. AuthenticationProcessingDetails is in alle drie de tabellen een string-kolom, vandaar de parse_json.
let lookback = 30d;
let myTenantId = "<your tenant ID>";
union
    (SigninLogs
        | where TimeGenerated > ago(lookback)
        | extend AppName = AppDisplayName, SignInType = "interactive"),
    (AADNonInteractiveUserSignInLogs
        | where TimeGenerated > ago(lookback)
        | extend AppName = AppDisplayName, SignInType = "nonInteractive"),
    (AADServicePrincipalSignInLogs
        | where TimeGenerated > ago(lookback)
        | extend AppName = ServicePrincipalName, SignInType = "servicePrincipal")
| mv-expand Detail = parse_json(AuthenticationProcessingDetails)
| where tostring(Detail.key) == "Azure AD App Authentication Library"
| extend Library = tostring(Detail.value)
| where Library has "ADAL"
| summarize SignIns = count(), Users = dcountif(UserPrincipalName, isnotempty(UserPrincipalName)), LastSeen = max(TimeGenerated),
            SignInTypes = make_set(SignInType), Libraries = make_set(Library, 10)
    by AppId, AppName, AppOwnerTenantId
| extend Owner = case(
    AppOwnerTenantId in ("f8cdef31-a31e-4b4a-93e4-5f571e91255a", "72f988bf-86f1-41af-91ab-2d7cd011db47"), "Microsoft",
    AppOwnerTenantId == myTenantId, "Own tenant",
    isempty(AppOwnerTenantId), "Unknown",
    "Other tenant")
| order by SignIns desc
De kolom Owner leunt op AppOwnerTenantId. f8cdef31-a31e-4b4a-93e4-5f571e91255a is de Microsoft Services-tenant en 72f988bf-86f1-41af-91ab-2d7cd011db47 is Microsofts eigen tenant, allebei genoemd in Verify first-party Microsoft applications in sign-in reports.

Graph PowerShell zonder Log Analytics

Zonder workspace haal je dezelfde gegevens uit Graph. Dit script haalt per soort sign-in zeven dagen op en groepeert de ADAL-sign-ins per app. Je hebt AuditLog.Read.All nodig en een rol die sign-in logs mag lezen, zoals Reports Reader of Global Reader.
Connect-MgGraph -Scopes "AuditLog.Read.All"
# authenticationProcessingDetails is only on the beta signIn resource (Microsoft.Graph.Beta.Reports)
$since = (Get-Date).ToUniversalTime().AddDays(-7).ToString("yyyy-MM-ddTHH:mm:ssZ", [cultureinfo]::InvariantCulture)

$adal = foreach ($type in 'interactiveUser', 'nonInteractiveUser', 'servicePrincipal') {
    $filter = "createdDateTime ge $since and signInEventTypes/any(t: t eq '$type')"
    Get-MgBetaAuditLogSignIn -Filter $filter -All | ForEach-Object {
        $lib = ($_.AuthenticationProcessingDetails |
            Where-Object Key -eq 'Azure AD App Authentication Library').Value
        if ($lib -match 'ADAL') {
            [pscustomobject]@{
                AppId            = $_.AppId
                AppName          = if ($_.AppDisplayName) { $_.AppDisplayName } else { $_.ServicePrincipalName }
                AppOwnerTenantId = $_.AppOwnerTenantId
                Library          = $lib
                SignInType       = $type
                User             = $_.UserPrincipalName
            }
        }
    }
}

$adal | Group-Object AppId | ForEach-Object {
    [pscustomobject]@{
        AppId            = $_.Name
        AppName          = $_.Group[0].AppName
        AppOwnerTenantId = $_.Group[0].AppOwnerTenantId
        SignIns          = $_.Count
        Users            = @($_.Group.User | Where-Object { $_ } | Sort-Object -Unique).Count
        SignInTypes      = ($_.Group.SignInType | Sort-Object -Unique) -join ', '
        Libraries        = ($_.Group.Library | Sort-Object -Unique) -join '; '
    }
} | Sort-Object SignIns -Descending | Format-Table -AutoSize
Wees realistisch over het volume. In een grote tenant is een week aan non-interactive sign-ins een flinke hoeveelheid pagina's, dus begin met één dag, kijk hoe lang het duurt en breid daarna uit. Voor alles wat je wilt herhalen is een workspace de betere plek.

Zolang de API nog antwoordt, zou ik ook exporteren wat de aanbeveling vandaag weet, zodat je je eigen resultaten ergens tegen kunt leggen. Het ID-formaat komt van de Learn-pagina van de aanbeveling, en List impactedResources vraagt DirectoryRecommendations.Read.All.
Connect-MgGraph -Scopes "DirectoryRecommendations.Read.All"
$tenantId = (Get-MgContext).TenantId

Get-MgBetaDirectoryRecommendationImpactedResource -RecommendationId "${tenantId}_adalToMsalMigration" -All |
    Select-Object DisplayName, SubjectId, Status, AddedDateTime,
        @{ n = 'Library'; e = { ($_.AdditionalDetails | Where-Object Key -eq 'Library').Value } } |
    Export-Csv -Path .\adal-recommendation-export.csv -NoTypeInformation

De resultaten verdelen naar eigenaar

Welke tenant eigenaar is van de app bepaalt wie er aan de slag moet.

Is Microsoft de eigenaar, dan is er voor jou geen code om te migreren. De ADAL-code zit in een client of tool van Microsoft, en de oplossing is die client bijwerken of vervangen. De kolommen met gebruikers en soorten sign-ins laten zien wie de oude versie nog draait, en de apparaatgegevens in de onderliggende sign-ins laten zien waarop.

Staat de app geregistreerd in je eigen tenant, dan is het een klus voor de eigen ontwikkeling. De eigenaren staan op de app registration onder Owners, en de bibliotheekwaarde vertelt de ontwikkelaars welke migratiegids van toepassing is (ADAL.NET, ADAL.js, Java enzovoort, allemaal gelinkt vanaf de MSAL-migratiepagina). Is er geen actuele eigenaar, dan zijn de gebruikerskolom en de IP-adressen in de sign-ins het beste spoor naar wie de app nog gebruikt.

Hoort de app bij een andere tenant, dan is het een product van een leverancier. Zelf repareren kan niet, maar je kunt de leverancier vragen om een versie op basis van MSAL en een datum, het antwoord vastleggen en bepalen wat er gebeurt als die versie er niet komt, bijvoorbeeld door met assignment required op de enterprise app te beperken wie hem mag gebruiken terwijl je een vervanger zoekt.

Apps met een lege AppOwnerTenantId zou ik eerst op AppId opzoeken onder Enterprise applications, voordat ik ze in een van deze groepen indeel.

Blijven monitoren als de API weg is

De aanbeveling gaf je twee dingen gratis: een doorlopend venster van 30 dagen en een signaal als een app die stil was gevallen weer ADAL ging gebruiken. Allebei krijg je terug door de KQL op te slaan als log search alert die dagelijks over de laatste 30 dagen draait, met een filter dat de AppIds uitsluit die je al hebt beoordeeld, zodat hij alleen afgaat bij iets nieuws. Zonder workspace doet een maandelijkse run van de PowerShell-versie, vergeleken met de vorige export, hetzelfde met meer handwerk.

Exporteer vóór de 15e de impactedResources-lijst, draai de query of het script over dezelfde periode en zet bij elke app die in een van beide resultaten opduikt een eigenaar en een streefdatum.

Geschreven door een expert van Argus IT

Zo’n expert in je team, of zelf zo werken in security, IAM of cloud?

Samantha Kloos-Kilkens

Samantha Kloos-Kilkens

Samantha Kloos-Kilkens werkt al meer dan tien jaar in security en identity, waarvan acht jaar bij Microsoft in de productgroep Identity and Network Access. In 2023 richtte ze Argus IT op en ze heeft een zwak voor de verborgen pareltjes in Entra ID. CISSP, CCSP, CISM, CCSK en Microsoft Certified Trainer.

Blijf op de hoogte

Schrijf je in voor onze nieuwsbrief en ontvang een seintje wanneer we een nieuw artikel publiceren of nieuws te delen hebben.