Azure Active Diretcory Enterprise App - App ownership - azure-active-directory

In the Azure AD App registration, we have ‘Owners’ tab. It show ‘In addition to users with permission to manage any applications, the users listed here can view and edit this application registration.’. Our documentation show, ‘Change application properties, such as the name and permissions the app requests’
Will the app owner be able change ‘API permissions’ / ‘Grant consent’ / ‘add a permission’ etc. ? If yes, how do they do that (Programmatically, APIs, PowerShell module ?)
App ownership image - https://i.imgur.com/JOr4J7u.jpg

The app owner will be able to change/add the API permission, but he will not be able to grant consent to the permissions which ADMIN CONSENT REQUIRED, to require end users to consent to an application each time they authenticate, append &prompt=consent to the authentication request URL, more details see this doc.
To change/add the API permissions to the AD App, you could use powershell, refer to this post.
$req = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$acc1 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "e1fe6dd8-ba31-4d61-89e7-88639da4683d","Scope"
$acc2 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "798ee544-9d2d-430c-a058-570e29e34338","Role"
$req.ResourceAccess = $acc1,$acc2
$req.ResourceAppId = "00000003-0000-0000-c000-000000000000"
Set-AzureADApplication -ObjectId 1048db5f-f5ff-419b-8103-1ce26f15db31 -RequiredResourceAccess $req

Related

Add an Azure AD user to a Azure DevOps project group using Azure Logic Apps

I am trying to add an Azure AD user to an Azure DevOps project group using the Azure Logic Apps DevOps Connector, action Send an HTTP request to Azure DevOps but I receive status Unauthorized while with the same user I am able to do it manually in the portal. Because there is almost no documentation regarding this tool and APIs it's using, I guess it is something with the URI but not sure. Any ideas?
Thank you
We could not add an Azure AD user to a Azure DevOps project group via Azure Logic Apps. This is an known issue in the action Send an HTTP request to Azure DevOps
We are using this REST API to add an AAD user as member of a group, it need the permission scope vso.graph_manage
And according to this doc Action Send an HTTP request to Azure DevOps has a limited set of scopes which control what resources can be accessed by the action and what operations the action is allowed to perform on those resources.
The Scopes contain:
vso.agentpools_manage
vso.build_execute
vso.chat_manage
vso.code_manage
vso.code_status
vso.connected_server
vso.dashboards_manage
vso.entitlements
vso.extension.data_write
vso.extension_manage
vso.identity
vso.loadtest_write
vso.packaging_manage
vso.project_manage
vso.release_manage
vso.test_write
vso.work_write
Since it does not contain the scope vso.graph_manage, and we could see the error message : TF400813: The user xxx is not authorized to access this resource in the output content
Update1
Power shell script:
$connectionToken="{PAT}"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$URL = "https://vssps.dev.azure.com/{Org name}/_apis/graph/users?groupDescriptors={groupDescriptors}&api-version=6.0-preview.1"
$body =#"
{
"principalName": "{User email}"
}
"#
$Result = Invoke-RestMethod -Uri $URL -ContentType "application/json" -Body $body -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST

Grant service principal access to application in other tenant

