Offline Domain Join using XOAP and Azure Blob storage

Offline Domain Join using XOAP and Azure Blob Storage
Use the Offline Domain Join module to Domain Join a device that doesn't have access to the Domain Controller. Download here for free!


Our module allows you to Domain Join a device that doesn’t have access to the Domain Controller (through the company network or via VPN). It’s an alternative to using Azure Hybrid Join.

While Azure Hybrid Join adds a device to Azure AD (Entra) and local AD, this option allows joining a device to local AD only. Meanwhile, Hybrid Join is limited regarding naming convention and only allows the defining of the prefix.

With this solution, it’s possible to define a prefix and to use a serial number of computers for the computer name.

Who is this for?

You can benefit from using this module whether you’re a XOAP user or not. Here’s how:

a) If you’re a XOAP user, simply set up Windows clients for use of Offline Domain Join via Azure Blob Storage using this module and XOAP console.

b) If you’re not a XOAP user, use this module in your own DSC environment, or use PowerShell scripts inside this module to create their own automation alternative for Offline Domain Join.

🚀 Want to experience everything XOAP has to offer? You can always start your free 30-day trial.

What does this module do?

To explain further, this module will rename the computer using the serial number and defined prefix. Afterwards, it’ll make an Offline Domain Join of the device via Azure Blob storage; if wanted.

The computer creates a request and posts it on a defined location on Azure Blob. Then, the Domain Controller will take that request and post a response on Azure Blob. This response file is then read by a computer – and the computer makes Offline Domain Join. Furthermore, the certificate will be imported from Azure Blob.

What do I need to know before I start?

To understand how to use it, knowledge of PowerShell, Active Directory and Azure Storage is needed along with these 3 components:

  1. Server-side: modify Domain Controller to allow for Offline Domain Join
  2. Azure Blob Storage: storage to host files needed for Offline Domain Join
  3. XOAPOfflineDomainJoinViaBlobDSC: to set up Windows client to create request and fetch the answer for Offline Domain Join

List of prerequisites:

  • AzureAZ PowerShell Module (if not installed ‘Az.Accounts’ and ‘Az.Storage’ submodules are going to be installed while running this DSC module);  
  • ComputerManagementDsc in version 8.5.0; 
  • Azure Blob storage; 
  • Local Active Directory; 
  • PowerShell script that reads the request from Azure Blob Storage and sets response file and machine certificate to Azure Blob storage (example below).
					$WarningPreference = "SilentlyContinue" 
$Domain = "" 
$OU = "OU=Notebooks,OU=Koeln,DC=test,DC=local,DC=com" 
$Tenant_ID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 
$Subscription_ID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 
$ResUsername = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 
$SAccountname = 'xoapdeployments' 
$ContainerName = "adjoin" 
$FExt = ".blb" 
$BlobFolder ="adblob" 
$RequestFolder = "request" 
$JoinName ="" 
Set-Location C:\Scripts 
#SecPass.exe generetes password for Azure access 
$SecPassStr = cmd /c .\SecPass.exe $args 2`>`&1    
$cred = New-Object System.Management.Automation.Pscredential($ResUsername, (ConvertTo-SecureString -String $SecPassStr)) 
$ARMA = Add-AzureRmAccount -ServicePrincipal -Credential $cred -TenantId $Tenant_ID -Subscription $Subscription_ID 
$storageContainer = Get-AzureRmStorageAccount | where {$_.StorageAccountName -eq $SAccountname} | Get-AzureStorageContainer 
$ComputerFiles = $storageContainer | Get-AzureStorageBlob | where {$_.Name.Contains($RequestFolder) -and !($_.Name.Contains("flag.flg"))}  | Select-Object "Name" ,"LastModified" 
# $ComputerFiles 
if($ComputerFiles) { 
    foreach($Computerfile in $ComputerFiles) { 
        $JoinName = $ComputerFile.Name.Replace("/","\") 
        # $JoinName 
        $storageContainer | Remove-AzureStorageBlob -Container $ContainerName -Blob ($JoinName) -Force 
        $JoinName = $JoinName.SubString(8) 
        $ADblobfile = $Computername + ".blob" -f $computer 
        $BlobName = ".\" + $JoinName + $FExt 
        # $BlobName 
        $run = "djoin.exe /provision /domain {0} /MachineOU {1} /machine {2} /savefile {3} /reuse /rootcacerts" -f $Domain, $OU, $JoinName, $BlobName 
        # $run 
        Invoke-Expression $run 
        $StorageBlob = $BlobFolder + "\" + $JoinName + $FExt 
        # $Storage 
        $storageContainer | Set-AzureStorageBlobContent –File $BlobName -Blob $StorageBlob -Properties @{"ContentType" = "text/plain"} 
        $storageContainer | Remove-AzureStorageBlob -Blob ($RequestFolder + "\" + $JoinName) -Force 
        Remove-Item -Path $BlobName 
Remove-AzureRmAccount -Username $ResUsername  


Available resources and syntax

					OfflineDomainJoinViaBlob [String] #ResourceName 
    [DependsOn = [String[]]] 
    [PsDscRunAsCredential = [PSCredential]] 
    Tenant_ID = [String] 
    Subscription_ID = [String] 
    Username = [String] 
    Password = [String] 
    SAccountname = [String] 
    ContainerName = [String] 
    RequestFolder = [String] 
    BlobFolder = [String] 
    CertFolder = [String] 
    [TimeoutInMinutes = [Int32]] 
    [RenameComputerUsingSerial = [Boolean]] 
    [ComputerNamePrefix = [String]] 
    [RebootAfterDomainJoin = [Boolean]] 

Saccountname  = Storage Account Name

🖱️ Ready to get started? Download this module below!

Download illustration

Download Offline Domain Join

 to Domain Join a device that doesn’t have access to Domain Controller

By downloading, you accept the XOAP privacy policy and will receive product information from us.

Share post

More Posts

EUC Hexagrid by Dizzion

The EUC Hexagrid and our role

XOAP is one of the key players in the End-User Computing (EUC) ecosystem. Check out the EUC Hexagrid for a detailed technical overview.

Scroll to Top