Authentication

With Java

476 views June 12, 2017 November 24, 2017 0

This guide will show you how to verify a SAML response using the client kit for Java. The example code in this section demonstrates verification of a SAML response in a Spark web application, and the Java client kit contains similar code using regular JSP.

You may download the code in this guide from https://github.com/signicat/auth.

Include the Java client kit in your project

The first step is to download the client kit for Java. The lib folder will contain the .jar-files you need, so include them into your project. The client kit also contains more example code.

Create the method which will receive the SAML response

The Verify Method
post(“/verify”, (request, response) -> {

String nationalId = null;
String assertion = request.queryParams(“SAMLResponse”);
if (assertion != null && assertion.length() > 0) {

Properties configuration = new Properties();
configuration.setProperty(“debug”, “false”);

// The name of the certificate we trust.
// IMPORTANT! This must be changed when moving from test to
// production.
boolean useTestEnvironment = true;
if (useTestEnvironment) {
configuration.setProperty(“asserting.party.certificate.subject.dn”,
“CN=test.signicat.com/std, OU=Signicat, O=Signicat, L=Trondheim, ST=Norway, C=NO”);
} else {
configuration.setProperty(“asserting.party.certificate.subject.dn”,
“CN=id.signicat.com/std, OU=Signicat, O=Signicat, L=Trondheim, ST=Norway, C=NO”);
}

// Creates the SamlFacade object that will be used to parse SAML
// responses
SamlFacade samlFacade = new SamlFacade(configuration);
try {
// Parse and validate the SAML Request
String recipientUrl = request.url();
SamlResponseData samlResponseData = samlFacade.readSamlResponse(assertion, new URL(recipientUrl));

for (SamlResponseData.Attribute attribute : samlResponseData.getAttributes()) {
if (attribute.getName().equals(“no.fnr”)) {
nationalId = (String) attribute.getValue();
System.out.println(nationalId);
}
}

} catch (ScResponseException e) {
System.out.println(“ERROR: The user was not authenticated: ” + e.getMessage());
} catch (ScSecurityException e) {
System.out.println(“ERROR: The login was aborted. Technical message: ” + e.getMessage());
} catch (MalformedURLException e) {
System.out.println(“ERROR: Failed to understand recipient URL. ” + e.getMessage());
}
}

if (nationalId != null) {

// Demo code for illustration purposes.
// You are not required nor encouraged to use the national
// identity number in your cookies.
response.cookie(“nationalid”, nationalId, 3600, true);
response.redirect(“/granted”);

} else {
response.redirect(“/denied”);
}
return null;
});

 

Code walkthrough

Code Description
String assertion = request.queryParams(“SAMLResponse”); Fetch the base 64 encoded SAML response from the HttpServletRequest.
configuration.setProperty(“asserting.party.certificate.subject.dn”, “…”); Set the subject distinguished name of the expected certificate used to sign the SAML response (i.e. the certificate used by Signicat to sign SAML responses). This value will differ between test and production, so make it configurable.
String recipientUrl = request.url(); A SAML response contains information about the intended recipient of it, i.e. the URL of the method which should receive it. This is a safety mechanism to make sure that you’re not verifying SAML responses that were intended for another recipient/application. If this application was running on http://localhost:4567 then the request URL would be http://localhost:4567/verify. (In production you are required to use https.)
SamlResponseData samlResponseData = samlFacade.readSamlResponse(assertion, new URL(recipientUrl)); The readSamlResponse method expects the base 64 encoded SAML response and the previously constructed recipient URL. If successful, the SamlResponseData will contain a set of all the attributes in the SAML response. If unsuccessful, it will throw an exception and the exception message will tell you why.
for(SamlResponseData.Attribute attribute : samlResponseData.getAttributes()) You may iterate over the attributes in the response, or you may use SamlResponseData.getSubjectName() to retrieve information about the subject. The code you write here will depend on what id method is in use and which information you are interested in. See example SAML responses for different id providers here.
response.cookie(“nationalid”, nationalId, 3600, true); Demo code. Most likely you want to map a national identity number of a person to some kind of user id in your application. You are not required nor encouraged to use the national identity number in your cookies.
response.redirect(“/granted”); Authentication is complete and you may redirect the user to wherever you’d like.