I have an Azure AD service principal in one tenant (OneTenant) that I would like to give access to an application in another tenant (OtherTenant).
The service principal in tenant OneTenant is a managed service identity for an Azure Logic App. So what I actually want is to call an API from my Logic App. This API is protected by an Azure AD application in OtherTenant.
The application in OtherTenant defines a number of roles and the service principal in OneTenant should have one of these roles so it can call the API.
I tried the following:
set the app in OtherTenant to multi-tenant
ran the following PS command to attempt to add the SP to a role in the app:
New-AzureADServiceAppRoleAssignment `
-ObjectId <object-id-of-sp-in-one-tenant> `
-Id <role-id> `
-PrincipalId <object-id-of-sp-in-one-tenant> `
-ResourceId <app-id-in-other-tenant>
(both logged in in OneTenant and OtherTenant)
This gives an error stating that either app-id-in-other-tenant or object-id-of-sp-in-one-tenant can not be found, depending on where I am signed in.
I also tried creating a Service Principal in OneTenant based on the app-id from OtherTenant In that case I get an error message: Authenticating principal does not have permission to instantiate multi-tenantapplications and there is not matching Applicationin the request tenant.
Ok, I finally got around to testing if the solution presented by Rohit Saigal works. It does point in the right direction but is not complete.
First step is to create a service principal in OneTenant that represents the application in OtherTenant. So while signed in to OneTenant, run the following script:
$spInOneTenant = New-AzureADServicePrincipal -AppId <app-id-in-other-tenant>
Next step is to run the New-AzureADServiceAppRoleAssignment cmdlet with the following parameters:
New-AzureADServiceAppRoleAssignment `
-Id <role-id> `
-ObjectId <object-id-of-sp-in-one-tenant> `
-PrincipalId <object-id-of-sp-in-one-tenant> `
-ResourceId $spInOneTenant.ObjectId
The trick is to use the object id of the service principal you created in the previous step as the ResourceId.
Taking the command as is from your question:
New-AzureADServiceAppRoleAssignment `
-ObjectId <object-id-of-sp-in-one-tenant> `
-Id <role-id> `
-PrincipalId <object-id-of-sp-in-one-tenant> `
-ResourceId <app-id-in-other-tenant>
Try changing the last parameter value i.e. ResourceId
Currently you're passing <app-id-in-other-tenant>
Replace that with <object-id-of-API-in-other-tenant>
The question/answers presented here were helpful, but yet it took me some time to work through the details and actually make it work, so allow me to elaborate some more on the above, as it might help others too.
Scenario
Two tenants:
Home Tenant.
Other Tenant.
One Azure App Service API app, with access managed by the Home Tenant.
One Logic app placed in a subscription in Other Tenant that need to securely access the API app in the Home Tenant.
Approach
Application registration
For the API app to delegate identity and access management to Azure AD an application is registered in the home tenant’s Azure Active Directory. The application is registered as a multi-tenant app.
You also need to create an app role (see documentation: How to: Add app roles in your application and receive them in the token), lets call it read.weather.
Configuration of Other Tenant and Logic App
To provide the Logic App access to the API app do this:
Enable a system assigned identity for the logic app - i.e. use Managed Identity. Note down the system assigned managed identity Object ID ({18a…}), you will need it in a minute.
Create a service principal for the application in the Other Tenant using this command, where appId is the appId of the application registered in Home Tenant (e.g. lets say it’s {1a3} here):
New-AzureADServicePrincipal -AppId {appId}
This command will output a json document which includes among other things an objectId for the service principal just created.
[... more json ...]
"objectId": "b08{…}",
[... more json...]
You should also see the appRoles, including the app role read.weather you just created, om the json output from the New-AzureADServicePrincipal command:
[... more json...]
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"description": "Read the weather.",
"displayName": "Read Weather",
"id": "46f{…}",
"isEnabled": true,
"value": "read.weather"
}
],
[... more json...]
To tie it all together make an app role assignment using the command:
New-AzureADServiceAppRoleAssignment -Id {app role ide} -ObjectId {system assigned identity object id} -PrincipalId {system assigned identity object id} -ResourceId {object id of service principal}
E.g. something like this:
New-AzureADServiceAppRoleAssignment -Id 46f… -ObjectId 18a… -PrincipalId 18a… -ResourceId b08…
Now we are ready to set up the HTTP request in the Logic App using the URI to the API app using Managed Identity for authentication.
Notice that the audience is needed and has the form: api://{appId}.
But wait…!
Does this mean that anyone could do this, if only they know the appId of your application registration, and wouldn’t this compromise the security of the API app?
Yes, it does, and yes indeed it could compromise the security of the API app.
If you look at the access token being created and used as bearer from the Logic App it is a valid access token, which contains all the necessary claims, including the app role(s). The access token is however issued by Other Tenant and not Home Tenant.
Therefore, if you have a multi tenanted application and you want to guard it against this scenario, then you could check the issuer (tid more likely) of the incoming access token calling the API and only accept it if the issuer is the Home Tenant, or you could make the application a single tenant app.
Or, you could require that the issuer matches a list of tenants that the API trusts.

Reset Password REST call returns 403 using service principal

