0

I've created a multi tenant Web API that works just fine. Now I want to build a native client for testing. The Web API app is defined in one tenant. The test app is defined in another tenant that has given admin consent to the Web API.

I want to use the native app to authenticate with username and password in my (non-interactive) integration tests. I cannot use certificate/app-only authentication because I need a real user context.

Getting a token

var userCredential = new UserCredential("admin@clienttenant.onmicrosoft.com", "password");
var context = new AuthenticationContext("https://login.windows.net/common");

return context.AcquireToken("https://webapitenant.onmicrosoft.com/webApiResourceUri", testClientId, userCredential).AccessToken;

The problem with this code is that it doesn't work until I've given admin consent to the native app, even if the user is in the same tenant as the app registration.

Exception thrown:

'Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException' in Microsoft.IdentityModel.Clients.ActiveDirectory.dll

Additional information: 
AADSTS65001: The user or administrator has not consented to use the application with ID 'nativeclientid'. Send an interactive authorization request for this user and resource. 

Since tests aren't interactive I have to create a console application that uses the above code but with PromptBehaviour.Always. This will prompt me for username and password and show a consent form. After I give consent the tests that is using the same native app registration starts working.

Is there a way to accept the consent form without a interactive GUI?

Gabriel Smoljar
  • 1,226
  • 2
  • 14
  • 32

1 Answers1

2

At the moment there is no other way to write user consent without some sort of user experience. (Which makes sense right?)

If you use the Azure Management Portal, as an administrator of your tenant, all the apps you create should automatically be consented for the resources you selected. This is because the Azure Management Portal specifically will write those consent links as you save your client application.

If you use other portals or APIs to create your application, then you will need to consent to the application at least one time. You do not need to necessarily put prompt behavior on your application to get the consent screen. You can just generate the URL for signing into your application, which will also take you through the consent experience:

https://login.microsoftonline.com/<TenantID>/oauth2/authorize?client_id=<AppID>&response_type=code&redirect_uri=<RedirectURI>&resource=<ResourceURI>&prompt=admin_consent

Note that we added a "prompt=admin_consent" at the end which will consent to the application on-behalf of the whole tenant. With this kind of consent, you will only need to do it once per application to get it working.

I hope this helps!

Shawn Tabrizi
  • 12,206
  • 1
  • 38
  • 69
  • Are you sure that apps created in the portal are automatically consented? I created the native client in the portal and was still prompted with a consent form. The test user is in the same directory as the native app. The web api is in a different tenant however. – Gabriel Smoljar Dec 15 '16 at 07:05
  • Specifically as an administrator, yes consent is recorded. In the past, Native Client applications did not record consent, but it was my understanding that this has since been fixed, so it should also work with native clients. Finally, you may find that in your code you are 'prompting to consent' which will force the consent dialogue no matter if you have already consented or not. Let me know if you still get this behavior and maybe we can debug your experience off the site. – Shawn Tabrizi Dec 15 '16 at 07:08
  • If I remember correctly it works as you say as long as the Web API and Native Client is registered in the same tenant. In my case I wanted to run tests against a remote server since it is easier to debug locally than waiting for and trouble shooting VSTS build output. The reason for having apps in separate tenants was that developers should only have to configure the their own native app in their own tenants and share the web api app in a common tenant. Forcing the consent form in the dummy console app was intentional as it would make sense based on the exception message in the question. – Gabriel Smoljar Dec 15 '16 at 10:32
  • I just tried to set this up for one of my colleagues who is admin. In this case both Web API and Native Client was in the same tenant. We still had to use the URL in your answer to get consent. Did I understand you correctly if I say that this is not the expected behavior? – Gabriel Smoljar Dec 16 '16 at 15:45
  • Yes this NOT the expected behavior. I just tested it myself and I got the results I expected. I went into my tenant, logged in as a tenant administrator, using the [Azure Management Portal](https://manage.windowsazure.com). I created a Native Client Application. I then created a single tenant Web API, with an App ID URI. I then went back to the native client app, and added the default permission that was created for my Web API in the Permissions to Other Applications Section. I then saved the native app. Then I used ADAL and the Auth Code Grant Flow to get an access token, all without consent. – Shawn Tabrizi Dec 16 '16 at 21:50