0
votes

When calling AcquireToken I get the error that silent authentication can not be used for managed users

I have the following code that reproduces the error:

    $nuGetPackages = "$env:temp\packages"
    $clientVersion = '3.14.2'
    $libPath = Join-Path $nuGetPackages "Microsoft.IdentityModel.Clients.ActiveDirectory.$clientVersion\lib"

    if (!(Test-Path $libPath)) {
        Write-Host "Installing Microsoft.IdentityModel.Clients.ActiveDirectory module"
        Install-Package -Name 'Microsoft.IdentityModel.Clients.ActiveDirectory' -RequiredVersion $clientVersion -ProviderName NuGet -Destination $nuGetPackages -Source http://www.nuget.org/api/v2/ -Force | Out-Null
    }

    Add-Type -AssemblyName System.DirectoryServices.AccountManagement
    $tenantName = [string]::Join('.',([System.DirectoryServices.AccountManagement.UserPrincipal]::Current.DistinguishedName.Split(',') |? { $_.Split('=')[0] -eq 'dc' } |% { $_.Split('=')[1] }))
    $authority = "https://login.windows.net/$tenantName"
    $resourceAppIdUri = "https://management.core.windows.net/"
    $clientId = "1950a258-227b-4e31-a9cf-717495945fc2" # common app id

    Get-ChildItem $libPath -Filter net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll |% { [System.Reflection.Assembly]::LoadFrom($_.FullName) | Out-Null }

    try {
        $creds = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential" -ArgumentList $env:USERNAME@$tenantName
        $creds.UserAuthType
        $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
        $task = $authContext.AcquireTokenAsync($resourceAppIdUri, $clientId, $creds)
        $task.Wait()
        $authResult = $task.Result
        $authResult
        return $authResult.AccessToken
    } catch {
        throw $_.Exception.ToString()
    }

Produces the error

Microsoft.IdentityModel.Clients.ActiveDirectory.AdalException: password_required_for_managed_user: Password is required for managed user
2

2 Answers

0
votes

This error means you didn't provider the password for this method. If you want to use the Resource owner password credentials flow to acquire the access token, we should provider both username and password via UserPasswordCredential class.

Here is the code sample which works well for me:

$nuGetPackages = "$env:temp\packages"
$clientVersion = '3.14.2'
$libPath = Join-Path $nuGetPackages "Microsoft.IdentityModel.Clients.ActiveDirectory.$clientVersion\lib"

if (!(Test-Path $libPath)) {
    Write-Host "Installing Microsoft.IdentityModel.Clients.ActiveDirectory module"
    Install-Package -Name 'Microsoft.IdentityModel.Clients.ActiveDirectory' -RequiredVersion $clientVersion -ProviderName NuGet -Destination $nuGetPackages -Source http://www.nuget.org/api/v2/ -Force | Out-Null
}

Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$tenantName = [string]::Join('.',([System.DirectoryServices.AccountManagement.UserPrincipal]::Current.DistinguishedName.Split(',') |? { $_.Split('=')[0] -eq 'dc' } |% { $_.Split('=')[1] }))
$authority = "https://login.windows.net/$tenantName"
$resourceAppIdUri = "https://management.core.windows.net/"
$clientId = "1950a258-227b-4e31-a9cf-717495945fc2" # common app id

Get-ChildItem $libPath -Filter net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll |% { [System.Reflection.Assembly]::LoadFrom($_.FullName) | Out-Null }

try {     
    $creds = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential" -ArgumentList '{username}', '{password}'
    #$creds.UserAuthType
    $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
    $task = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authContext,$resourceAppIdUri, $clientId, $creds)
    #$task = $authContext.AcquireTokenAsync($resourceAppIdUri, $clientId, $creds)
    $task.Wait()
    $authResult = $task.Result
    $authResult
    return $authResult.AccessToken
} catch {
    throw $_.Exception.ToString()
}
0
votes

It's not true silent authentication like with ADFS (meaning it pops up a windows and cannot be used with non-interactive service accounts), but using PromptBehavior.None or Auto allows the pass-through (or password sync) Azure Seamless SSO to work (no password prompt)