Creation of the b2c-extensions-app by script - azure

When you create a ADB2C Tenant Resource, an application registration is also created, named b2c-extensions-app. Do not modify. Used by AADB2C for storing user data. This is a special application which is needed for crud operations.
Around the internet and in the docs, it is mentioned that it gets created automatically, but that's not the case. It is created only after you login into that tenant and go to app registrations, it is a trigger of some sorts. How do I know this? I reached to Microsoft support.
My question: this interferes with some of my automation scripts. Does anyone know of an endpoint to which I can make a rest request so this app gets created.

Okay, after a lot and I mean a lot of trial and error, I finally found the endpoint that causes the creation of that app. I will show a code snippet in PowerShell.
$context = Connect-AzAccount ...
# Aquire an access token from the resource: https://management.core.windows.net/
$tokenItem = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate(
$context.Account,
$context.Environment,
$TenantId,
$null,
'Never',
$null,
'https://management.core.windows.net/')
Invoke-WebRequest -Uri "https://main.b2cadmin.ext.azure.com/api/tenants/GetAndInitializeTenantPolicy?tenantId=<your_tenant_name>&skipInitialization=false" `
-Method "GET" `
-Headers #{
"Authorization" = "Bearer $($tokenItem.AccessToken)";
"x-ms-client-request-id" = ([guid]::NewGuid().Guid)
}

Related

Azure Managed Identity Resource for AKS

I'm trying to follow the guide outlined at this link to generate an access token for AKS for the system assigned managed identity.
The code snippet at the link is doing the following from an app service kudu console:
$resource = "https://graph.microsoft.com"
$endpoint = $env:IDENTITY_ENDPOINT
$header = $env:IDENTITY_HEADER
$apiVersion = "2019-08-01"
$headers = #{ 'X-Identity-Header' = $header }
$url = "$($endpoint)?api-version=$apiVersion&resource=$resource"
$response = Invoke-RestMethod -Method Get -Uri $url -Headers $headers
$response.access_token
Although this snippet works, the resource identifier varies depending on the resource for which you're requesting the access token. I'm not sure what resource value must be specified to get this for AKS. I have found it for the following, but not for AKS:
https://servicebus.azure.net
https://graph.microsoft.com
https://management.azure.com
https://database.windows.net
https://relay.azure.net
https://eventhubs.azure.net
Does anyone know what this ought to be for AKS?
Figured it out. Apparently after deploying AKS a new Microsoft generated enterprise application is created under your tenant called "Azure Kubernetes Service AAD Server" and has a universal GUID:
6dae42f8-4368-4678-94ff-3960e28e3630.
This should be used as the resource.
Surprisingly there's no mention on any Microsoft authored documentation regarding this. Stumbled across this on other sites.
Hope this helps someone else.
Some references:
Reference to this on github
Reference to this on related SO post

Create Azure AD Tenant from command or API

I have been working on creating New Tenant from API or Command Line in Azure Active Directory and I could not find a way to do it.
I have been also using Azure GraphAPI but it doesn't support this.
Is there any way from command or API that I can use to automate creation of new tenants?
I have researched on google and stackoverflow, but I didn't find any way to do it from command or API.
and is there any plan of Microsoft to provide such API in future? (edited)
There's no public, documented or supported (by MSFT) API available for this. That being said you might try using the portal internal API with something like this:
Invoke-WebRequest -Uri "https://main.iam.ad.ext.azure.com/api/Directories" `
-Method "POST" `
-Headers #{
"Accept-Language"="en"
"Authorization"="Bearer <azure ad access token issued for aud=74658136-14ec-4630-ad9b-26e160ff0fc6>"
} `
-ContentType "application/json" `
-Body "{`"companyName`":`"<company name>`",`"initialDomainPrefix`":`"<initial domain prefix (the one that will be appended to onmicrosoft.com)>`",`"countryCode`":`"<iso (2 letter) country code>`"}"

Blocking admin user sign-in using Microsoft Graph

