Learning Center/API and Integration/SAML Toolkits

SAML toolkit for Java

Thomas Pedersen
posted this on March 29, 2011 09:33 pm

Make sure you read the Introduction to OneLogin's SAML Toolkits.

Get the toolkit

Download the toolkit from github.com/onelogin/java-saml.

Using the toolkit

The com-folder contains the files you’ll copy into your Java application. The files index.jsp and consume.jsp are the ones that actually handle the SAML conversation, so let's have a look at those. They will act as a template for making your application a SAML relying party/service provider.

The index.jsp file acts as an initiater for the SAML conversation, if it should be initiated by the application. This is called Service Provider Initiated SAML. The service provider creates a SAML Authentication Request and sends it to the identity provider (IdP):

<%@page import="java.net.URLEncoder,org.apache.log4j.Logger"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="com.onelogin.saml.*,com.onelogin.*" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Auth Request</title>
<%

  // the appSettings object contain application specific settings used by the SAML library
  AppSettings appSettings = new AppSettings();

  // set the URL of the consume.jsp (or similar) file for this app. The SAML Response will be posted to this URL
  appSettings.setAssertionConsumerServiceUrl("http://x.y.z.z/consume.jsp");

  // set the issuer of the authentication request. This would usually be the URL of the issuing web application
  appSettings.setIssuer("https://www.mywebapp.com");
  
  // the accSettings object contains settings specific to the users account. 
  // At this point, your application must have identified the users origin
  AccountSettings accSettings = new AccountSettings();

  // The URL at the Identity Provider where to the authentication request should be sent
  accSettings.setIdpSsoTargetUrl("https://app.onelogin.com/saml/signon/12345");
  
  // Generate an AuthRequest and send it to the identity provider
  AuthRequest authReq = new AuthRequest(appSettings, accSettings);
  String reqString = accSettings.getIdp_sso_target_url()+"?SAMLRequest=" + AuthRequest.getRidOfCRLF(URLEncoder.encode(authReq.getRequest(AuthRequest.base64),"UTF-8"));
  response.sendRedirect(reqString);
%>
</head>
<body>
</body>
</html>

In order to know where to redirect the user with the authentication request, we need to establish the user's identity provider affinity. This depends on your application. Perhaps accounts have dedicated subdomain name (e.g. mycompany.accountingapp.com) or SAML-authentication for accounts is limited to certain IP-ranges. In those situations, you need to look up account information based on whatever information you already have about the user. In this example, those settings are provided by consume.jsp, which is meant as a stub for you customization:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="com.onelogin.*,com.onelogin.saml.*,org.apache.log4j.Logger" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>SAML Assertion Page</title>
</head>
<body>
<%
  String certificateS ="MIIBrTCCAaGgAwIBAgIBATADBgE......";

  // user account specific settings. Import the certificate here
  AccountSettings accountSettings = new AccountSettings();
  accountSettings.setCertificate(certificateS);

  Response samlResponse = new Response(accountSettings);
  samlResponse.loadXmlFromBase64(request.getParameter("SAMLResponse"));

  if (samlResponse.isValid()) {

    // the signature of the SAML Response is valid. The source is trusted
  	java.io.PrintWriter writer = response.getWriter();
  	writer.write("OK!");
  	String nameId = samlResponse.getNameId();
  	writer.write(nameId);
  	writer.flush();
	
  } else {

    // the signature of the SAML Response is not valid
  	java.io.PrintWriter writer = response.getWriter();
  	writer.write("Failed");
  	writer.flush();

  }
%>
</body>
</html>

The consume script receives the SAML assertion. Again, you need to know the identity provider to which the user belongs, but now you get a clue, since the username or email address in the SAML assertion - use samlResponse.getNameId() to retrieve it. Next you’ll use this information to retrieve the identity provider information, and after that, you can verify that the SAML assertion is actually from the identity provider configured on the account, as above.

What needs to be configured

In the example above, SAML settings are divided into two parts, the application specific (const_assertion_consumer_service_url, const_issuer, const_name_identifier_format) and the user/account specific (idp_sso_target_url, x509certificate). You’ll need to add your own code here to identify the user or user origin (e.g. by subdomain, ip_address etc.).

The following information needs to be available on the account:

appSettings.setAssertionConsumerServiceUrl
The URL at which the SAML assertion should be received. In this example "http://localhost:3000/saml/consume" would be correct.

appSettings.setIssuer
The name of your application. Some identity providers might need this to establish the identity of the service provider requesting the login.

accSettings.setIdpSsoTargetUrl
The URL to which the authentication request should be sent. This would be on the identity provider.

accountSettings.setCertificate
The x509 certificate fingerprint. This is provided from the identity provider when setting up the relationship.