Lesson Learned #379: ADALNativeWrapper.ADALGetAccessToken error using AAD - Password Authentication
Published Jun 22 2023 07:49 AM 1,322 Views

Issue

 

Analyzing one of the cases in which we encountered an error using Azure Active Directory with Password Authentication, I would like to share the lessons learned during this process, to understand why the error occurs, possible solutions for it, and an example to validate correct access to the resource.

Stack Frame: at ADALNativeWrapper.ADALGetAccessToken(String username, IntPtr password, String stsURL, String servicePrincipalName, ValueType correlationId, String clientId, Boolean* fWindowsIntegrated, Int64& fileTime) at ADALNativeWrapper.ADALGetAccessToken(String username, String password, String stsURL, String servicePrincipalName, ValueType correlationId, String clientId, Int64& fileTime) at System.Data.SqlClient.ActiveDirectoryNativeAuthenticationProvider.c__DisplayClass2_0.

 

ADALNativeWrapper.ADALGetAccessToken refers to a method or function related to the ADAL (Active Directory Authentication Library) Native Wrapper. ADAL is a library provided by Microsoft that enables developers to authenticate users and obtain access tokens for accessing protected resources, typically in the context of Azure Active Directory (Azure AD) authentication.

 

The specific method ADALNativeWrapper.ADALGetAccessToken is likely part of the ADAL wrapper code and is used to retrieve an access token for a given user or client application. Access tokens are commonly used in OAuth 2.0-based authentication flows to authorize access to protected APIs or resources.

Workflow process to receive a token

 

The workflow process to receive a token, including the use of SSL and ports, typically involves the following steps:

 

1. Client Authentication: The client application initiates the authentication process by sending a request to the authentication server, typically using a secure HTTPS connection (SSL/TLS) over a specific port (e.g., port 443).

2. SSL Handshake: The client and server perform an SSL handshake to establish a secure encrypted connection. This involves exchanging SSL certificates, verifying their authenticity, and negotiating encryption algorithms and session keys.

3. User Authentication: The authentication server validates the credentials provided by the user, such as username and password or other authentication methods like multi-factor authentication. Once the user is authenticated, the server proceeds to generate an access token.

4. Token Generation: The authentication server generates an access token, which typically includes information about the user and their permissions. The token is signed using a private key known only to the server.

5. Token Response: The authentication server sends the access token back to the client application as a response to the authentication request. This response is typically sent over the same SSL/TLS connection established earlier.

6. Token Validation: The client application receives the access token and verifies its authenticity and integrity. This involves validating the signature using the public key associated with the authentication server's SSL certificate.

7. Secure Communication: With the validated access token, the client application can securely communicate with the protected resources, such as APIs or services, by including the token in the request headers. The server hosting the resources will verify the token's validity before granting access.

 

Test the connectivity

So, let's try to play with the following PowerShell Script to reproduce issues using AAD Password authentication:

 

 

$TenantId = "7acc0f8a-xxx-xxxxx-xxxx"
$ClientId = "8edefa3d-xxxx-xxx-xxxxx-xxxx"
$Username = "username@domain.com"
$Password = "Password"
$Resource = "https://database.windows.net/"
$ClientSecret = "xxxxxxxxxxxx"

$TokenEndpoint = "https://login.microsoftonline.com/$TenantId/oauth2/token"

$Body = @{
    grant_type = "client_credentials"
    client_id = $ClientId
    client_secret = $ClientSecret
    username = $Username
    password = $Password
    resource = $Resource
}

$Response = ""
$Response = Invoke-RestMethod -Method Post -Uri $TokenEndpoint -Body $Body

# Print the response
$Response | ConvertTo-Json

 

 

The given PowerShell script is used to obtain an access token from Azure Active Directory (Azure AD) by performing a password-based authentication using the client credentials grant type. Here's a breakdown of the variables used in the script and their significance:

 

- $TenantId: This variable represents the unique identifier (UUID) of the Azure AD tenant. The tenant ID is used to specify the directory in which the authentication and authorization process will take place.

- $ClientId: This variable refers to the client application's ID or Application ID. It is a UUID assigned to the client application registered in Azure AD. The client ID is used to identify and authorize the specific client application making the authentication request.

- $Username: This variable holds the username or user identity associated with the account being used for authentication. In this script, it is used for password-based authentication, where the user's credentials are directly provided in the request.

- $Password: This variable contains the password associated with the given username. It is used to authenticate the user during the password-based authentication process.

- $Resource: This variable specifies the resource or service endpoint for which the access token is being requested. In this case, it is set to `"https://database.windows.net/"`, indicating that the token will be used to access a Microsoft Azure SQL Database.

- $ClientSecret: This variable represents a client secret, which is typically used for authentication in scenarios where the client application is not directly interacting with the user. It acts as a password for the client application and is used to authenticate the client application during the token request.

 