I am trying to execute the following API using a bearer token issued to a service principal NOT an AD User. Yes I know this is the AD Graph versus Microsoft Graph endpoint, but I have my reasons :)
https://graph.windows.net/GUID-REDACTED/users/GUID-REDACTED?api-version=1.6
I get a 403 error despite the fact that I have granted all Application Permissions for "Windows Azure Active Directory" (and Microsoft Graph) to that principal. I also applied admin consent (via Grant Permissions) in the portal. Note that a request to read all users (i.e., remove last GUID off URL above) DOES succeed.
The bearer token contains the following seven claims (curiously in AD, EIGHT permissions are granted):
"Device.ReadWrite.All",
"Directory.Read.All",
"Member.Read.Hidden",
"Directory.ReadWrite.All",
"Domain.ReadWrite.All",
"Application.ReadWrite.OwnedBy",
"Application.ReadWrite.All"
The token was acquired via:
var context = new AuthenticationContext($"https://login.microsoftonline.com/{tenantId}");
var m = new HttpRequestMessage()
var accessToken = context.AcquireTokenAsync("https://graph.windows.net", credentials).Result.AccessToken;
m.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
I have tried the analog of this via the Microsoft Graph endpoint, but with the ADAL AuthenticationContext and get the same 403 result. If I use the Microsoft Graph Explorer though, it works. In that case I am logged in as a user though. Upon comparing the scopes in the tokens (scp) there are differences (because the user has certain 'user' scopes), but nothing that immediately looks suspicious.
Directory.AccessAsUser.All is on the user scope but not the application identity scope, but that makes sense to me, unless that scope is (incorrectly?) required for the operation I am trying.
Any ideas what I am missing here? Is there a reference that maps the scopes/roles required to the actual API operations? Does the SP need a directory role, like a user would need?
As #MarcLaFleur said, it's not a good idea to give an application permissions to reset users' password. But if you don't have other choices you can still use client credentials flow to achieve this. But this is not recommeded unless you don't have other choices.
Solution:
You can assign Company Administrators Role to your Service principal. You can refer to this document to do that.
Use AAD Powershell to Connect AAD:
Connect-AzureAD
Get the Role of Company Administrator:
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Company Administrator'}
Assign the role to your SP:
Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $yoursp.ObjectId

How to programatically create applications in Azure AD

I'm currently creating my applications on Azure Active directory manually whenever there is a request for a new environment. I was exploring ways to create these applications from the code via REST API. I had success in creating users and groups on existing applications by using 'client_credentials' as shown.
ClientCredential clientCred = new ClientCredential(clientID, clientSecret);
AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(resAzureGraphAPI, clientCred);
In similar fashion I tried to use the 'access_token' generated from above to create a new application
adClient.Applications.AddApplicationAsync(newApplication).Wait()
But this throws an error- "Insufficient privileges to complete the operation."
I looked at other threads and the Azure AD msdn page and turns out the client_credentials flow does not support creating/updating applications.
Adding Applications programmatically in Azure AD using Client Credentials Flow
The above thread also mentioned that way to workaround it was by using the 'grant_type=password' flow. I tried it as suggested but I keep getting the following error which doesn't make sense to me.
"error": "invalid_grant",
"error_description": "AADSTS50034: To sign into this application the account must be added to the 1283y812-2u3u-u293u91-u293u1 directory.\r\nTrace ID: 66da9cf9-603f-4f4e-817a-cd4774619631\r\nCorrelation ID: 7990c26f-b8ef-4054-9c0b-a346aa7b5035\r\nTimestamp: 2016-02-21 23:36:52Z",
"error_codes": [
50034
],
Here is the payload and the endpoint that I'm hitting. The user that is passed is the owner of the AD where I want to create the application
endpoint:https://login.windows.net/mytenantID/oauth2/token
post data
resource 00000002-0000-0000-c000-000000000000
client_id id
client_secret secret
grant_type password
username principal#mydomain.com
password password
scope openid
Any thoughts or suggestions of where I might be going wrong would be appreciated.
You can use PowerShell to create your apps:
$servicePrincipalName =”Your Client App Name”
$sp = New-MsolServicePrincipal -ServicePrincipalNames $servicePrincipalName -DisplayName $servicePrincipalName -AppPrincipalId “Your Client ID"
New-MsolServicePrincipalCredential -ObjectId $sp.ObjectId -Type Password -Value “Your client secret”
Add-MsolRoleMember -RoleObjectId “62e90394-69f5-4237-9190-012177145e10" -RoleMemberType ServicePrincipal -RoleMemberObjectId $sp.ObjectId
The role denoted by 62e90394-69f5-4237-9190-012177145e10 is the Admin role, and this can be adjusted as required to the ObjectId of any other role. Run Get-MsolRole to get a list of roles and ObjectIds.
You could then run this code from your App or run it manually. You will also need to run your connection code before the above, something along the lines of:
$loginAsUserName = "Your Tenancy Admin Account"
$loginAsPassword = "Your Tenancy Admin Account Password"
$secpasswd = ConvertTo-SecureString $loginAsPassword -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ($loginAsUserName, $secpasswd)
Connect-MsolService -Credential $creds
I was able to create the application in my tenant. The AD tenant which I was using to create the application under was verified for a different domain. Basically I ended up plugging in an user from that domain and using the resource_type=password flow was able to generate an access token. Next, firing the following lines of code did the trick
ActiveDirectoryClient adClient = new ActiveDirectoryClient(
serviceRoot,
AccessToken);
adClient.Applications.AddApplicationAsync(newApplication).Wait();
Check the following things which seem to be a little off in your POST to the OAuth Token endpoint:
When wanting access to the Graph API of your Azure AD, you will need to pass https://graph.windows.net as the resource body parameter; this is (imho) not well documented, but that's what you need to do
As client_id and client_secret you need to pass the Client ID and the Key of a predefined Application inside your Azure AD which in turn you have granted permissions on a per user level to; these need to be sufficient to add applications
See here: https://msdn.microsoft.com/Library/Azure/Ad/Graph/howto/azure-ad-graph-api-permission-scopes?f=255&MSPPError=-2147217396
The scope parameter is not used, I think; you will get the claims you defined inside the Azure AD management portal back (the assigned permissions for your application)
This should render you an access token you can then subsequently use on the https://graph.windows.net/tenantId/ end points.

