Soren has taught me yesterday that some of the bugs I encountered have been properly disinsected by Microsoft, so other than the workarounds I suggested, there is an option to apply the hotfix and forget about that one.
Today, I’ll explain a not so critical bug, as the one yesterday, but depending on what exactly you do with Web services, it may be more than just a nuisance.
Hello, bug #3: accessing WSDL without database-wide permissions.
Problem
This one is very simple to repeat, and you don’t need any coding. You simply need to have a Windows login which only has roles assigned for a single company.
Follow these steps:
- Add a Windows login to your NAV database, assign it to SUPER role, and specify company for that role. For example:
- Synchronize the login, if necessary.
- Publish a page as a Web service, say 21 Customer Card, call it whatever
- Restart the NST (the Web services part).
- Open the browser as the user you defined in step 1.
- Navigate to the WSDL of the Web service defined in step 3, e.g. http://localhost:7047/DynamicsNAV/WS/Page/Customer
At this point, this is what the server returns: “The remote server returned an error: (500) Internal Server Error.”
Now do a funny thing. Access the same Web service, but as a user who has database-wide SUPER role (SUPER without a company name specified).
Now you get WSDL as expected.
Now repeat the same as the user with only company-level SUPER role. Guess what – no more errors. The server happily returns the WSDL.
So, a one-sentence description of symptoms is this: a user with only company-level access cannot read WSDL of a Web service unless a user with database-wide SUPER access has previously read the WSDL of the same service.
I can’t tell exactly what’s happening under the hood, but I imagine it’s some security glitch which prevents the user to read WSDL unless the user has database-wide SUPER access. If a database-wide SUPERman has already read the WSDL, it seems to be cached, and returned to anybody else from cache, regardless of their security permission.
So, it may be that accessing WSDL without database-wide SUPER role is prohibited by design, in which case WSDL shouldn’t be returned from cache. Or it may be that anybody should read the WSDL as long as they have proper access to the underlying object(s), in which case there is a bug in returning the WSDL back to the user.
In any case, not good.
Workaround
Well, there is none I could identify. The only thing you can do is access WSDL as a superman, then consuming the service as whoever.
However… (there must be a however)
What if you had a generic application (and I know of at least three of such) which must access WSDL in runtime, and that WSDL might be accessed by a mere mortal?
There are several possible options:
- If objects are not expected to change, access WSDL once for each needed service during setup, and cache the WSDL description.
- If objects are expected to change, create a Windows service which runs as a superman, and accesses WSDL on behalf of mortals.
- As an alternative to above, you may store credentials of a superman (of course, you should use some strong encryption here, e.g. the one Windows uses for storing credentials of Windows services), then if reading of the WSDL fails for the error seen earlier, you retry as superman and see if it works.
- Despair.
I understand this might not be a big problem for most of Web services applications, primarily those that are custom-built for a single customer. But if you have any ISV application which is not specific to an installation, but can run under many different installations of NAV, then this problem might hurt you a bit, in which case I hope you read this post before you actually deploy the application to hundreds of customers.
If you have some thoughts about this problem, or are aware of a hotfix which solves it, please contribute.
Instead of:
http://localhost:7047/DynamicsNAV/WS/Page/Customer
use :
http://localhost:7047/DynamicsNAV/WS//Page/Customer
http://localhost:7047/DynamicsNAV/WS/CompanyName/Page/Customer
Armonds: thanks for the comment. I can’t check it right now, but are you sure this actually does fix this problem?
nop 🙁
but I got error message: No execute permission on ” Page with ID
JUST experienced this and had a web developer point it out to me. He had SUPER, company specific permissions. Solution was to take the basic role and assign that without a company. Problem solved. I didn’t have much time to test but I’m guessing that it’s trying to get at the Object Metadata system table. By assigning SUPER with a company it would essentially take all (some? definitely getting to the security tables) of the system (2000000000+) tables and exclude them as they are DataPerCompany = No. That might make sense, the “error” however doesn’t. Anyway, someone could start with Basic and chop that role down until they get to the table(s) required.
@Bill: yes, but this is not quite a solution. Imagine a situation where you want to hide the list of companies from users (quite a legitimate request). If you do what you mention above, that user will be able to cache the WSDL, but that user will also be able to get the list of all companies in the database.
I’ve been battling in this area too and found another strange thing happening with the WSDL. A 3rd party wants to consume a NAV webservice method called “sendNotification”. I setup a codeunit with a function called that, but the WSDL presents it as “SendNotification”. Because it uses an upper case “S” and the requests want a lower case “s” they get rejected.
I guess I’ll have to look at using a proxy service to relay the requests to NAV – unless you have any better ideas?
John – sorry, I am not aware of this problem, and I can’t think of a solution. I am kind of surprised that NST converts the method call to uppercase, but it seems like a bug to me. On another hand, I have a question – why does it absolutely have to be lowercase? This is against the conventions of identifier naming in NAV, and should be avoided.
NST doesn’t capitalise everything, just the first letter. It’s simple to replicate, just create a codeunit with a function that starts with a lowercase letter, publish it and then look at the WSDL.
The 3rd party that will be consuming the service defines a WSDL they want to you to provide and they have decided to use a lower case “s”. Since it is a big multi-national bank that uses this method to provide “services” to its customers, there is no scope for getting them to change. So it’s a case of being stuck between two huge corporations that won’t budge. Sad but true.