With Azure AD External Identities, Microsoft is bringing some of the Azure AD B2C features to “regular” Azure AD, and it is now generally available (GA). With these features, you can add public self service sign up-baed authentication flows to your services, using your existing Azure AD.
Continue reading “Using Azure AD External Identities to power self service sign-in for a web site”Checking out the new Azure AD Temporary Access Pass preview feature
So, “Temporary Access Pass (Preview)” just popped out as an available authentication method in my demo tenant, and I figured this was something that needs investigation!

Batch creating privileged access groups in Azure AD
Quick blogpost today, showing how to batch create privileged access groups for the Privileged Identity Management feature in Azure AD. The endpoint used is not currently documented in the Graph documentation.
First thing you need to do is get yourself an access token. Follow my guide for this. This script will use a hardcoded variable for the token.
# Get your access token somehow, not in scope for this example
$accesstoken = "eyJ0eXAiOiJKVGtHUniJSUzI1NiIs--- snip ---wFzrJUYkOm37KY27WJvQ"
# Groups to create
$groups = "test12345","test123468","test9577","test304934089"
# No need to edit below this line
# Build header value
$headers = @{Authorization = "Bearer $accesstoken"}
$groups | Foreach {
# Check if group already created
$matching = Invoke-RestMethod "https://graph.microsoft.com/beta/groups?`$filter=displayName eq '$($_)'" -Headers $headers
$id = $null
# Create if no group was found
if(!$matching.value) {
Write-Verbose "Creating group: $($_)" -Verbose
$body = @{
displayName = $_
isAssignableToRole = $true
mailEnabled = $false
mailNickname = $_
securityEnabled = $true
} | ConvertTo-Json
$creation = Invoke-RestMethod "https://graph.microsoft.com/beta/groups" -Headers $headers -Method Post -Body $body -ContentType "application/json"
Write-Verbose "Group '$($_)' created with object id $($creation.id)" -Verbose
$id = $creation.id
} else {
Write-Verbose "Group '$($_)' already created" -Verbose
$id = $matching.value[0].id
}
# Check for PIM registration of group
$pimmatching = Invoke-RestMethod "https://graph.microsoft.com/beta/privilegedAccess/aadGroups/resources?`$filter=externalId eq '$id'" -Headers $headers
# Register group in PIM, if not already registered
if(!$pimmatching.value) {
Write-Verbose "Registering group $($_) ($id) in PIM" -Verbose
$body = @{
externalId = $id
} | ConvertTo-Json
$registration = Invoke-RestMethod "https://graph.microsoft.com/beta/privilegedAccess/aadGroups/resources/register" -Headers $headers -Method Post -Body $body -ContentType "application/json"
} else {
Write-Verbose "Group $($_) already registered in PIM" -Verbose
}
}
Finding synced accounts with Azure AD privileges
In a recent blogpost, Protecting Microsoft 365 from on-premises attacks, it is recommended to not federate (which I have been recommending for years) and not to synchronize accounts with privileged access to Azure AD and Microsoft 365. This post contains a few script to help you determine synchronized accounts with privileged access to Azure AD.
Continue reading “Finding synced accounts with Azure AD privileges”Accessing the backend Azure AD APIs behind portal.azure.com
There are many features that are currently “UI only” with Azure AD, managed through the Azure Portal. However, some times it can be useful to being able to access these things through scripts, such as for auditing or whatever.
Behind the Azure Portal, there are several APIs that are public facing, but undocumented and not meant for being used directly. Follow this guide with caution, as there is things that can go wrong if you start posting or patching to these APIs.
Continue reading “Accessing the backend Azure AD APIs behind portal.azure.com”Reporting signin methods registered in your Azure AD
Azure AD contains several different means of signing in; password, mobile phone, fido2 keys etc., but how are your users using these options? Here is a script for reporting statistics for exactly that.
Continue reading “Reporting signin methods registered in your Azure AD”Terraform – Specifying parameters to azurerm_resource_group_template_deployment
Here is a quick example on how to provide parameters to azurerm_resource_group_template_deployment, as the documentation is currently very poor.
Here is a quick main.tf:
variable "location" {
default = "westeurope"
type = string
description = "The Azure location where all resources in this example should be created"
}
provider "azurerm" {
features {}
}
data "azurerm_client_config" "current" {}
data "azurerm_subscription" "current" {}
resource "azurerm_resource_group" "rg" {
name = "testResourceGroup1"
location = var.location
}
resource "azurerm_resource_group_template_deployment" "example" {
name = "testLogicApp1"
resource_group_name = azurerm_resource_group.rg.name
deployment_mode = "Complete"
template_content = file("logicapp.json")
parameters_content = jsonencode({
azure_location = {value = azurerm_resource_group.rg.location}
name = {value = "testLogicApp1"}
azure_function_code = {value = "testtesttest"}
})
}
As you can see, the parameters_content is converted from a Terraform object to JSON using jsonencode, and all values must be provided like you would define parameters using az deployment, with “value=xx”.
And this is my ARM template for the LogicApp:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"azure_location": {
"defaultValue": "westeurope",
"type": "string"
},
"name": {
"type": "String"
},
"azure_function_code": {
"type": "String"
}
},
"variables": {
},
"outputs": {
"principalId": {
"type": "string",
"value": "[reference(concat(resourceId('Microsoft.Logic/workflows', parameters('name')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2018-11-30').principalId]"
},
"tenantid": {
"type": "string",
"value": "[reference(concat(resourceId('Microsoft.Logic/workflows', parameters('name')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2018-11-30').tenantid]"
},
"resourceId": {
"type": "string",
"value": "[resourceId('Microsoft.Logic/workflows', parameters('name'))]"
}
},
"resources": [
{
"type": "Microsoft.Logic/workflows",
"apiVersion": "2017-07-01",
"name": "[parameters('name')]",
"location": "[parameters('azure_location')]",
"identity": {
"type": "SystemAssigned"
},
"dependsOn": [
],
"resources": [],
"properties": {
"state": "Enabled",
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"azurefunctioncode": {
"defaultValue": "[parameters('azure_function_code')]",
"type": "String"
}
},
"triggers": {
"Recurrence": {
"recurrence": {
"frequency": "Day",
"interval": 1,
"schedule": {
"hours": [
"2"
],
"minutes": [
5
]
}
},
"type": "Recurrence"
}
},
"actions": {
},
"outputs": {}
}
}
}
]
}
A look behind the Azure AD “Permission classifications” preview
For a long time, Azure AD has been criticized for having a too liberal approach to user consents by default, with users being able to delegate things like “Mail.ReadWrite” allowing apps to send and receive emails, as well as reading any existing emails, and “User.ReadBasic.All” allowing your users to consent to third party applications reading ALL of your users basic profiles. Combine this with the “offline_access” scope, where the 3rd party apps can essentially retain access after the user has logged out of the app, this soon becomes a bit of a nightmare.
Continue reading “A look behind the Azure AD “Permission classifications” preview”Importing users to Azure AD B2C rapidly using the batch endpoint
Just migrated in total 4 million accounts to Azure AD B2C, and that required a few tricks in order to manage in time. The batch endpoint helped out nicely, and here is a quick a easy module you can use.
Continue reading “Importing users to Azure AD B2C rapidly using the batch endpoint”Using Azure AD Privileged Identity Management with Active Directory roles (such as domain admin)

I just put my Azure AD Group Writeback Script on Github, and figured it was time to do something I know many have requested from Microsoft to deliver, but that is still missing; Using Azure AD Privileged Identity Management to control access to Active Directory built-in groups such as Domain Admin, Schema Admin and Enterprise Admin.
Continue reading “Using Azure AD Privileged Identity Management with Active Directory roles (such as domain admin)”