Saturday, August 4. 2018

Sometimes I get surprised with the lack of information and/or documentation around wildfly and JBoss. If you search over the security documentation for wildfly, it supports several authentication mechanisms, by default BASIC, FORM, SPNEGO and CLIENT-CERT. There is no mention to bearer tokens or JWT but, surprise, surprise, the support is there and it can be used out of the box. There is very scarce documentation but you can find some examples and a quickstart about this feature.

A JSON Web Token (JWT) is an access token than contains three parts: a header, a payload and a signature. The header is just a JSON with some fixed fields (like type -jwt in this case-, algorithm of the signature or the id of the key used). The payload is the interesting part and is just any JSON with the information that the token is going to interchange, it can be any information, but things like username, roles, groups, name and surname are common. Among those fields there are two typical keys: iss or issuer and aud or audience. The issuer is who is issuing the token. The audience is for what endpoint the token was created. Wildfly implementation can be configured to check these two fields. Finally a signature of the header and payload is added to ensure that the token is valid and has not been modified (non-repudiation and integrity). In current days these tokens are ubiquitous to authenticate and authorize web services applications.

I had no idea about this feature (even more, I thought that there was no bearer authentication by default in wildfly) and I had recommended custom developments several times for this use-case. That was a wrong advise or, at least, an incomplete one. So, once I have heard about this mechanism I thouhgt that it was fair to test it and know more about how it works. This entry is going to test the new BEARER_TOKEN mechanism introduced by elytron in a wildfly 13. The JWT token is going to be provided by the keycloak project but the server is going to consume it just using elytron (no agent provided by keycloak is going to be used, just plain wildflyBEARER_TOKEN mechanism).

Using the keycloak administration several objects are created. First a role that will be assigned to our users. In Roles click Add Role and create a user role.

Then create the user to be used with that role. Go to Users and Add user.

Assign a password in the Credentials tab (non-temporary) and finally assign the user role to it.

In Clients click Create and fill the wildlfy client information. This client will be used to get the token for the application (using direct login or direct grants) and with that token the wildfly endpoint will be called.

When you configure a client as confidential in the second tab, Credentials, you can set a secret for the client. This password will be needed for some operations later on (for login using client credentials and to configure introspection).

In the Scope tab full scope is removed and only the role user is assigned. This way the JWT token is restricted to contain only this role (if the user has it) and not all the user information.

Finally a mapper is going to be configured. This part is the only tricky point of the demo. The wildfly authenticator expects the roles in a top-level field in the JWT token, but keycloak uses the claim realm_access.roles (two levels). For that reason the role list is going to be moved to a Roles field (in elytron this is the default attribute is for roles, although any another attribute can be configured using a role-decoder). Create protocol mapper in the Mappers tab.

Now that keycloak is configured, we need the certificate that is going to be used to sign the token. We can get it from keycloak in Realm Settings → Keys → RSA type → Click Certificate. Create a keystore with it. The base64 data should be enclosed with -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines to be in a PEM format (the file keycloak.pem was generated).

As commented before the jwt is configured to only admit access tokens that are emitted by a set of issuers and to a specific audience (it seems those two fields are optional and can be omitted). The key-store is used to reference the certificate that keycloak is going to use to sign the tokens. This way elytron will validate that the signature is valid, being sure that the token was generated by keycloak and not modified by someone else. The attribute to identify the user will be preferred_username and nothing is specified for roles, so the default Roles attribute will be used.

Finally some debug levels are configured to check that everything is working.

In order to use the previous configuration the web.xml should use a security-constraint and the authentication method should be set to BEARER_TOKEN. Besides the user role is configured to give access to the application (this way the application is ensuring that token roles are parsed correctly).

Now a little test.sh is created in order to test the endpoint (you can find it inside the maven project). A curl command is executed to login and get a token using direct grants over the keycloak client. That token is sent inside the Authorization header to call the wildfly endpoint. The script is very simple but it works.

bash test.sh
Hello ricky!!!

The hello endpoint is returning my username so the token is being correctly validated and the username and roles are obtained.

Now let's try the introspection. The introspect is an endpoint that an OAuth 2.0 server gives to validate access tokens. This way, instead of using wildfly internal code, the container will call this endpoint to validate the access token. This has some advantages, for example, that the token is not restricted to be a JWT one.

So now the configuration of the jwt-realm should be modified from jwt to oauth2-introspect. The elytron configuration just offers to use a username/password configuration using BASIC authentication, but, as I commented previously, this is the default authentication for a confidential keycloak client, so it should work. The username is the client name, wildfly, and the password the one generated in the Credentials tab when the client was configured.