The script constructs the token endpoint URL using the $TokenEndpoint variable by combining the Azure AD login URL (https://login.microsoftonline.com/) with the specific $TenantId to form the complete token endpoint URL.

 

The request body is created as a hashtable ($Body) that includes the necessary parameters for the token request, such as grant_type (set to "client_credentials"), client_id, client_secret,username, password, and resource.

 

The Invoke-RestMethod cmdlet sends a POST request to the token endpoint ($TokenEndpoint) with the request body ($Body). This request performs password-based authentication with the provided credentials. The response from the token endpoint, which includes the access token, is stored in the $Response variable.

 

Example of token

 

This token provided AAD (Azure Active Directory) will be JSON object representing an access token issued by Azure AD. Here's an explanation of the token properties:

 

- token_type: Indicates the type of token issued. In this case, it is set to "Bearer," which is a commonly used type for access tokens.

- expires_in: Specifies the remaining time, in seconds, until the token expires. .

- ext_expires_in: Indicates the extended expiration time, similar to expires_in, in seconds.

- expires_on: Represents the expiration timestamp of the token. 

- access_token: This property contains the actual access token value, a long string of characters. The access token is used to authenticate and authorize requests to the specified resource (in this case, the Azure SQL Database).

 

Access tokens are time-sensitive and should be obtained and used within their validity period.

Based on this situation if we have an error

 

There are several possible issues that could arise when trying to correctly obtain resources such as the port, DNS, or other parameters based on the provided PowerShell script. Some common problems could include:

 

1. Errors in the provided parameters: If the values of parameters such as TenantId, ClientId, Username, Password,Resource, or ClientSecret are provided incorrectly or contain typographical errors, the script will not be able to authenticate properly, and the access token will not be generated.

 

2. Network connectivity issues: If the script is being executed in an environment where network connectivity is poor or nonexistent, it may not be able to establish a connection to the token endpoint or Azure AD services for authentication. This can result in failures when requesting the access token.

 

3. Firewall or proxy restrictions: If firewalls or proxies are in place that block or restrict the outgoing connections required by the script, the connection to the token endpoint or Azure AD services may not be established. In such cases, it is necessary to ensure that the network restrictions allow the necessary communications.

 

4. Permission and role issues: If the user account or identity being used in the script does not have the proper permissions or does not have a role assigned that allows it to obtain access tokens, the authentication will fail. Ensure that the user account has the necessary permissions to authenticate and obtain access tokens.

 

5. Time-related and expiration issues: Access tokens have a limited lifespan. If the script is executed after the access token has expired, the authentication request will not be successful. Make sure that the script is executed within the validity period of the access token.

Additionally, there are other possible incidents related to DNS not functioning correctly or failing to resolve the name, the port 443 not being open, or the network routes with access to the port not being correctly identified. These issues can result in the script being unable to establish the necessary connections and authenticate with Azure AD.

 

It is important to verify the parameter values, check network connectivity, configure firewall or proxy restrictions properly, ensure appropriate permissions are in place, consider token lifetimes, and address any potential DNS or port-related issues to ensure successful authentication.

 

How to test the connection

 

To verify aspects such as DNS resolution, port availability, and network connectivity, you can perform various checks and validations. Here are the details and steps for each aspect:

 

1. DNS Resolution:

- To check DNS resolution, you can use the nslookup command in the command prompt or terminal. Execute the following command: nslookup <hostname> where <hostname> is the DNS name or domain you want to verify.
- This command will provide information about the resolved IP address and the DNS server used for resolution. Ensure that the IP address is correctly resolved and matches the expected value.

2. Port Availability:
- You can check if a specific port is open and accessible using the Test-NetConnection cmdlet in PowerShell or the telnet command in the command prompt or terminal.
- In PowerShell, execute the following command: Test-NetConnection -ComputerName <hostname> -Port <port>, replacing <hostname> with the target host and <port> with the port number you want to verify.
- In the command prompt or terminal, use the `telnet` command as follows: telnet <hostname> <port>.
- If the port is open and accessible, you will receive a successful response. Otherwise, an error or timeout message will indicate that the port is not reachable.

3. Network Connectivity:
- To test network connectivity, you can use the ping command in the command prompt or terminal. Execute the following command: ping <hostname> replacing <hostname> with the target host you want to test.
- The ping command sends ICMP Echo Request messages to the target host and receives ICMP Echo Reply messages if the host is reachable.
- If you receive successful replies, it indicates that network connectivity is established. If there are no replies or you encounter timeouts, it suggests a connectivity issue.

 

Additional Information

Additional Endpoints Required for AAD Authentication and CRL Checks for Azure SQL DB - Microsoft Com...

 

Enjoy!

Version history
Last update:
‎Jun 22 2023 08:00 AM
Updated by: