Search code examples
azurepowershellazure-ad-msalazure-identityazure-app-registration

How to generate a delegated token with username and password in Azure AD using PowerShell?


I'm automating the creation of Azure AD applications using PowerShell and running into an issue when trying to generate a delegated token. I've been able to create an application, add a client secret, and even generate a token using client credentials (app token) with no issues.

The token works fine for app-level permissions. However, I'm not sure how to modify my script to add delegated permission and generate delegated token that can act on behalf of a user.

Here’s the code I’ve been using for generating the client credentials token:

Connect-AzAccount

$appName = "MyTestingApp"
$app = New-AzADApplication -DisplayName $appName

$secret = New-AzADAppCredential -ApplicationId $app.AppId -EndDate (Get-Date).AddYears(1)

Start-Sleep -Seconds 30

$graphApiId = '00000003-0000-0000-c000-000000000000'
$mailSendId = 'b633e1c5-b582-4048-a93e-9f11b44c7e96'

$graphSp = Get-AzADServicePrincipal -Filter "appId eq '$graphApiId'"

Add-AzADAppPermission -ObjectId $app.Id -ApiId $graphApiId -PermissionId $mailSendId -Type Role

$sp = New-AzADServicePrincipal -ApplicationId $app.AppId

New-AzADServicePrincipalAppRoleAssignment -ServicePrincipalId $sp.Id -ResourceId $graphSp.Id -AppRoleId $mailSendId

Start-Sleep -Seconds 30

$tenantId = (Get-AzContext).Tenant.Id
$clientId = $app.AppId
$clientSecret = $secret.SecretText

$tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"

$body = @{
    client_id     = $clientId
    client_secret = $clientSecret
    scope         = "https://graph.microsoft.com/.default"
    grant_type    = "client_credentials"
}

$response = Invoke-RestMethod -Method Post -Uri $tokenUrl -ContentType "application/x-www-form-urlencoded" -Body $body
$token = $response.access_token
$token

Everything works fine here for client credentials, but I’m stuck when it comes to delegated tokens. Any guidance on how I can adjust the script to generate a delegated token with Mail.Send permission using username would be really helpful.


Solution

  • Initially, you can run below PowerShell script to create an application with secret and add Mail.Send Delegated permission with consent:

    $appName = "MyTestingApp0611"
    $app = New-AzADApplication -DisplayName $appName
    
    $secret = New-AzADAppCredential -ApplicationId $app.AppId -EndDate (Get-Date).AddYears(1)
    
    Start-Sleep -Seconds 30
    
    $graphApiId = '00000003-0000-0000-c000-000000000000'
    $mailSendId = 'e383f46e-2787-4529-855e-0e479a3ffac0'
    
    $graphSp = Get-AzADServicePrincipal -Filter "appId eq '$graphApiId'"
    
    Add-AzADAppPermission -ObjectId $app.Id -ApiId $graphApiId -PermissionId $mailSendId
    
    az ad app permission admin-consent --id $app.AppId 
    
    Start-Sleep -Seconds 30
    

    When I ran above code, new app registration created successfully having Mail.Send Delegated permission with consent like this:

    enter image description here

    To generate a delegated token with Mail.Send permission using username password flow, refer below sample script:

    $tenantId = (Get-AzContext).Tenant.Id
    $clientId = $app.AppId
    $clientSecret = $secret.SecretText
    $username = "[email protected]"
    $password = "xxxxxxxxxx"
    
    $tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
    
    $body = @{
        client_id     = $clientId
        client_secret = $clientSecret
        scope         = "https://graph.microsoft.com/Mail.Send"
        username      = $username
        password      = $password
        grant_type    = "password"
    }
    
    $response = Invoke-RestMethod -Method Post -Uri $tokenUrl -ContentType "application/x-www-form-urlencoded" -Body $body
    
    $token = $response.access_token
    $token
    

    Response:

    enter image description here

    To confirm that, I decoded above token in jwt.ms website and got scp claim like this:

    enter image description here