Page Web Service with User Authentication

J_hooJ_hoo Member Posts: 2
edited 2013-09-17 in NAV Tips & Tricks
Hi all,

Since mibuso's been such a huge help to me in the past, I want to share my recent NAV-solution with you guys.

What I wanted was to publish a page as a web service from NAV, but I wanted to have user-authentication. NAV didn't provide a reasonable way to do this,

and on the other hand I wanted to let specific users only access specific records.

Example scenario:
    - The record Sales Quotes is published as a web service (a new page) - I want users to be able to log in with their own Customer No. and a password, from a front-end (eg. php or java) - Users may only access their own records


Of course, we could just filter the new Sales Quote -page with Sell-to Cust. = Customer, but this is unacceptable because by removing the filter a bad-guy could access everyones records.

So instead, my solution:
    - The record for the web service -page is temporary - Authentication details are provided in a filter-field - The accepted users are listed in a separate NAV table - The records (to publish) are written to the temporary table in runtime, in C/AL, based on the credentials provided

A. STEPS TO SET THIS UP:

1. A new Page, with the source table you want to publish (eg. Sales Quote), SourceTableTemporary = yes.
2. A Users-table, with User Name and Hash-fields (eg. sha12) if you want to do it right, or a password-field if moving plaintext-passwords is ok for you.
3. Fields "User Name" and Hash in the record you want to publish. These fields are only used by the front-end to provide credentials - they needn't have any values in the record itself.
4. Proper trigger code in OnFindRecord() of the web service Page. Here's an example which builds the temporary record, ie. the records to give out in the web service:
OnFindRecord(Which : Text) : Boolean
{
   	// trim since filter can contain ''
	userName := DELCHR( GETFILTER("User Name"), '<>', '''');
	userHash := DELCHR( GETFILTER(Hash), '<>', '''');

	// function which compares the given credentials to the ones in the User-table.
	// Be sure to use SETRANGE and not SETFILTER when looking for the User with hash,
	// and check that you only get one record as a result. We don't want Hash='*' to work.
	IF NOT cu.userAuthentication(userName, userHash) THEN
	 BEGIN
	   DELETEALL(FALSE);
	   EXIT(FALSE);
	 END;

	IF (userName <> '') THEN  // credentials accepted
	 BEGIN
	  salesHeader.COPYFILTERS(Rec); // could potentially be some filters worth copying
	  salesHeader.SETRANGE(Hash);   // don't care about auth-filters anymore
	  salesHeader.SETRANGE("User Name", userName);

	  salesHeader.SETRANGE("Document Type", salesHeader."Document Type"::Order);

	  IF salesHeader.FIND('-') THEN
	   REPEAT
	        Rec.TRANSFERFIELDS(salesHeader);
	        Rec.INSERT(FALSE);
	   UNTIL salesHeader.NEXT() = 0;

	   Rec.RESET;
	   EXIT(Rec.FIND(Which));
	 END;

	EXIT(FALSE);
}



B. STEPS TO USE THIS:

1. Set the filters you want for the record, eg. Salesperson Code = FUU
2. Set filter-value for the fields User Name and Hash
3. Request records from the web service

Java-example for setting the authentication-filters
	WebServiceFilter userFilter = new WebServiceFilter();
	userFilter.setField(WebServiceFields.USER_NAME);
	userFilter.setCriteria(userName);			
	WebServiceFilter hashFilter = new WebServiceFilter();
	hashFilter.setField(WebServiceFields.HASH);
	hashFilter.setCriteria(userHash);
				
	ArrayList<WebServiceFilter> filters1 = new ArrayList<WebServiceFilter>(); 
	filters1.add(userFilter);
	filters1.add(hashFilter);
	WebServiceList salesQuotes = serviceCall.readMultiple(filters1, null, 0);

C. STEPS TO TEST THIS
To see whether authentication works and the web service provides (only the) records as we want it to.

1. Set working credentials as filters in the web service pages OnOpenPage
OnOpenPage()
SETFILTER("User Name", '2000');
SETFILTER(Hash, '%1', 'C984106E1276A..');

2. Run the Page. If everything is working as it should, you should now see the records which will be provided when these login-credentials are provided.
Also test what happens when you clear the filter.

3. Remember to clear the OnOpenPage-trigger-code before you publish this, otherwise this users records will be shown.


I hope this proves useful for others too!

Have a great week!
J
Sign In or Register to comment.