I am writing a Powershell script, which is leveraging the Microsoft Graph using an App Registration. The script is getting a list of admins within our tenancy and it's checking to see if they have logged in within a 30 day time-frame. If they haven't, a notification email is sent and their account sign-in is toggled to blocked.
The email notification part of the code works as intended, but it's the sign-in toggle I am having trouble getting to work from Powershell, since I am getting a 'Forbidden 403' error when I run the code.
I've tried running the sign-in toggle using the Graph Explorer and it worked as intended.
#CREATE ACCESS TOKEN
$token = Invoke-RestMethod -Uri https://login.microsoftonline.com/$tenant/oauth2/token?api-version=1.0 -Method Post -Body #{"grant_type" = "client_credentials"; "resource" = "https://graph.microsoft.com/"; "client_id" = $clientID; "client_secret" = $clientSecret}
$Headers = #{
'authorization'="Bearer $($Token.access_token)"
}
#Url
$apiAccount = "https://graph.microsoft.com/v1.0/users/$userPrincipalName"
#TOGGLE SIGN-IN
$blockaccount = "{
""accountEnabled"": ""false""
}"
Invoke-RestMethod -Headers $headers -Uri $apiAccount -Body $blockaccount -ContentType "application/json" -Method Patch
# My App Registration permissions (Application)
AuditLog.Read.All
Directory.ReadWrite.All
Mail.Send
User.ReadWrite.All
When running the code, I get a 'Forbidden 403' error. I've even tried adding the App Registration to the Helpdesk Admin role in Azure and that didn't yield any success either.
On the Documentation page, https://learn.microsoft.com/en-us/graph/api/user-update you’ll see an important hint when updating users. It says you’ll need the delegated Directory.AccessAsUser.All permission to update the passwordProfile property.
My guess is that you’ll also need that (with an admin logged-in) to enable/disable the login status.

Cannot set "preAuthorizedApplications" object in new App registrations module through Azure Powershell

