Hi!
I'm having an issue accessing a BC14 (CU22) OnPrem OData Webservice via OAuth.
I have AAD Authentication set up and can log in with AAD Users.
I have registered a second application as the consumer and created a secret to retrieve Tokens, this works fine as well:
curl --location --request POST 'https://login.microsoftonline.com/{{tenantId}}/oauth2/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'client_id={{ApiConsumerApplicationId}}' \ --data-urlencode 'client_secret={{ApiConsumerClientSecret}}' \ --data-urlencode 'resource={{BusinessCentralApplicationId}}'
Response:
{ "token_type": "Bearer", "expires_in": "86399", "ext_expires_in": "86399", "expires_on": "1622970582", "not_before": "1622883882", "resource": "821ba44a-a427-472e-9cc9-12b89bf42c08", "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiI4MjFiYTQ0YS1hNDI3LTQ3MmUtOWNjOS0xMmI4OWJmNDJjMDgiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC82YWE0Nzc1NS0wNjY2LTRhN2ItYWVmMy1mZDY2ZTM2ZjlkNDMvIiwiaWF0IjoxNjIyODgzODgyLCJuYmYiOjE2MjI4ODM4ODIsImV4cCI6MTYyMjk3MDU4MiwiYWlvIjoiRTJaZ1lOQk1uT2ZFTGw0aXBOa1VjL3ZXOGYvUEFRPT0iLCJhcHBpZCI6ImY0NTc1OTk0LTYzYmYtNGQxMS1iNGVmLTM5NjQ1MjU3YWMzZCIsImFwcGlkYWNyIjoiMSIsImlkcCI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzZhYTQ3NzU1LTA2NjYtNGE3Yi1hZWYzLWZkNjZlMzZmOWQ0My8iLCJvaWQiOiI3YTU1YWE2NS03MjJhLTQwYTMtYjM1ZC0xMTA3NDBhMDJhY2QiLCJyaCI6IjAuQVlFQVZYZWthbVlHZTBxdThfMW00Mi1kUTVSWlZfU19ZeEZOdE84NVpGSlhyRDJCQUFBLiIsInJvbGVzIjpbIkZpbmFuY2lhbHMuUmVhZFdyaXRlLkFsbCJdLCJzdWIiOiI3YTU1YWE2NS03MjJhLTQwYTMtYjM1ZC0xMTA3NDBhMDJhY2QiLCJ0aWQiOiI2YWE0Nzc1NS0wNjY2LTRhN2ItYWVmMy1mZDY2ZTM2ZjlkNDMiLCJ1dGkiOiJaWEQtZ0VrNGkwV1NoNWtlcElnRkFBIiwidmVyIjoiMS4wIn0.VLpIJwhivCHAfNuwnF_PTgkfLIXS95twOFkDcXVYcBpL6F0AMFjMWwyrqTRSnvpYvsR2HDz7lWhzL-IvZfafZ1En1NJhyAgpL2pB1yVqqVPPPE_jYbo7mm6JyuxK1iuwj_gH1LmQb8LL3VzrewZDHigW0W57VTG_6M1b24njQv3sNcAU3e7WkCmughbyvXECW89vcPE1twANpLoY-GpYjXQaE923eG3ROf195F5P9aRQeYmBgZ06GVxIvhQcUrriNsURixeAkXZA8zYSsegINinOdy5pIGx3heK5AklLulr5lzwp70uoPDl0gvUFG9y68A1Px4J_elBMiW1fBOnvWw" }
Here's the issue; when I use the Token to make a request I get the following response (HTTP 500):
{ "error": { "code": "Unknown", "message": "IDX10231: Audience validation failed. Delegate returned false, securitytoken: '[PII is hidden]'. CorrelationId: 54ded16a-9bf6-466a-8300-3adac2b6c614." } }
The Event log (Admin) shows the following message:
Server instance: RELion10_EXTENSIONS_OData_Oauth2 Tenant ID: Type: Microsoft.IdentityModel.Tokens.SecurityTokenInvalidAudienceException InvalidAudience: 821ba44a-a427-472e-9cc9-12b89bf42c08 Message: IDX10231: Audience validation failed. Delegate returned false, securitytoken: '[PII is hidden]'. StackTrace: at Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable`1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters) at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters) at Microsoft.Dynamics.Nav.Service.NavJwtSecurityTokenFactory.CreateAndValidateWithAudienceList(String serializedToken, FederationMetadataProvider federationMetadataProvider, IEnumerable`1 allowedAudiences, String tokenId, NavDiagnostics diagnostics) at Microsoft.Dynamics.Nav.Service.WebServiceBearerAuthenticator.TryAuthenticateUser(String authorizationHeader, Uri requestUrl) at Microsoft.Dynamics.Nav.Service.ServiceAuthenticationHelper.AuthenticateForServiceCall(Uri uri, String authorizationValue, Func`3 createException) at Microsoft.Dynamics.Nav.Service.OData.V4.HttpRequestMessageExtensions.Authenticate(HttpRequestMessage request) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Microsoft.Dynamics.Nav.Service.OData.NavServiceEnvironment.EnsureNavAuthentication() at Microsoft.Dynamics.Nav.Service.OData.V4.RouteBuilder.GetEdmModelInternal(IServiceProvider serviceProvider) at lambda_method(Closure , ServiceProvider ) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.AspNet.OData.Routing.DefaultODataPathHandler.Parse(String serviceRoot, String odataPath, IServiceProvider requestContainer, Boolean template) at Microsoft.AspNet.OData.Routing.DefaultODataPathHandler.Parse(String serviceRoot, String odataPath, IServiceProvider requestContainer) at Microsoft.Dynamics.Nav.Service.OData.V4.PathHandler.Parse(String serviceRoot, String odataPath, IServiceProvider requestContainer) at Microsoft.Dynamics.Nav.Service.OData.V4.RouteConstraint.Match(HttpRequestMessage request, IHttpRoute route, String parameterName, IDictionary`2 values, HttpRouteDirection routeDirection) at System.Web.Http.Routing.HttpRoute.ProcessConstraint(HttpRequestMessage request, Object constraint, String parameterName, HttpRouteValueDictionary values, HttpRouteDirection routeDirection) at System.Web.Http.Routing.HttpRoute.ProcessConstraints(HttpRequestMessage request, HttpRouteValueDictionary values, HttpRouteDirection routeDirection) at System.Web.Http.Routing.HttpRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request) at System.Web.Http.HttpRouteCollection.GetRouteData(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpRoutingDispatcher.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Net.Http.DelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Web.Http.HttpServer.d__0.MoveNext() Source: Microsoft.IdentityModel.Tokens HResult: -2146233088 StackTrace: at Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable`1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters) at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters) at Microsoft.Dynamics.Nav.Service.NavJwtSecurityTokenFactory.CreateAndValidateWithAudienceList(String serializedToken, FederationMetadataProvider federationMetadataProvider, IEnumerable`1 allowedAudiences, String tokenId, NavDiagnostics diagnostics) at Microsoft.Dynamics.Nav.Service.WebServiceBearerAuthenticator.TryAuthenticateUser(String authorizationHeader, Uri requestUrl) at Microsoft.Dynamics.Nav.Service.ServiceAuthenticationHelper.AuthenticateForServiceCall(Uri uri, String authorizationValue, Func`3 createException) at Microsoft.Dynamics.Nav.Service.OData.V4.HttpRequestMessageExtensions.Authenticate(HttpRequestMessage request) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Microsoft.Dynamics.Nav.Service.OData.NavServiceEnvironment.EnsureNavAuthentication() at Microsoft.Dynamics.Nav.Service.OData.V4.RouteBuilder.GetEdmModelInternal(IServiceProvider serviceProvider) at lambda_method(Closure , ServiceProvider ) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.AspNet.OData.Routing.DefaultODataPathHandler.Parse(String serviceRoot, String odataPath, IServiceProvider requestContainer, Boolean template) at Microsoft.AspNet.OData.Routing.DefaultODataPathHandler.Parse(String serviceRoot, String odataPath, IServiceProvider requestContainer) at Microsoft.Dynamics.Nav.Service.OData.V4.PathHandler.Parse(String serviceRoot, String odataPath, IServiceProvider requestContainer) at Microsoft.Dynamics.Nav.Service.OData.V4.RouteConstraint.Match(HttpRequestMessage request, IHttpRoute route, String parameterName, IDictionary`2 values, HttpRouteDirection routeDirection) at System.Web.Http.Routing.HttpRoute.ProcessConstraint(HttpRequestMessage request, Object constraint, String parameterName, HttpRouteValueDictionary values, HttpRouteDirection routeDirection) at System.Web.Http.Routing.HttpRoute.ProcessConstraints(HttpRequestMessage request, HttpRouteValueDictionary values, HttpRouteDirection routeDirection) at System.Web.Http.Routing.HttpRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request) at System.Web.Http.HttpRouteCollection.GetRouteData(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpRoutingDispatcher.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Net.Http.DelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Web.Http.HttpServer.d__0.MoveNext()
Event Log (Operational)
Server instance: RELion10_EXTENSIONS_OData_Oauth2 Tenant ID: The received security token could be validated but does not give access to Dynamics 365 Business Central. Token Details : Issuer: https://sts.windows.net/6aa47755-0666-4a7b-aef3-fd66e36f9d43/ Expiry (UTC): 07.06.2021 09:29:10 TenantId: 6aa47755-0666-4a7b-aef3-fd66e36f9d43 AppId: f4575994-63bf-4d11-b4ef-39645257ac3d IdentityProvider: https://sts.windows.net/6aa47755-0666-4a7b-aef3-fd66e36f9d43/ Version: 1.0
I am using the Business Central (AAD) Application's Id as the Resource (821ba44a-a427-472e-9cc9-12b89bf42c08).
I also tried using the appIdUrl as the resource, again I can retrieve Tokens just fine. When I use a token like this, I get a different error message (HTTP Status 401):
{ "error": { "code": "Authentication_InvalidCredentials", "message": "The server has rejected the client credentials. CorrelationId: b08e51a3-7702-4ec0-9c07-6c7eedb39ae4." } }
In this case the event log does not create an entry.
What am I doing wrong?
I've been at it for hours now, so any help is greatly appreciated
Jakob