And my little script continues returning the same output, therefore the introspection endpoint is validating the ticket as expected.

So, it is working. Wildfly and the new elytron subsystem has a poor documented mechanism called BEARER_TOKEN, which lets you authenticate using JWT tokens (and, developing a custom realm, can be extended to more tokens, in general, to any token sent in the Authorization header with the BEARER prefix). In this entry the keycloak single sign-on product was installed to obtain the JWT token and then a token realm was configured inside elytron to validate it. First an internal validation was done (the wildfly code checks issuer, audience and signature) and then an OAuth introspection endpoint was configured to do the same (the server just calls the endpoint to validate the token). Both configuration work. Remember that the only trick was moving the roles to first level claim (Roles in this case), that is needed because wildfly just considers attributes at first level (and keycloak adds roles by default in a more complex JSON document). After my warning some documentation is starting to come to the project.

Saturday, July 21. 2018

This is the second entry about the interoperability between wildlfy and .NET using the WS-AT (Web Service Atomic Transactions). In the previous post I explained that there was an issue between both platforms which has been addressed in wildfly during the past months (mainly a different interpretation of the standard in which both sides think they are right and the other part is wrong). The wildfly XTS setup was also done using the new asynchronous implementation. In this new entry the windows side is going to be configured. I don't like to take screenshots so I will try to minimize the use of them but, this is windows, some images are going to be necessary.

As I commented before, I am not a specialist in Microsoft (better said, I am a complete disaster with it), so please take this information as a starting point or example. The steps to configure the WS-AT in windows 2016 are the following.

In the previous entry some certificates were created (ca, wildfly and win2016). Now those certs are going to be installed in the windows system. Copy the ca.crt, wildfly.crt and the win2016.p12 to the windows machine. And install them using the Certificate snap-in (follow this blog post to start the application). Import the three certificates in the following locations:

Select Personal → Certificates. Right click → All Tasks → Import... And select the win2016.p12 (the password is requested).

Once the certificates are installed the thumbprints for the last two will be needed (the certificates for each server). So please select the certificate and double click on it. In the second tab details you have the property Thumbprint with the number for each one (in my case wildfly cert is 8DA33E3DCD937777F1D307B58A3E6E103B8F31BB and win2016 is 1c54bd1932207b4e183e732a7e42ea757b471335).

Now it's the time to configure the WS-AT endpoint. This is done with the wsatconfig utility. Start the Developer Command Prompt for VS 2017 console (the wsatconfig is not exposed in a normal cmd console). And execute the following command:

This command enables network access for WS-AT on port 443 and configures the previous certificates (remember the thumbprints) to be used and admitted to communicate with the endpoint. In my case the final configuration is the following.

Finally a console application is needed to use the wildfly endpoint and the transactions. Open Visual Studio 2017 and File → New Project → Select Console App (.NET Framework). My application name is wsat-simple-client and can be download from here.

Add a reference to System.Transactions (to be able to use WS-AT in the application).

Then import the wsdl using the add service reference and selecting the WSDL of the wsat-simple application deployed in wildfly. This will create the artifacts to call the remote endpoint.

Now there are two tricky steps needed (both are required to start a WS-AT transaction when calling the wildfly endpoint). The App.config should be modified to add the following stanza inside the imported binding RestaurantServiceATServiceSoapBinding (meaning that this binding requires WS-AT):

<transactionFlow transactionProtocol="WSAtomicTransaction11"/>

And the auto-generated Reference.cs of the service should also be modified, to add that the makeBooking() method needs transaction level as a mandatory requirement:

And everything is ready. This is the video executing the application. It calls to the wildfly endpoint but, before that, the program knows that a transaction is needed for that method and it starts a WS-AT transaction. When wildfly receives the request it registers (now asynchronously) to the transaction as a new parted and the full flow is completed. Everything works as expected and the full transaction is completed successfully performing all the calls between both sides without any issues.

Your browser doesn't support the video tag. See this entry for more information about how to see the videos in this blog. You can download the file instead.

The summary is that now there is a initial support for interaction between wildfly and .NET using WS-AT. Previously any try to execute a transaction starting it at the windows side (wildfly needed to register to the MSDTC endpoint) failed because one side executed the registration synchronously and the other part expected an asynchronous call. Now wildfly has added the asynchronous endpoints to receive the windows responses and implemented a simple logic to handle the flow. All of this will be on the next release of wildfly 14. I do not think that a lot of people is using or wanting this but I know that it was a headache for a few people in the last year. Let's see if now it starts working.

Saturday, July 7. 2018