Short Scenrario: A muti tenant front end javascript (React.JS) Web Application calls a multi tenant ASP.NET Core 2.2 WebAPI from the browser.
Authentication:
ADAL.js in the front end app takes care of getting a token from either AzureAD1 or AzureAD2 or AzureAD3... when the User signs-in (based on the User's original Azure Active Directory).
The User gives consent to the front end Web App (scope: Sign in and read user profile) which is delegated to the WebAPI too. (meaning the user does not need to consent to the WebAPI as well)
The front end Web App calls the WebAPI with the bearer token to get the resources.
Problem: I must automate the deployment of a new environment. And set the manifest file accordingly (It's a SaaS solution)
In the manifest file I need to expose the WebAPI for the client application (https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-expose-web-apis#expose-a-new-scope-through-the-ui)
Setting "knownClientApplications" is not enough (due to previously described delegation)
The new v2 endpoint (https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-overview) has a new App Registration feature. The old one is called "Legacy" now and will be deprecated starting May 2019.
In the Azure Portal need to expose the API and add the front end WebApp as an "Authorized cient applications".
This step will add a new object in the manifest file:
"preAuthorizedApplications": [
{
"appId": "guid",
"permissionIds": [
"guid"
]
}
],
But it's still not available throuh PowerShell! (https://learn.microsoft.com/en-us/powershell/module/azuread/set-azureadapplication?view=azureadps-2.0)
How can I add this "preAuthorizedApplications" section into the manifest file using Azure PowerShell? Why is it available in the portal but not in PS yet? It's the other way around usually...
08-05-2019 Update based on the answer:
I am getting the access token via a Service Principal:
$adTokenUrl = "https://login.microsoftonline.com/$TenantId/oauth2/token"
$resource = "https://graph.windows.net/"
$body = #{
grant_type = "client_credentials"
client_id = "$ServicePrincipalId"
client_secret = "$ServicePrincipalKey"
resource = "$resource"
}
$response = Invoke-RestMethod -Method 'Post' -Uri $adTokenUrl -ContentType "application/x-www-form-urlencoded" -Body $body
$token = $response.access_token
According to the docs: https://learn.microsoft.com/en-us/graph/api/application-update?view=graph-rest-beta&tabs=cs
The Service Principal should have at least Application.ReadWrite.OwnedBy, and most Application.ReadWrite.All privileges.
Should I ask our AAD admin to grant the below rights to the Service Principal?
08-05-2019 Update 2: Service Principal has been granted with ALL of the highlighted rights above.
Attempt 1:
Step 1: getting an access_token via the Service Principal (Owner of the Api app to be updated)
$adTokenUrl = "https://login.microsoftonline.com/$(TenantId)/oauth2/token"
$resource = "https://graph.microsoft.com/"
$body = #{
grant_type = "client_credentials"
client_id = "$(ServicePrincipalId)"
client_secret = "$(ServicePrincipalKey)"
resource = "$resource"
}
$response = Invoke-RestMethod -Method 'Post' -Uri $adTokenUrl -ContentType "application/x-www-form-urlencoded" -Body $body
$token = $response.access_token
Step 2: using this access_token, building up my PATCH request as per Md Farid Uddin Kiron's suggestion, and
Result: The remote server returned an error: (403) Forbidden.
09-05-2019 Update 3: After some kind and detailed explanation and guidance, I got this to work and getting HTTP 204 for my Postman request. Only thing left is to integrate this steps into my pipeline.
See accepted answer. It works. If someone has the same issue,
please read the other answer from Md Farid Uddin Kiron.
If you want to avoid calling directly the graph API (maybe you are in an azure pipeline using a Service Connection and don't have access to the credentials) you can do this :
$AppName = << WebApp >>
$preAuthorizedApplicationsAppId = <<GUID>>
# Get the application and delegated permission to pre-authorize
$appRegistration = Get-AzureADMSApplication -Filter "displayName eq '$AppName'"
$oauth2Permission = $appRegistration.Api.OAuth2PermissionScopes | Where-Object {$_.Value -eq $AppName -and $_.Type -eq 'Admin'}
# Build a PreAuthorizedApplication object
$preAuthorizedApplication = New-Object 'Microsoft.Open.MSGraph.Model.PreAuthorizedApplication'
$preAuthorizedApplication.AppId = $preAuthorizedApplicationsAppId
$preAuthorizedApplication.DelegatedPermissionIds = #($oauth2Permission.Id)
$appRegistration.Api.PreAuthorizedApplications = New-Object 'System.Collections.Generic.List[Microsoft.Open.MSGraph.Model.PreAuthorizedApplication]'
$appRegistration.Api.PreAuthorizedApplications.Add($preAuthorizedApplication)
# Update the Application object
Set-AzureADMSApplication -ObjectId $appRegistration.Id -Api $appRegistration.Api
This answer comes from this GitHub issue.
You are right, seems there is something faultiness exists in AzureAD powershell module. That not works for me too .
If you want to modify your app manifest using powershell to add "preAuthorizedApplications" section, you can try the powershell script below.
I have tested on my side and it works for me.
In theory, I have called Microsoft Graph API to modify the app manifest . If you have any further concerns, please feel free to let me know.
$AdAdminUserName = "<-your Azure ad admin username ->"
$AdAdminPass="<-your Azure ad admin password ->"
$AdAppObjId = "<-your app obj id->"
$AdPreAuthAppId = "<-the app that need to be pre authed ->"
$AdAppScopeId = "<-your app scope id->"
$tenantName = "<-your tenant name->"
$body=#{
    "grant_type"="password";
    "resource"="https://graph.microsoft.com/";
    "client_id"="1950a258-227b-4e31-a9cf-717495945fc2";
    "username"=$AdAdminUserName;
    "password" = $AdAdminPass
}
$requrl = "https://login.microsoftonline.com/"+$tenantName+"/oauth2/token"
$result=Invoke-RestMethod -Uri $requrl -Method POST -Body $body 
$headers = New-Object 'System.Collections.Generic.Dictionary[String,String]'
$headers.Add("Content-Type","application/json")
$headers.Add("Authorization","Bearer " + $result.access_token)
$preAuthBody = "{`"api`": {`"preAuthorizedApplications`": [{`"appId`": `"" + $AdPreAuthAppId + "`",`"permissionIds`": [`"" + $AdAppScopeId + "`"]}]}}"
$requrl= "https://graph.microsoft.com/beta/applications/"+$AdAppObjId
Invoke-RestMethod -Uri $requrl -Method PATCH -Body $preAuthBody -Headers $headers
Note: ROPC is not safe as Microsoft does not recommend to use that. It also does not allow to use MFA that is why it is little
dangerous.
Some additions to another reply.
Actually, in AzureADPreview powershell module, there is a parameter -PreAuthorizedApplications for Set-AzureADApplication. But neither the cmdlet help nor the documentation page has been updated to detail all these, it was also mentioned here.
I am not sure the parameter will work or not, per my test, I always get a bad request error. Even if I call the Azure AD Graph API, I get the same error. The command Set-AzureADApplication essentially calls the Azure AD Graph API, so if the parameter works, it will also work for the API. Also, in the AAD Graph doc, there is no such property. According to the test result, the parameter seems not to work currently. (not sure, if there is something wrong, please correct me)
I got this error too using client_credentials type to get access_token to call that API even though I granted all Microsoft Graph API and AAD API application related permissions. It is really weird.
However , using password flow to get access token under Azure AD admin account will be able to call this API successfully :
Update
You could get your client id and client secret by below steps
Go to azure portal on azure active directory menu see the screen
hot below:
Once you select azure active directory you would see App
registrations click on that. Then select your application. See the below picture
On your apllication you would see the client id, tenant id and
client secret which marked on the screen shot below:
If you still have any concern please feel free to share. Thank you and happy coding!
to resolve token issue I did like this(if you have az subscription owner, in this case you can get token which allows to update aad owned application properties without aad admin login and password). After az login by subscription owner:
$msGraphAccess = az account get-access-token --resource "https://graph.microsoft.com |
ConvertFrom-Json
$accessToken = $msGraphAccess.accessToken
$headers = New-Object 'System.Collections.Generic.Dictionary[String,String]'
$headers.Add("Content-Type", "application/json")
$headers.Add("Authorization", "Bearer " + $accessToken)

How do I access the GRAPH API to get all users WITHOUT having to login ?

What I want is simple but I have not found a clear answer.
I have a simple console app and all I want to do is get all the users in my Azure AD using the new GRAPH API. All the examples I have require the program login (OAuth?). I don't want that. I want to give the code the user/pw and simply start calling the methods.
Whenever you have a user physically sitting at the device, your best bet, by far, is to invoke the full sign-in flow. Not only does keep an admin's credentials from being exposed, but it also allows the user to change password if needed, invoke multi-factor authentication, etc.
However, there are some scenarios where you want an entirely unsupervised service running on a completely secure and trusted machine. (Known as a "confidential client" in OAuth 2.0.) This can be achieved with the OAuth 2.0 Client Credentials Grant flow, which uses only the application's credentials to authenticate. This is illustrated in Service to Service Calls Using Client Credentials.
Using ADAL, this flow is invoked by using either AuthenticationContext.AcquireToken(String, ClientCredential) (where your credential is an password credential--a string), or AuthenticationContext.AcquireToken(String, ClientAssertionCertificate) (where your credential is a certificate that you use to sign an assertion). There is a .NET (C#) sample for each of these on the Azure AD samples for daemon applications:
Calling web APIs in a daemon or long-running process
Authenticating to Azure AD in daemon apps with certificates
Using PowerShell and certificate authentication, it would look something like this:
$appId = "<app client ID>"
$resource = "https://graph.windows.net" # (or other resource URI)
$tenantId = "<domain name or ID>"
$certThumbprint = "<certificate thumbprint>"
# Get locally-installed cert by thumbprint
$x509cert = Get-ChildItem "Cert:\LocalMachine\My" | ? { $_.Thumbprint -eq $certThumbprint } | Select-Object -First 1
# Get access token using ClientAssertionCertificate
$authority = "https://login.microsoftonline.com/$tenantId"
$creds = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate $appId, $x509cert
$authContext = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext $authority
$authResult = $authContext.AcquireToken($resource, $creds)
# Make Graph API request to list all users
$header = #{
"Authorization" = "Bearer $($authResult.AccessToken)"
"Content-Type" = "application/json"
}
$result = Invoke-RestMethod -Method Get -Headers $header -Uri "https://graph.windows.net/$tenantId/users?api-version=1.6"
($result.Content | ConvertFrom-Json).value
You will need to ensure your application is registered in Azure AD, and has the minimum required application permissions for what you're trying to do (and not more than that, to limit your exposure if the app's credentials were to be compromised). For example, if your application only needs to read directory data (e.g. to find a user by email address), you would set the permissions like this:
Here is the PowerShell script I wrote.
# Adding the AD library to your PowerShell Session.
Add-Type -Path 'C:\Program Files\Microsoft Azure Active Directory Connect\Microsoft.IdentityModel.Clients.ActiveDirectory.dll'
# This is the tenant id of you Azure AD. You can use tenant name instead if you want.
$tenantID = "<the tenant id of Azure AD>"
$authString = "https://login.microsoftonline.com/$tenantID"
# Here, the username must be MFA disabled user Admin at least, and must not be a live id.
$username = "<the username of the AD's Admin>"
$password = "<the password of the above user>"
# The resource URI for your token.
$resource = "https://graph.windows.net/"
# This is the common client id.
$client_id = "1950a258-227b-4e31-a9cf-717495945fc2"
# Create a client credential with the above common client id, username and password.
$creds = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential" `
-ArgumentList $username,$password
# Create a authentication context with the above authentication string.
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" `
-ArgumentList $authString
# Acquire access token from server.
$authenticationResult = $authContext.AcquireToken($resource,$client_id,$creds)
# Use the access token to setup headers for your http request.
$authHeader = $authenticationResult.AccessTokenType + " " + $authenticationResult.AccessToken
$headers = #{"Authorization"=$authHeader; "Content-Type"="application/json"}
# Get the users.
Invoke-RestMethod -Method GET -Uri "https://graph.windows.net/$tenantID/users?api-version=1.6"
If you are using C#, it would be really similar, because my script is actually translated from C# code. For other Programing language, there are similar APIs in the corresponding Azure SDK. If not, you might consider using OAuth2.

Resources