Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not getting OAuth/Bearer challenge for On-Premise #233

Open
chrispiasecki opened this issue Jan 21, 2022 · 7 comments
Open

Not getting OAuth/Bearer challenge for On-Premise #233

chrispiasecki opened this issue Jan 21, 2022 · 7 comments
Labels
Investigating We are looking into this issue at this time.

Comments

@chrispiasecki
Copy link

chrispiasecki commented Jan 21, 2022

Using ASP.NET 6 Web API, we're not able to authenticate using ServiceClient (v0.5.17) to an on-premise instance (v8.2) configured with IFD using ADFS 2016. The SDK is unsuccessful in retrieving the authority in a bearer challenge. It is sending a request to the organization's discovery endpoint /XRMServices/2011/Discovery.svc, which is resulting in a 200 instead of a 401, therefore does not include a WWW-Authenticate header. It would appear the discovery endpoint is anonymously accessible, which I believe is set by default in a standard on-premise installation? Below is the error we're seeing when instantiating the ServiceClient:

ERROR REQUESTING Token FROM THE Authentication context\r\nERROR REQUESTING Token FROM THE Authentication contextNeed a non-empty authority (Parameter 'Authority')Unable to login to Dataverse, Error was : Need a non-empty authority (Parameter 'Authority')\r\nUnable to Login to Dataverse\r\nUnable to Login to DataverseOrganizationWebProxyClientAsync is null\r\nOrganizationWebProxyClientAsync is nullOrganizationWebProxyClientAsync is null\r\nOrganizationWebProxyClientAsync is null

Using Fiddler, we can send an unauthenticated request to /api/data/v8.2/WhoAmI and successfully get back the Bearer challenge header with the correct resource and authorization urls as shown below.

WWW-Authenticate: Bearer authorization_uri=https://{adfs2016Url}/adfs/oauth2/authorize, resource_id=https://{orgIFDurl}/ WWW-Authenticate: NTLM WWW-Authenticate: Negotiate

We are then able to retrieve an access token and successfully make an authorized WhoAmI request to get data back, which indicates CRM and ADFS are configured correctly for OAuth2.

We've also tried on ASP.NET Core 3.1 with the same result. We first tried using the ServiceClient v0.5.10 with no success then tried v0.5.17 when it was published, but again same result.

@RedsGT

@RedsGT
Copy link

RedsGT commented Jan 27, 2022

I wasn't able to get this to work either. It looks like the authority value never makes it to the disco call for some reason.

That being said, because the serviceclient is now using MSAL which only works with ADFS 2019+. (See MSAL connects directly to AD FS ) , You'll need to upgrade or setup a separate ADFS instance for this to work.

The GOOD news is, I WAS able use the Token constructor with MSAL and the Resource Owner Password Credentials grant type to get a successful connection with .NET Core 6.

More BAD news though that IF you are stuck with ADFS 2016, it will not work with MSAL as noted above and it also will not work with the exact combination of .NET Core/ADAL/ADFS 2016/ROPC, if you thought you might want to use it with the Token constructor. See (ADAL) UserPasswordCredential doesn't support .NET Core.

With the current lack of Client Credential grant support server side (aka Application User), a working up-to-date S2S supported config for onpremise .NET Core 6 using ServiceClient in my mind would be:
ADFS 2019+
MSAL (either inbuilt when issue is fixed, or with the token constructor)
OAuth2 ROPC Grant type

@chrispiasecki
Copy link
Author

Thanks for the follow up @RedsGT. Is ADFS 2019 even supported yet with any on-premise version of D365, particularly v8.2 ? In the event we are stuck with ADFS 2016 for a while, is the only option to supply our own handler via the token constructor? Is there an available sample for this?

@RedsGT
Copy link

RedsGT commented Jan 30, 2022

@chrispiasecki ADFS 2019 is officially supported for v9.1currently. ADFS 2016 has always been unsupported for v8.2 per https://support.microsoft.com/en-us/topic/compatibility-with-microsoft-dynamics-crm-2016-40e02971-79e6-d0a9-e7db-35c56015891e as well but as it's been the only option for many of the OAuth grant types and it's just been used anyway by many. If you think of ADFS as a stand-alone IDP, it is still supported in that regard, just like Dynamics CE is. For ADFS 2016, the ROPC grant mixed with .NET Core won't work with either MSAL or ADAL for different reasons, even when the issue outlined here is resolved. Alternatives would be to fork MSAL/ADAL and tweak them to do what you need, find a lib that does work to grab a token and feed that into the constructor, or write your own. I can't really give any guidance beyond that.

@MattB-msft MattB-msft added the Investigating We are looking into this issue at this time. label Feb 1, 2022
@MattB-msft
Copy link
Member

Following up on this...
The next drop we are going to ship of the Dataverse ServiceClient does correct the authority acquisition and correct the construction of the request for MSAL against ADFS 2019 onPrem.

We are discussing options for ADFS 2016 with the AAD Team activity, however as you may (or may not) know, ADFS 2016 and Windows Server 2016 are both now in extended support vs's mainline support. That status of the server and ADFS system do not bode well for MSAL to provide backward support.

@MattB-msft
Copy link
Member

@chrispiasecki please check this with he 0.6.1 client if you can and let us know if this sorted it out for you.

@chrispiasecki
Copy link
Author

@chrispiasecki please check this with he 0.6.1 client if you can and let us know if this sorted it out for you.

Unfortunately I don't have an available ADFS 2019 environment readily available to test on. Our client will be moving to ADFS 2019 in near future and I will be able to validate then.

@janis-veinbergs
Copy link

janis-veinbergs commented Aug 28, 2023

MSAL supports only ADFS 2019, thus it is not expected for this tool to support ADFS 2016. https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-net-adfs-support :

AD FS 16, as it doesn't support PKCE and still uses resources, not scope

The GOOD news is, I WAS able use the Token constructor with MSAL and the Resource Owner Password Credentials grant type to get a successful connection with .NET Core 6.

@RedsGT I tested ROPC for ADFS2016 and it supported only "confidential client" where I must pass client_secret. But MSAL doesn't support that scenario: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc

As part of not recommending this flow for use, the official SDKs do not support this flow for confidential clients, those that use a secret or assertion. You may find that the SDK you wish to use does not allow you to add a secret while using ROPC.

If I omit client_secret for ADFS 2019, I get MSIS9622: Client authentication failed. Please verify the credential provided for client authentication is valid. - so using library to connect using ROPC flow against ADFS would also seem impossible.

However it may work when using this constructor:

public ServiceClient (Uri instanceUrl, Func<string,System.Threading.Tasks.Task<string>> tokenProviderFunction, bool useUniqueInstance = true, Microsoft.Extensions.Logging.ILogger logger = default);

and providing tokenProviderFunction and using plain http request to acquire access_token using ROPC flow that satisfies ADFS2016/2019 - may work :) I may try out that process, but now I'm trying to connect to onprem via ANY flow using only connection string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Investigating We are looking into this issue at this time.
Projects
None yet
Development

No branches or pull requests

4 participants