[JAX-WS] Basic Authnetication example (Glassfish) and the client

This example will demonstrate how to configure and use Container provided BASIC authentication for a JAX-WS web service. To note that this is the real 🙂 BASIC authentication.

There are 3 parts:

I. Configure Glassfish realms
II. Implement the actual web service class and configure the deployment descriptor
III. Test authentication from SoapUI
IV. Java Client

I. Configure Glassfish realms
In order to define the realms in Glassfish, it is necessary to do 2 things:
I.1. Enable Default Principal To Role Mapping
Go to the glassfish console: localhost:4848 And open:
Configurations->Server Config -> Security and set enabled for Default Principal To Role Mapping as shown in the picture

1

I.2. Define the file based realm user
Go to Security -> Realms -> file and click on Manage Users as shown in the picture
2

Then define your user name and password. And most importantly type into Group List the value USER. See picture

3

Now you have your user acv with password acv and who is in the Group USER.

II. Implement the actual web service class and configure the deployment descriptor
II.1. Create a new Dynamic web project in Eclipse and set Glassfish as the target runtime. Don’t forget to select create web.xml on the last step of the wizard

II.2. Create a new java class inside a package. Note the user of the @RolesAllowed annotation which should have the value of USER, the very one that you have just defined in the server configuration:

package com.vvirlan;
import javax.annotation.security.RolesAllowed;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
public class Main {
	@WebMethod
	@RolesAllowed("USER")
	public String sayHello() {
		return "Hello";
	}
	@WebMethod
	@RolesAllowed("USER")
	public String sayNothing() {
		return "";
	}
}

II.3 Edit web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">
	<display-name>JaxWsBasicSecurity</display-name>
	<servlet>
		<servlet-name>Main</servlet-name>
		<servlet-class>com.vvirlan.Main</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>Main</servlet-name>
		<url-pattern>/user</url-pattern>
	</servlet-mapping>
	<security-constraint>
		<web-resource-collection>
			<web-resource-name>WRCollection</web-resource-name>
			<url-pattern>/user</url-pattern>
			<http-method>GET</http-method>
			<http-method>POST</http-method>
		</web-resource-collection>
		<auth-constraint>
			<role-name>USER</role-name>
		</auth-constraint>
		<user-data-constraint>
			<transport-guarantee>NONE</transport-guarantee>
		</user-data-constraint>
	</security-constraint>
	<login-config>
		<auth-method>BASIC</auth-method>
	</login-config>
	<security-role>
		<role-name>USER</role-name>
	</security-role>
</web-app>

So what we do here. First we define a servlet and point it to our class: Main. Next we map this servlet called Main to a url pattern. From now on our web service will be available not at the usual MainService, but at the url /user. Now we define the security constraint and instruct the container to require authentication for GET and POST request for the path /user. Next we define the role name USER again and set auth-method to BASIC. Finally we again use the name USER to declare the security role.

III. Run the application and ideally you should be able to open it in the browser and see a BASIC authentication form requiring username and password. Type acv and acv and you should see the endpoint. Somewhere here:
http://localhost:8080/JaxWsBasicSecurity/user

To test in SoapUI:
III.1 Create a new SOAP project
III.2 Paste in the WSDL URL: http://localhost:8080/JaxWsBasicSecurity/user?wsdl
III.3 You will be required to type username and password put twice acv and acv (in 2 forms)
III.4 Now trying to run a request you need to define Auth as in the picture
4
Clicking on play should give you the response.

IV. Java Client
IV.1. The first step is of course wsimport. But you have authentication enabled so you need to do this: Create a file called myXauthFile.txt in tmp folder (anywhere you like). Set the content to:

http://acv:acv@localhost:8080/JaxWsBasicSecurity/user?wsdl

IV.2 Run wsimport from the tmp folder:

C:\tmp\wsbasic>wsimport -keep -Xauthfile myXauthFile.txt http://localhost:8080/JaxWsBasicSecurity/user?wsdl

You should get the client artifacts.
IV.2 Copy your newly generated artifacts into eclipse in your client project
IV.3 Implement the Client class:

package com.vvirlan;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
public class TheClient {
	public static void main(String[] args) {
		TheClient cl = new TheClient();
		cl.run();
	}
	public void run() {
		Authenticator myAuth = new Authenticator() {
			@Override
			protected PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication("acv", "acv".toCharArray());
			}
		};
		Authenticator.setDefault(myAuth);
		MainService service = new MainService();
		Main port = service.getMainPort();
		// This would work, but you will get a 401 error on MainService service
		// = new MainService();
		// BindingProvider bp = (BindingProvider) port;
		// bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "acv");
		// bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "acv");
		String result = port.sayHello();
		System.out.println(result);
	}
}

Troubleshooting.
In case you get 403, try setting the server realms for both default-config and server-config. Also try to set the password again in glassfish. After this you need to restart the server and redeploy the app.

Advertisements