Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Azure PowerShell work with username/password based auth?

I want to understand how Azure PowerShell makes Azure API calls using AAD username/password based credentials.

My understanding is that an app needs a client-id before it can make Azure API calls. This client ID must be registered with a user’s account.

Does Azure PowerShell have a client-id? If so, how does it work without explicitly registering it with Azure accounts? Is it a special id that has been whitelisted across accounts?

like image 358
dhaundy Avatar asked May 26 '15 09:05

dhaundy


People also ask

Which PowerShell command is used to authenticate to Azure?

The Connect-AzAccount cmdlet connects to Azure with an authenticated account for use with cmdlets from the Az PowerShell modules.

What is the PowerShell command for login to Azure?

The Complete PowerShell 7 course: Beginner To Advanced Once you type the az login command, it will prompt for the Azure portal login console. If you need to log in with the device authentication code in the browser, you need to use the parameter –use-device-code.

How does Azure AD authenticate users?

Azure AD Multi-Factor Authentication works by requiring two or more of the following authentication methods: Something you know, typically a password. Something you have, such as a trusted device that is not easily duplicated, like a phone or hardware key. Something you are - biometrics like a fingerprint or face scan.


2 Answers

You don't need to create an application registration in Azure Active Directory for Azure Powershell. To leverage username/password credentials of an Azure AD user, you can use the Add-AzureAccount cmdlet:

$username = "admin@your_account.onmicrosoft.com"
$password = "SuperSecretPassword" | ConvertTo-SecureString -AsPlainText -Force

$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password 
Add-AzureAccount -Credential $credential 

Just make sure you have the latest version of the Azure PowerShell module installed, and the account you're using is an organizational account (as opposed to a Microsoft account) or a native Azure AD user.

To answer the last part of your question, there is a well-known client ID for Azure PowerShell ("1950a258-227b-4e31-a9cf-717495945fc2"). It's hard coded in the Azure Powershell module and can be used to authenticate PowerShell scripts to Azure AD when they invoke the Azure Management APIs directly:

# Load Active Directory Authentication Library (ADAL) Assemblies
$adal = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
$adalforms = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll"
[System.Reflection.Assembly]::LoadFrom($adal)
[System.Reflection.Assembly]::LoadFrom($adalforms)

# Set Azure AD Tenant name
$adTenant = "yourtenant.onmicrosoft.com" 

# Set well-known client ID for Azure PowerShell
$clientId = "1950a258-227b-4e31-a9cf-717495945fc2" 

# Set redirect URI for Azure PowerShell
$redirectUri = "urn:ietf:wg:oauth:2.0:oob"

# Set Resource URI to Azure Service Management API
$resourceAppIdURI = "https://management.core.windows.net/"

# Set Authority to Azure AD Tenant
$authority = "https://login.windows.net/$adTenant"

# Set user credentials (*** obviously you wouldn't have the password in clear text in a production script ***)
$userName = "admin@your_tenant.onmicrosoft.com"
$password = "SecretPassword"
$creds = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential" -ArgumentList $userName,$password

# Create AuthenticationContext tied to Azure AD Tenant
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority

# Acquire token
$authResult = $authContext.AcquireToken($resourceAppIdURI,$clientId,$creds)
like image 79
jgrenier Avatar answered Sep 28 '22 01:09

jgrenier


You can also get the desired behavior where users of your applications need to provide only user name and password just like Azure PowerShell.

This is what you can do too.

a) In order for users, outside your tenant directory, to access your web api the web api needs to be multi-tenant. Let's say you went ahead and configured this in Azure AD.

b) Next, you create a native application in your directory with delegated permissions to your web api.

c) Then, you add the native client app ID into the web api knownClientIds property by updating its manifest. The reason you do this is for consent flow, which after user's approval gets the Web API SPN provisioned in the user's directory. This needs to happen for multi-tenant apps. Read more here.

Now, let's say you ship an application that makes calls to the Web API (e.g. Azure powerShell). You can simply hardcode the client ID and APP ID URI (redirect URI) in your application and users don't need to provide it.

But the most important thing now is to use the correct ADAL API. If you use the below API, this will raise an error

var uc = new UserCredential(userName, userPassword); authresult = context.AcquireToken(webapiresourceid, nativeclientID, uc);

AADSTS65001: The user or administrator has not consented to use the application with ID '<app id guid>'. Send an interactive authorization request for this user and resource.

The reason is the user has to consent since the Web API is multi-tenant. For native client applications this is not needed since they are multi-tenant by default.

So, you have to use the below API and this will raise consent form (only first time)

result = context.AcquireToken( webapiresourceid, nativeclientID, new Uri("nativeclientRedirectURI"), PromptBehavior.Auto, new UserIdentifier(userName, UserIdentifierType.RequiredDisplayableId));

Note, native client ID and native client URI both can be hardcoded just like how Azure PowerShell did it in above answer.

like image 38
Frank Q. Avatar answered Sep 28 '22 00:09

Frank Q.