We have a requirement where we want to create the Azure AD application automatically for enabling Microsoft Login.
Is there any way we can programmatically achieve the creation part as everywhere it is showing the GUI steps for registering an app in Azure AD.
Thanks in Advance.
You can register the application using this api
POST https://graph.microsoft.com/beta/applications
One of the following permissions is required to call this API
1) Delegated (work or school account):
Application.ReadWrite.All, Directory.ReadWrite.All,
Directory.AccessAsUser.All
2) Delegated (personal Microsoft account):
Application.ReadWrite.All
3) Application: Application.ReadWrite.OwnedBy, Application.ReadWrite.All,
Directory.ReadWrite.All
Example:
const options = {
authProvider,
};
const client = Client.init(options);
const application = {
displayName: 'Display name'
};
await client.api('/applications')
.version('beta')
.post(application);
For more details refer this document
Related
I have set up a test project that follows this microsoft guide: https://learn.microsoft.com/en-us/azure/app-service/scenario-secure-app-access-microsoft-graph-as-app?tabs=azure-powershell
The only difference that I made from that tutorial is the code portion. I changed it to look like this:
TokenCredential tokenCredential = new DefaultAzureCredential();
var scopes = new[] { "https://graph.microsoft.com/.default" };
var graphClient = new GraphServiceClient(tokenCredential, scopes);
var group = graphClient.Groups["<my-group-id>"].Request().GetAsync().Result;
Everything works as expected when I publish the website and access it, but when I run this code locally I receive
Insufficient privileges to complete the operation.
I am signed into VS using the same account that I am using in Azure portal (it's a global admin account). Is there any other configuration setting that I am missing so that I can run this code and test locally?
Usually you need one of the following permissions to query groups i.e delegated and application permissions : GroupMember.Read.All, Group.Read.All, Directory.Read.All, Group.ReadWrite.All, Directory.ReadWrite.All User.Read.All
Run VS as administrator and also give user administrator role.
But visual studio may not work in this case . So please try with
different credential type like client secret/certificate credential
with your app .
In local debugging ,use Shared Token Cache Credential ,as in
your local environment, DefaultAzureCredential uses the shared token
credential from the IDE.
In Visual Studio, you can set the account that you want to use when
debugging using VS : under Options -> Azure Service Authentication.
Please check Azure Managed Service Identity And Local Development by Rahul Nath (rahulpnath.com)
If multiple accounts are configured, try to set the SharedTokenCacheUsername property to that specific account to use.
var azureCredentialOptions = new DefaultAzureCredentialOptions();
azureCredentialOptions.SharedTokenCacheUsername = "<azure ad User Name>";
var credential = new DefaultAzureCredential(azureCredentialOptions);
Reference: DefaultAzureCredential: Unifying How We Get Azure AD Token | Rahul Nath (rahulpnath.com)
I am developing a backend in node express where I use the passport-azure-ad library to protect the routes of my api, is there any way to access the roles defined in Azure Ad for the application and validate them in the routes?
To achieve the above requirement you may need to follow the below workaround.
We can get our Azure AD log details by using MS GRAPH Programmatically
SAMPLE CODE:-
const options = {
authProvider,
};
const client = Client.init(options);
let directoryAudit = await client.api('/auditLogs/directoryAudits/{id}')
.get();
Also you can get roles which has assigned in Azure AD by using below MS GRAPH query in your code.
GET /users/{id | userPrincipalName}/appRoleAssignments
For complete setup please refer the below links:
MS DOC:- Call the Microsoft Graph API in a Node.js console app.
SO THREAD:- How to issue tokens from Azure AD in a Node.js App/API?
Summary: I have a REST API that I use for functional testing. I only allow people or groups in a specific "Tester" role to hit the API. I want to trigger this functional testing during an Azure DevOps Release Pipeline automatically, but I can't figure out how to authorize the machine account to hit the API.
Details:
I have this API secured with [Authorize(Roles = "Tester")]
[Route("quotas/developers")]
[HttpGet]
[Authorize(Roles = "Tester")]
[SwaggerResponse(HttpStatusCode.OK, "Successful operation", Type = typeof(DeveloperQuota[]))]
public async Task<List<DeveloperQuota>> GetDeveloperQuota([FromUri]string developerUpn)
To set this up, I have an Enterprise Application registered in Azure Active Directory. In the manifest, I declare the role.
And then in the Enterprise Application I add some users and groups which are assigned the role "Tester."
This works fine for running my functional tests by hand. I run the tests, it pops up an oauth dialog for me to enter my credentials, it grabs my Bearer token from the successful auth request then passes it along to the APIs.
private string GetActiveDirectoryToken()
{
string authority = this.configuration.ActiveDirectoryAuthority;
string resource = this.configuration.ActiveDirectoryAudience;
string keyVaultUri = this.configuration.KeyVaultUri;
IKeyVaultAdapterFactory keyVaultAdapterFactory = new KeyVaultAdapterFactory();
var keyVaultAdapter = keyVaultAdapterFactory.CreateInstance(KeyVaultServicePrincipal.PowerShellAppId);
SecureString clientIdSecure = keyVaultAdapter.GetAzureKeyVaultSecretSecure(keyVaultUri, "GasCallbackRegistrationClientID", null).Result;
SecureString redirectUriSecure = keyVaultAdapter.GetAzureKeyVaultSecretSecure(keyVaultUri, "GasCallbackRegistrationClientIDRedirectUri", null).Result;
var authContext = new AuthenticationContext(authority);
var result = authContext.AcquireTokenAsync(
resource,
SecureStringUtilities.DecryptSecureString(clientIdSecure),
new Uri(SecureStringUtilities.DecryptSecureString(redirectUriSecure)),
new PlatformParameters(PromptBehavior.Auto)).Result;
return result.AccessToken;
}
Of course, if I'm running this during automation, there will be nothing to fill in the dialog with creds, nor do I want to be storing a copy of these creds, especially since these creds roll on a schedule which are maintained elsewhere.
My thought was that I could create an Azure Service Principal, associate a cert with the service principal, install the cert on my deployment machine, login as the Service Principal if the cert was available, and then put that Service Principal in the "Tester" role. The problem is I can't add a Service Principal as a user in the Enterprise Application. It only appears to allow me to add "Users and groups." I similarly can't add a service principal to a group.
Any thoughts on how I can authorize my deployment box to hit these APIs?
Roles published for applications are treated as application permissions and not assignable to other apps via the "Users and Groups" assignment screen.
To assign the app permissions to a client app, go to the client app's registration page, click on Api Permissions and then Add a Permission. Select the My Api tab, search for your application that published the app roles and you'd see the app role listed in the list below. Select that, save and then grant admin consent.
I have an Azure AD app (AAD App1) which has user assignment enabled. So only, users from a particular group let's say "Group A" can access any resource (let's say an Azure Function API) protected by that Azure AD app.
Now I have another daemon Azure function job, which needs to make an authenticated call to the above mentioned Azure function API. Since this is a daemon job, I have generated another Azure AD app (AAD App2) for this.
Below is my code to get access tokens:
string resourceId = "id of app used to authenticate azure function"; // AAD app ID used by the Azure function for authentication
string clientId = "id of app registered for the daemon job";// AAD app ID of your console app
string clientSecret = "secret of app registered for the daemon job"; // Client secret of the AAD app registered for console app
string resourceUrl = "https://blahblah.azurewebsites.net/api/events";
string domain = "<mytenant>.onmicrosoft.com"; //Tenant domain
var accessToken = await TokenHelper.GetAppOnlyAccessToken(domain, resourceId, clientId, clientSecret);
Now when I try to generate access token to access the Azure function API, I get an invalid grant error as below:
AdalException:
{"error":"invalid_grant","error_description":"AADSTS50105: Application
'' is not assigned to a role for the application
''.\r\nTrace ID:
6df90cf440-c16d-480e-8daf-2349ddef3800\r\nCorrelation ID:
4c4bf7bf-2140-4e01-93e3-b85d1ddfc09d4d\r\nTimestamp: 2018-05-09
17:28:11Z","error_codes":[50105],"timestamp":"2018-05-09
17:28:11Z","trace_id":"690cf440-c16d-480e-8daf-2349ddef3800","correlation_id":"4c4bf7bf-2140-4e01-93ef3-b85d1dc09d4d"}:
Unknown error
I am able to properly generate AAD access tokens if I disable the user assignment.
I am trying to avoid creating a service account here. Is there anyway I can add an app principal to an Azure AD group or add it as a member of another Azure AD app?
Unfortunately, you cannot add an AAD application/service principal as a member of Azure AD group.
I have confirmed this issue in My Answer for another similar question [EDIT - now seems to be possible, see said answer]
You can also upvote this idea in our Feedback Forum. Azure AD Team will review it.
Hope this helps!
Let me first describe a "manual" scenario. I login to Partner Center as a partner and go to customer list (https://partnercenter.microsoft.com/en-us/pcv/customers/list). For any customer it is possible to manage all its usage-based subscriptions in Azure portal using All resources (Azure portal) link:
In particular, I can add a co-admin to subscription (i.e. add a user with role Owner):
How to automate this management of customer's subscriptions?
My efforts: I have some experience of CREST API and RBAC API. This is limitation of an Azure Active Directory (AAD) application described in docs:
You can only grant access to resource in your subscription for applications in the same directory as your subscription.
Due to each customer's subscription exists in separate customer's AAD, it seems RBAC API cann't help:
It requires an AAD application-based token (i.e. based on TenantId,
ClientId, ClientSecret), and there is no way to
programmatically create an AAD application in customer's directory.
An application located in partner's AAD cann't get access to
customer's subscription.
Does any way to programmatically add an admin/co-admin/owner to customer's subscription exist?
With Patrick Liang help on MSDN forums, finally I've come up with a solution: enable Pre-consent feature for a partner's AAD app to grant access to customers subscriptions. Let me describe it:
1. Partner Center Explorer project
https://github.com/Microsoft/Partner-Center-Explorer/
It's a web application similar to partnercenter.microsoft.com and it's a good example of various Microsoft APIs usage. Most important, this project is a complete example of accessing customer's subscription from partner AAD app. However, it suggests user interaction (OAuth authentification to login.live.com as a partner) and I faced some issues when tried to avoid it. Below I describe how to connect to customer's subscription with all credentials already in code.
2. Partner AAD app
Create native AAD app instead of web AAD app but configure its "Permissions to other applications" the same way. Skip steps which are not applicable to native app (for example, skip client_secret obtaining and skip manifest update).
3. PowerShell script
Last step of app configuring is to run this script:
Connect-MsolService
$g = Get-MsolGroup | ? {$_.DisplayName -eq 'AdminAgents'}
$s = Get-MsolServicePrincipal | ? {$_.AppPrincipalId -eq 'INSERT-CLIENT-ID-HERE'}
Add-MsolGroupMember -GroupObjectId $g.ObjectId -GroupMemberType ServicePrincipal -GroupMemberObjectId $s.ObjectId
It's required to install several modules to execute these comandlets. If you get an error during "Microsoft Online Services Sign-In Assistant for IT Professionals" install, try to install BETA module:
Microsoft Online Services Sign-In Assistant for IT Professionals BETA
And you probably will need this one:
Microsoft Online Services Module for Windows PowerShell 64-bit
4. Code
Finally we are ready to authenticate and create a role assignment:
public async void AssignRoleAsync()
{
var token = await GetTokenAsync();
var response = await AssignRoleAsync(token.AccessToken);
}
public async Task<AuthenticationResult> GetTokenAsync()
{
var authContext = new AuthenticationContext($"https://login.windows.net/{CustomerId}");
return await authContext.AcquireTokenAsync(
"https://management.core.windows.net/"
, ApplicationId
, new UserCredential(PartnerUserName, PartnerPassword));
}
public async Task<HttpResponseMessage> AssignRoleAsync(string accessToken)
{
string newAssignmentId = Guid.NewGuid().ToString();
string subSegment = $"subscriptions/{CustomerSubscriptionId}/providers/Microsoft.Authorization";
string requestUri = $"https://management.azure.com/{subSegment}/roleAssignments/{newAssignmentId}?api-version=2015-07-01";
string roleDefinitionId = "INSERT_ROLE_GUID_HERE";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var body = new AssignRoleRequestBody();
body.properties.principalId = UserToAssignId;
body.properties.roleDefinitionId = $"/{subSegment}/roleDefinitions/{roleDefinitionId}";
var httpRequest = HttpHelper.CreateJsonRequest(body, HttpMethod.Put, requestUri);
return await client.SendAsync(httpRequest);
}
}
To obtain role definition IDs, just make a request to get all roles per subscription scope.
Useful links:
MSDN: How to manage customer's usage-based subscription programmatically?
MSDN: When will auto-stamping/implicit consent be available for CREST customers?
Managing Role-Based Access Control with the REST API