Error situations

The following exceptions are not uncommonly produced when verifying the SAML response:

Exception Description
ScResponseException A type of exception which occurs when the SAML response indicates an invalid authentication, for example if the authentication process was cancelled or the user´s certificate expired.
ScSecurityException A type of exception related to security, i.e. expired SAML responses, incorrect recipient, problems verifying the certificate information etc.

Full Example Code

import static spark.Spark.*;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Properties;

import com.signicat.services.client.ScResponseException;
import com.signicat.services.client.ScSecurityException;
import com.signicat.services.client.saml.SamlFacade;
import com.signicat.services.client.saml.SamlResponseData;

public class Auth {

public static void main(String[] args) {

get(“/”, (request, response) -> {

String target = request.url() + “verify”;
String targetUrlEncoded = urlEncode(target);
String authenticationUrl = “https://preprod.signicat.com/std/method/shared/?id=nbid:demo:nb&target=” + targetUrlEncoded;
response.redirect(authenticationUrl);
return null;
});

post(“/verify”, (request, response) -> {

String nationalId = null;
String assertion = request.queryParams(“SAMLResponse”);
if (assertion != null && assertion.length() > 0) {

Properties configuration = new Properties();
configuration.setProperty(“debug”, “false”);

// The name of the certificate we trust.
// IMPORTANT! This must be changed when moving from test to
// production.
boolean useTestEnvironment = true;
if (useTestEnvironment) {
configuration.setProperty(“asserting.party.certificate.subject.dn”,
“CN=test.signicat.com/std, OU=Signicat, O=Signicat, L=Trondheim, ST=Norway, C=NO”);
} else {
configuration.setProperty(“asserting.party.certificate.subject.dn”,
“CN=id.signicat.com/std, OU=Signicat, O=Signicat, L=Trondheim, ST=Norway, C=NO”);
}

// Creates the SamlFacade object that will be used to parse SAML
// responses
SamlFacade samlFacade = new SamlFacade(configuration);
try {
// Parse and validate the SAML Request
String recipientUrl = request.url();
SamlResponseData samlResponseData = samlFacade.readSamlResponse(assertion, new URL(recipientUrl));

for (SamlResponseData.Attribute attribute : samlResponseData.getAttributes()) {
if (attribute.getName().equals(“no.fnr”)) {
nationalId = (String) attribute.getValue();
System.out.println(nationalId);
}
}

} catch (ScResponseException e) {
System.out.println(“ERROR: The user was not authenticated: ” + e.getMessage());
} catch (ScSecurityException e) {
System.out.println(“ERROR: The login was aborted. Technical message: ” + e.getMessage());
} catch (MalformedURLException e) {
System.out.println(“ERROR: Failed to understand recipient URL. ” + e.getMessage());
}
}

if (nationalId != null) {

// Demo code for illustration purposes.
// You are not required nor encouraged to use the national
// identity number in your cookies.
response.cookie(“nationalid”, nationalId, 3600, true);
response.redirect(“/granted”);

} else {
response.redirect(“/denied”);
}
return null;
});

get(“/granted”, (request, response) -> {
String nationalId = request.cookie(“nationalid”);
System.out.println(nationalId);
response.type(“text/plain”);
return “Access granted”;
});

get(“/denied”, (request, response) -> {
response.type(“text/plain”);
response.status(401);
return “Access denied”;
});

}

public static String urlEncode(String s) {

try {
return URLEncoder.encode(s, “UTF-8”);
} catch (UnsupportedEncodingException e) {
return null;
}
}

}

Was this helpful?