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