How do I talk to ADFS from Java?

Your application needs to act as a SAML SP, either directly (from your code), or indirectly (e.g. through SAML SP support on reverse proxy, application server, ...).

For direct options (which require more modifications to your application) you can:

  • code the SAML SP yourself (most likely with OpenSAML, you can find examples in sources of existing products)
  • use a ready-made product to integrate into your application, such as Spring SAML or OpenAM Fedlet

For indirect options (which require less modifications to your application) you can:

  • use Shibboleth SAML SP plugins or mod_auth_mellon on your Apache reverse proxy (if you use one)
  • deploy SAML SP as another application on your container (e.g. Spring SAML or OpenAM) and make it communicate with your application - so SAML SP performs authentication with ADFS and communicates this to your application e.g. through a shared cookie, or a custom token

You can find more comparison details and considerations in this thread.

ADFS 3 should have support for OAuth Authorization Server and it might well be an easier way to integrate, see here and here. Implementing authentication using OAuth is generally significantly easier than SAML, with no relevant disadvantages.

The Resin Authenticators that Caucho provides aren't gonna help with federation. Instead, you need to add a ServletFilter that looks for unauthenticated users. When it finds one, you should direct them to a login page. On this, you should ask the user if they want to login directly to your site or federate to another organization. (This could be done by displaying a username/password form + logos of trusted third-parties.) In the former, direct login case, use the Resin Authenticator to check against your local user repo or however you're doing it now. For the federated case, use SAML.

Federation would start by sending an authentication request to the trusted partner (the ADFS server). This is a little XML document packed into a form that will need a few things to be changed per request (e.g., creation time). This can be done with String.format -- nothing complicated. Send this authentication request to the SAML server (i.e., ADFS) at the organization the user selected. They'll login and send the authentication response to some "Assertion Consumer Service" that you need to create.

An ACS is just an endpoint that receives the SAML authentication response. This needs to be an unauthenticated endpoint that will parse and validate the reply from ADFS. Use OpenSAML to do this. There are quite a few things you need to do to make sure it's valid. For example, you must verify the digital signature of the assertion. You also need to check the issue time, that it's not in the future. Verify that the assertion is for you by checking the Destination in the confirmation data, audience, and recipient. Etc. Etc.

If this is beyond what you'd like to code, checkout an open source or commercial SAML server. It needs to function as an SP, and should run in Resin to keep things simple. One candidate that is mean and lean is Asimba. You can deploy this into Resin, and it will take care of both the request and the reply.

A Note about OAuth

What you're contemplating here is federation (or Web single-sign on). OAuth isn't suited for federation. It is a protocol designed to do delegated authorization. The OpenID Foundation has extended OAuth 2 to support federation in the OpenID Connect profile of OAuth. ADFS doesn't support this federation protocol, and is limited to WS-Federation and SAML. Therefore, you should no be looking into OAuth if ADFS will be used by your partners.