During the last year I have been involved in a very strange problem using Web Service Atomic Transaction (WS-AT) between Microsoft and Wildlfy. The WS-AT is an old OASIS standard to provide atomic transactions in the web between different services. The issue happened when the windows client started the transaction and a wildfly endpoint was called, in that moment the endpoint should register in the transaction and that operation failed. There was a lot of investigation and the final analysis was that the call was executed synchronously by wildfly but the Microsoft endpoint wanted it asynchronously. The standard is not very specific in this point and windows asynchronous requirement is, at least, controversial, an enhancement for wildfly was filed anyway.

In the last days the needed modifications have been included in the not yet released wildfly 14 and I decided to test it with a nightly snapshot. This entry is the wildfly setup and a continuation post will detail the windows side (much more complicated in my humble opinion). The steps to configure current snapshot are the following.

Download wildfly 14 (remember that now you can just download a nightly build). In my case I used the snapshot from Jun 30th 2018.

Install the bundle; copy the standalone-xts.xml configuration from the examples to the configuration folder; add an administrator user and, finally, start it using the xts configuration.

Configure the asynchronous registration for XTS. There is a new attribute in the XTS subsystem async-registration that should be changed to true (there is also going to be a system property to do the same in the future, mainly thinking for older versions). At the same time the server is configured to listen in all the interfaces of my laptop (the windows virtual machine should contact the server using the internal network).

This property enables two new endpoints in the XTS subsystem to receive the Microsoft responses for the registration call. Those endpoints are registered at the following locations:

http://localhost:8080/ws-c11/RegistrationResponseService?wsdl

http://localhost:8080/ws-c11/CoordinationFaultService?wsdl

The windows implementation requires mutual TLS authentication for the web services so it is important to create two certificates for each partner (windows and wildfly). In my environment the wildfly machine is my laptop (daredevil.sample.com/192.168.100.1) and the windows host is a 2016 essentials VM (remoteserver2.sample2.com/192.168.100.14). A CA is used to sign the two certificates for each server.

Now the certificates for wildfly are going to be installed. For that elytron is going to be configured to use HTTPS with the previously created certificates (the procedure is identical to the one followed in this previous entry).

Although the asynchronous endpoints are available and running after adding the XTS property, they are not used by default. Think that two parts are needed, one is having the endpoints deployed and the other is modifying the register call to send those endpoints, transforming the call from synchronous to asynchronous. This last part is managed using the xts-properties.xml configuration file for XTS.

Extract the default configuration xts-properties.xml from the library (jbossxts-X.X.X.jar, inside the modules folder of the wildfly installation), it's at first level inside the jar. Modify the file adding the property org.jboss.jbossts.xts.useAsynchronousRequest to SECURE (there is an example of the property but commented inside the file).

This way the XTS implementation will use the secure endpoints (https) in the registration call and the windows counterpart will call them with the response or the fault. Move the xts-properties.xml to the configuration folder (${JBOSS_HOME}/standalone/configuration/). The following CLI commands configure it to be used (there is a java option for that) besides some logging is also added to debug the calls during the process and web services are configured to use https scheme and the correct server name by default.

The sample WS-AT application that is integrated in the wildfly quickstarts is going to be used for testing. Some minor changes are needed to accommodate the code to windows. First clone the quickstart repository.

Then three modifications are done: windows prefers DOCUMENT style instead of RPC; by default Microsoft uses SOAP12, so the endpoint is tagged to be SOAP12HTTP_BINDING; finally the test client is configured to use the https endpoint in my wildfly machine (forcing https communication). Here it is my patch for the application.

Finally just package the application and deploy the resulting wsat-simple.war file in the wildfly server.

mvn clean package

And that is all. The wildfly application should work locally in the server. The video shows how you can go to the https port (application is deployed in / by default) and the local client is used to start a WS-AT call to the same server (both client and server are inside the wildfly server). The client starts the transaction and the ws endpoint registers asynchronously against the coordination endpoints inside the same server. The successful page is shown saying the transaction was completed with no issue. You can check the logs to see that the registration call was made contacting to the new asynchronous endpoints (the ReplyTo is filled with the new async URL and the response is received to that endpoint).

Your browser doesn't support the video tag. See this entry for more information about how to see the videos in this blog. You can download the file instead.

The most interesting part is left for the next entry. A .NET application will be integrated to call the WS-AT endpoint in the wsat-simple application. In turn the wildfly web service will call the windows coordination endpoint (which require asynchronous calling) to be registered as a partner in the transaction. The configuration of both sides is not trivial so I prefer to divide the entry in two parts. I have the demo working but I need to collect some screenshots for the windows configuration (I am sorry in advance about the Microsoft part, please consider I never use windows and every time I have to work with it the results are a big mess).