Passing claims from Domain Controller (in Kerberos tickets) to Active Directory Federation Server

I'm hoping someone can help me out as this has been puzzling me for quite some time now. I have a domain controller set up with kerberos armoring enabled to include claims in the issued kerberos tickets. I then have Dynamic Access Control configured to define some claim types to include in the kerberos tickets. The kerberos tickets appear to contain the defined claim types when I tested using a simple PowerShell script using System.Security.Principal.WindowsIdentity to query all claims included in the current user's Identity, which I presume is obtained from the existing issued kerberos ticket.
I then configured Active Directory Federation Services which integrated with Active Directory DC as a Claims Provider Trust, and I setup a SAML test web application to server as a Service Provider / Relying Party. The setup works if I use "Send LDAP Attribute as Claims" in the Relying Party trust to query AD and obtain the claims.
However, what I wanted to do is get the claims included in the kerberos tickets and include them in the SAML token issued by AD FS as the user performs SSO through Windows Integrated Login. I tried all possible "Pass Through" rules in both Claims Provider Trust and Relying Party Trust to extract these claims from he kerberos tickets and include them in the generated SAML tokens in AD FS, but none seem to work. I even created a custom rule to just pass through all claims but none seem to work. It appears that the kerberos tickets don't even contain the associated claims I defined in Dynamic Access Control since I was able to pass through default claims in kerberos like the UPN, Groups SID, Name, etc. But if it's the custom claims I defined in Dynamic Access Control to be included in the kerberos ticket, they seem to be nonexistent.
Can anyone help me diagnose this further?
FYI, the test web app I used is simpleSAMLphp and I just use it to displays all claims/attributes it receives from the SAML token issued by AD FS.
Here is the PS script I used to test and see that the kerberos ticket of the current user contains the claim types I defined in Dynamic Access Control:
$CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$Username = $CurrentUser.Name
Write-Output "User: $Username`n"
Write-Output "---- CLAIMS ----`n"
$Claims = $CurrentUser.Claims
foreach ($claim in $Claims) {
# Get Claim Type
if ($claim.Type -match "http://") {
$claimType = ($claim.Type).Split('/')[($claim.Type).Split('/').Count -1]
}
elseif ($claim.Type -match "ad://") {
$claimTypeName = ($claim.Type).Split(':')[($claim.Type).Split(':').Count -2]
$claimType = $claimTypeName.Split('/')[$claimTypeName.Split('/').Count -1]
}
# Transform
if ($claimType -eq "groupsid") {
$claimType = "group"
}
# Get Claim Value
$claimValue = $claim.Value
if ($claimValue -match "S-" -and $claimType -eq "group") {
try {
$SIDvalue = New-Object System.Security.Principal.SecurityIdentifier($claimValue)
$accountName = $SIDvalue.Translate([System.Security.Principal.NTAccount])
$claimValue = $accountName
}
catch {
Write-Verbose "WARNING: Unable to get group name attribute of SID $SIDvalue"
$claimType = "groupsid"
}
}
Write-Output "$claimType`: $claimValue"
}
If I can provide any other information to help diagnose this issue, please let me know.
Thank you in advance.

Resources