The user or administrator has not consented to use the application with ID '<APPID>' - azure-active-directory

We started having this problem shortly after we started using DYN365O Update 3. Our code worked for a while then one day in mid-January stopped working. We have a ticket into Microsoft but was hoping someone has found a workaround. The following error happens when our code tries to connect:
Response Code (1004) {"error":"AADSTS65001: The user or administrator
has not consented to use the application with ID ''. Send an
interactive authorization request for this user and resource.\r\nTrace
ID: d1775f71-ac60-4d12-ace5-39b52452a5c7\r\nCorrelation ID:
38e3b5c6-52c2-4ea9-9ad1-67230e246b40\r\nTimestamp: 2017-01-29
21:42:43Z"}
I was able to use the code here (https://github.com/Microsoft/Dynamics-AX-Integration) to recreate the problem. Here is the relevant section:
string aadTenant = ClientConfiguration.Default.ActiveDirectoryTenant;
string aadClientAppId = ClientConfiguration.Default.ActiveDirectoryClientAppId;
string aadResource = ClientConfiguration.Default.ActiveDirectoryResource;
AuthenticationContext authenticationContext = new AuthenticationContext(aadTenant);
// OAuth through username and password.
string username = ClientConfiguration.Default.UserName;
string password = ClientConfiguration.Default.Password;
// Get token object
var userCredential = new UserPasswordCredential(username, password);
AuthenticationResult authenticationResult = authenticationContext.AcquireTokenAsync(
aadResource,
aadClientAppId,
userCredential).Result;
When pointing to our Update 2 (August Update) DYN365O instance
everything works perfectly.
Changing the URI to point to Update3 we begin to see these errors.
I have searched the internet and I have done everything suggested including:
Setting oauth2AllowImplicitFlow = true in the manifest for the Azure
App.
Under permissions for the APP in AAD I have used the Grant
Permissions to "grant permissions for all accounts in the
directory".
Altering the call to AcquireTokenAsync to include
"prompt=admin_consent". I am presented with the prompt screen but
even after entering the AAD admin userid/password I get the same
error.
Tried other users for 3.
Verified that the user in DYN365O (under System Administration >>
Users) is identical in both our Update2 and Update3 instances and is
a System Administrator.

Related

Get a token for the current logged in user, using MSAL.NET

I'm trying to get a token for the current logged in user, using MSAL.NET
I'm getting a reference to PublicClientApplication, using the following API:
_clientApp = PublicClientApplicationBuilder.Create(ClientId)
.WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
.WithBroker()
.WithDefaultRedirectUri()
.Build();
Then, later in the code, I'm trying to call AcquireTokenSilent with the following code:
var firstAccount = Microsoft.Identity.Client.PublicClientApplication.OperatingSystemAccount;
authResult = await _clientApp.AcquireTokenSilent(scopes, firstAccount)
The call to AcquireTokenSilent thow an exception, with the following details:
Microsoft.Identity.Client.MsalServiceException
HResult=0x80131500
Message=WAM Error Microsoft.Identity.Client.Platforms.Features.WamBroker.AadPlugin
Error Code: WAM_aad_provider_error_3399614466
Error Message:
WAM Error Message: V2Error: invalid_request AADSTS90002: Tenant '75950cd6-4468-4918-b750-966c6b4fa3d1' not found. Check to make sure you have the correct tenant ID and are signing into the correct cloud. Check with your subscription administrator, this may happen if there are no active subscriptions for the tenant.
Interestingly, the SID '75950cd6-4468-4918-b750-966c6b4fa3d1' is NOT my tenant ID, and actually, I do not have this string anywhere in my code.
In the application registration, I set up the redirect URI to:
ms-appx-web://microsoft.aad.brokerplugin/<my application SID>. The application is registered for domain only, and the my device is domain joined.
What am I doing wrong?
Update
Answer a comment from #Sridevi.
I'm following this demo almost to the letter: https://learn.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-windows-desktop
With the following changes:
As a redirect URI, I wrote: ms-appx-web://microsoft.aad.brokerplugin/<client SID>
When building the MSAL application, I added .WithBroker() as mentioned above
For firstAccount, I do not take the first account from the list of acounts as in the tutorial (it is empty the first time), but I'm using the enum OperatingSystemAccount, mentioned above as well.
I would appreciate a sample or tutorial for getting this token otherwise.

deamon authentication on powerapps admin REST API

In scope of a compliance monitoring app for our powerapps usage, we created a C# console app which crawls powerapps.
environments
applications
permissions
(similar REST call than powershell commands Get-AdminPowerAppEnvironment Get-AdminPowerApp provided by Microsoft.PowerApps.Administration cmdlets)
proof of concept was done by stealing the Bearer header from fiddler when connected with my admin AAD account. POC is now validated, time to make it clean. And as often with AAD auth flow (for me), it's more complex than expected (sum up of hours of try & fails).
I find really little internet reference on how to authenticated & crawl (this part is ok) this API.
I tried different auth workflow and lib
MSAL
ADAL
fiddler on top of powershell command (but in powershell I'm not using a service principal)
and either I can't spot the correct scope or my service principal has no permission on the resource.
I have an App registration called AAA powerapps with ... quite a lot of permission (try & fails)
Created a client secret
just in case, put into Power Apps administrator
string authority = $"https://login.microsoftonline.com/[tenant-guid]/";
var app = ConfidentialClientApplicationBuilder
.CreateWithApplicationOptions(new ConfidentialClientApplicationOptions { ClientId = "[client-id]", ClientSecret = "[shhuuuu]" })
.WithAuthority(authority).Build();
// tried with https://management.azure.com/.default / https://api.bap.microsoft.com/.default / https://service.powerapps.com./default
var token = app.AcquireTokenForClient(new[] { "https://management.azure.com/.default" }).ExecuteAsync().Result;
//var client = new RestClient("https://api.bap.microsoft.com/providers/Microsoft.BusinessAppPlatform/scopes/admin/environments?api-version=2016-11-01");
var client = new RestClient("https://management.azure.com/providers/Microsoft.BusinessAppPlatform/scopes/admin/environments?api-version=2016-11-01");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer " + token.AccessToken);
IRestResponse response = client2.Execute(request);
I get a token, but I don't think it's on the correct scope/resource unfortunately.
Depending on the scope, I either get
Forbidden
{"error":
{"code":"Forbidden","message":"The service principal with id '[service principal guid (not client id)'
for application <null> does not have permission to access the path 'https://api.bap.microsoft.com:11779/providers/Microsoft.BusinessAppPlatform/scopes/admin/environments?api-version=2016-11-01' in tenant [tenant-guid]."}}
or
Unauthorized
{"error":{"code":"AuthenticationFailed","message":"Authentication failed."}}
Didn't succeed with client id & client secret but managed to call api.bap.microsoft.com/../Microsoft.BusinessAppPlatform with AAD user.
eg https://api.bap.microsoft.com/providers/Microsoft.BusinessAppPlatform/scopes/admin/environments?api-version=2016-11-01
re-used same method as Microsoft.PowerApps.Administration cmdlets
AAD account with AAD Power platform administrator role
If Multi Factor Access enabled for admin, create exception rule
use ADAL nuget Microsoft.IdentityModel.Clients.ActiveDirectory
dotnet
AuthenticationContext authContext = new AuthenticationContext("https://login.windows.net/common");
var credentials = new UserPasswordCredential("admin_powerapps#domain.net", "password");
// "1950a258-227b-4e31-a9cf-717495945fc2" = client ID for Azure PowerShell.
// available for any online version
var token = authContext.AcquireTokenAsync("https://management.azure.com/", "1950a258-227b-4e31-a9cf-717495945fc2", credentials).Result;
// any REST call
Header "Authorization" : "Bearer " + token.AccessToken
Endpoint : https://api.bap.microsoft.com/providers/Microsoft.BusinessAppPlatform/scopes/admin/environments?api-version=2016-11-01
results
The benefit from this method is that it can crawl "all" environments seamlessly (not sure the approach with creating a user on each was working).
Another approach I spotted was using Powerapps connector for admin but it involved extra configuration on each environments and required a license.
Not fully sure this method would be supported long term (eg xx.windows.net). Open minded for any other suggestion.
I was facing the same issue. What solved it with me is to register the app with tenant admin rights on the power platform admin using this command New-PowerAppManagementApp. Please, find MSFT article here.
After your client application is registered in Azure AD, it also needs to be registered with Microsoft Power Platform. Today, there's no way to do this via the Power Platform admin center; it must be done programmatically via Power Platform API or PowerShell for Power Platform administrators. A service principal cannot register itself—by design, the application must be registered by an administrator username and password context. This ensures that the application is created knowingly by someone who is an administrator for the tenant.
$appId = "CLIENT_ID_FROM_AZURE_APP"
# Login interactively with a tenant administrator for Power Platform
Add-PowerAppsAccount -Endpoint prod -TenantID $tenantId
# Register a new application, this gives the SPN / client application same permissions as a tenant admin
New-PowerAppManagementApp -ApplicationId $appId

Delete User from Azure AD B2C using Graph API right after it was created - ObjectNotFoundException

I'm using Custom Policy to sign up users in Azure AD B2C.
In the last step, before the JWT is issue, the technical profile does the following:
<!-- Store the user in the AD -->
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" ContinueOnError="false" />
<!-- Sends the user information, including ObjectId to website to store locally-->
<ValidationTechnicalProfile ReferenceId="REST-SendUserInformation" ContinueOnError="false"/>
So, this works fine. However, in my code, if something goes wrong in the step 2 (send the user's information to store locally), I call the Graph API to delete the user that was just created.
However, I noticed that the Graph API works when I "debug" (which means, taking some time to click next.. next...), but when it's running in the server, the user is not deleted from the AD.
It doesn't throw an exception.
My code to delete the user is the following:
public AzureGraphService(IConfiguration configuration)
{
var azureOptions = new AzureAdOptions();
configuration.Bind("AzureAdB2C", azureOptions);
// Client credential provider is used by services and desktop applications to acquire Microsoft Graph access token without a user.
_confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(azureOptions.ClientId)
.WithTenantId(azureOptions.Domain)
.WithClientSecret(azureOptions.ClientSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(_confidentialClientApplication);
// Set up the Microsoft Graph service client with client credentials
_graphClient = new GraphServiceClient(authProvider);
}
public async Task DeleteUserFromAD(string azuresubid)
{
try
{
// Delete user by object ID
await _graphClient.Users[azuresubid]
.Request()
.DeleteAsync();
}
catch (Exception ex)
{
// TODO - Log exception?
throw ex;
}
}
After looking the Audit Logs in Azure AD B2C, I found this
"ObjectNotFoundException".
However, I'm certain that the object is correct and the objectID that I use to delete is also correct because it works if I "debug" (go slowly).
My question is:
Is there a delay between the Object (User) is created in the AD B2C and the time that I can actually see and delete the object from there?
Thank you
There is a delay, the policy execution targets the same DCs, your graph api call from your REST API is likely hitting a different DC and cannot find the account at that time. Use retry logic, try 3 times with a 5 second delay. Usually replication completes in 7sec.

Error AADSTS65001 but no consent prompt for just one user

I am writing a C# .NET app. It is connected to our service on Azure which is configured for using AAD. In turn, our service tries to make calls to Exchange via EWS.
This all worked fine for me until we recently deployed our service bits to a new Azure web app with new app registrations. They are all configured correctly and other developers on our team can authenticate with the service and use it as expected.
When I try to connect to the service, I get the following error:
AADSTS65001: The user or administrator has not consented to use the application with ID '61a8b794-7f67-4a01-9094-fcdd45693eaa'. Send an interactive authorization request for this user and resource.
Trace ID: ece7c5d0-2ecb-4096-a87a-2cd33271d65d
Correlation ID: 093b5935-3b06-4d76-91a9-6619bc179544
Timestamp: 2017-02-09 23:19:28Z
The consent prompt never appeared for me when trying to connect after deploying the new service.
I'm not sure what it is about my user account that causes this error to occur (it happens on multiple machines with my account) while others can connect successfully.
Here’s some of the code used to acquire the token in the service:
var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext;
var upn = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn);
var email = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email);
var userName = upn != null ? upn.Value : email?.Value;
accessToken = bootstrapContext.Token;
ClientCredential clientCred = new ClientCredential("61a8b794-7f67-4a01-9094-fcdd45693eaa", appKey);
UserAssertion assertion = new UserAssertion(accessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);
AuthenticationContext authContext = new AuthenticationContext("https://login.microsoftonline.com/microsoft.onmicrosoft.com");
AuthResult = authContext.AcquireToken("https://outlook.office365.com", clientCred, assertion);
Any ideas why I wouldn't get the consent prompt, but other users on my team have?
Based on the description, you are developing multi-tier application using Azure AD.
Since you mentioned this issue was occurred after using the new app, did you config your new app as the knownClientApplications of your service app(61a8b794-7f67-4a01-9094-fcdd45693eaa)?
If yes, you should can give the consent for the service app when you sign-in your web app( refer here about multi-tier applications).
The problem why only you get this issue may others have given the consent to this app before.
Please let me know if it helps.

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.

Resources