<?xml version = "1.0" encoding = "UTF-8" ?>
<Response Destination = "https://example.com/home/" ID = "_44bf7ba9-9337-4ae1-8e70-a737dcb585cc" IssueInstant = "2014-01-18T11:10:44.9568516Z" Version = "2.0" xmlns = "urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xsd = "http://www.w3.org/2001/XMLSchema" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" >
<Issuer xmlns = "urn:oasis:names:tc:SAML:2.0:assertion" > Islyklar </Issuer >
<Signature xmlns = "http://www.w3.org/2000/09/xmldsig#" >
<CanonicalizationMethod Algorithm = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
<SignatureMethod Algorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI = "#_44bf7ba9-9337-4ae1-8e70-a737dcb585cc" >
<Transform Algorithm = "http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm = "http://www.w3.org/2001/10/xml-exc-c14n#" />
<DigestMethod Algorithm = "http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue > digestvalue(base64encoded) </DigestValue >
<SignatureValue > signaturevalue(base64encoded) </SignatureValue >
<X509Certificate > certvalue(base64encoded) </X509Certificate >
<StatusCode Value = "urn:oasis:names:tc:SAML:2.0:status:Success" />
<Assertion ID = "_804d90d1-8376-49c6-b604-d11c13be4207" IssueInstant = "2014-01-18T11:10:44.9568516Z" Version = "2.0" xmlns = "urn:oasis:names:tc:SAML:2.0:assertion" >
<Issuer > Islyklar </Issuer >
<NameID NameQualifier = "island.is" />
<SubjectConfirmation Method = "urn:oasis:names:tc:SAML:2.0:cm:bearer" >
<SubjectConfirmationData Address = "123.456.789.123" NotOnOrAfter = "2014-01-18T11:15:44.9568516Z" Recipient = "https://example.com/home/" />
<Conditions NotBefore = "2014-01-18T11:10:44.9568516Z" NotOnOrAfter = "2014-01-18T11:15:44.9568516Z" >
<Audience > example.com </Audience >
<AuthnStatement AuthnInstant = "2014-01-18T11:10:44.9568516Z" >
<SubjectLocality Address = "789.456.123.789" />
<AuthnContextClassRef > urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport </AuthnContextClassRef >
<Attribute FriendlyName = "Kennitala" Name = "UserSSN" NameFormat = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic" >
<AttributeValue xsi:type = "xsd:string" > 1234567890 </AttributeValue >
<Attribute FriendlyName = "Nafn" Name = "Name" NameFormat = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic" >
<AttributeValue xsi:type = "xsd:string" > John Johnson </AttributeValue >
<Attribute FriendlyName = "IPTala" Name = "IPAddress" NameFormat = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic" >
<AttributeValue xsi:type = "xsd:string" > 123.456.789.123 </AttributeValue >
I have developed a Java web application, and I want to implement SAML. These are the steps I believe is right to implement SAML.
I have got a sample code and I am able to create SAML request and its like this
I can encode it and send to IdP.
I want to create sample Java code to get this SAML request and then create a SAML response. How can I decode the request and validate it and create response? And Do I need to sign the saml response with certificate? and then send back to the SP?
The steps you've listed are more or less correct. The only thing I'd point to is that you have to be careful with the meaning if the word sends (ex. in "SP. sends a SAML authentication request to IdP"). SAML allows authentications scenarios with zero direct communication between SP and IdP.
Another small addition is that SP may also sign his request, so you may have signature validation on both sides. Validation on the SP side is obligatory.
If you want to implement SAML, you may want to check one of the existing solutions, for example Shibboleth . If you're on platforms like Spring and JBoss you may want to check Spring Security SAML or JBoss PicketLink . If you want to go lower-level, check OpenSAML .
In my corp we have JBoss as standard and are very happy with PicketLink .
Although this is an old post, I am adding sample code and references which I found useful.
Now Validate the digital signature.
Now fetch the assertion map.
In the above logic use the below private method to pull all the assertion attributes. Finally you will have map of all the fields that are sent to you.
Add new class SAMLReader as below.
SAML for Web Developers
Interested in adding SAML (Security Assertion Markup Language) support to your app? This post explains the basic single sign-on flows for web applications. If you have questions or feedback, please file an issue .
SAML lets you manage user identities and authorizations across multiple apps. It's similar to how we use our Google identity to login to YouTube, or our Facebook identity for. errr everything else.
Large companies love single sign-on. Instead of using OAuth, they use SAML. And instead of Farmville, it's Enterprise Software™. Po-tay-toes, Po-tah-toes.
The SAML standard has been around for a long time, with the latest version (2.0) released in 2005. It's widely adopted by large companies, and there's a whole industry (identity access management, IAM) dedicated to supporting it.
How does it make your users' lives easier?
There are many complex use cases for SAML, but let's start with a simple example to get familiar with the jargon.
Alice needs to schedule a work trip. Her company has two internal web applications; One for booking flights, and another for booking a rental car.
In SAML speak, Alice is our principal. the user that we're trying to authenticate and learn about. The two applications are the service providers .
She visits https://flights.acme-corp.biz/flights and is redirected to https://idp.acme-corp.biz?SAMLRequest=. to single sign-on.
When the principal, Alice on her browser, tries to access a protected resource ( /flights ), the service provider ( https://flights.acme-corp.biz ) doesn't present her with a login page. Instead, it redirects her to an identity provider ( https://idp.acme-corp.biz ) with an authentication request in the query parameter. The identity provider uses the authentication request to tell which service provider is making the request. Alice is now logged into the identity provider. In this context, we can also call the identity provider a session authority and say that Alice has a valid session with it. This becomes important later on when we talk about how she books a car rental.
Tip: I avoid abbreviations and acronyms in this guide, but you will commonly see service provider abbreviated as SP, and identity providers abbreviated as idP.
Alice types her username and password into https://idp.acme-corp.biz and is redirected back to https://flights.acme-corp.biz/flights .
After the identity provider successfully authenticates Alice, it sends a response back to the service provider saying authentication was successful, and releasing assertions about the principal. Assertions are statements about the principal. They typically include information like email, full name, and other contact information. The service provider can use these to update an existing user's profile, or to provision a new user. (Provisioning is a fancy term for "creating a new thing").
After booking her flight, she visits https://cars.acme-corp.biz/rentals. She is once again redirected to https://idp.acme-corp.biz?SAMLRequest=. but she's immediately redirected back to https://cars.acme-corp.biz/rentals without having to type her password again.
Why didn't Alice need to re-authenticate? Remember that when she redirected to the identity provider for booking her flight, she established a session with the identity provider. When this other service provider ( https://cars.acme-corp.biz ) sent a authentication request, the identity provider saw that Alice had previously authenticated because of her active session. There's no need for Alice to re-authenticate again, so the identity provider redirects her back to the site she wanted with a successful response.
Tip: Just as an identity provider can be called a session authority, the complement for service providers is to be called a session participant .
In the single sign-on example, I glossed over how a user is "redirected" between the identity providers and service providers. In SAML, a binding describes how messages should be encoded, and the underlying transport protocol to carry them. For web single sign-on, two common bindings are the "HTTP Redirect Binding" and the "HTTP Post Binding". Their names hint at their function. For example, we can specify that initial authentication requests from a service provider to an identity provider should happen with the redirect binding; The response from identity provider to service provider should happen with the post binding.
This is a common configuration, but SAML also supports other bindings like SOAP, URI, and Artifact.
SAML responses include conditions under which the response is valid. Responses are typically only good for a few minutes to prevent replay attacks (SAMLCore 22.214.171.124). They can be optionally signed and/or encrypted with a shared secret between relying parties (all identity providers and service providers) (SAMLCore 5 and 6). It's a good idea to do everything over SSL.
Because SAML is such a general framework, there's a ton of choices for how to configure it. Which binding to use? Signed or unsigned assertions / responses? Fortunately, SAML also defines a standard for communicating these configurations between relying parties. By publishing metadata about your service, configuring your service could be as easy as a single click to import the metadata.
Putting it all together
Now that we know all the pieces involved, let's implement a simple single sign on flow for the Flights service provider. Here are our requirements:
To keep the examples simple, I'm putting the minimum set of attributes in the XML messages. There are many more attributes and elements you can optionally specify to tweak it to your needs. Schema Central is a great reference for what's actually required and what's optional.
First, we need to define service provider metadata to let identity providers know how to talk to us.
The AssertionConsumerService element tells identity providers to use the HTTP POST Binding to send responses to /saml/consume .
When Alice requests the page /flights. our app will redirect the user to the identity provider and pass along the following authentication request:
The AuthnRequest must have a globally unique identifier (ID). This will show up again when we see the response from the identity provider.
Since we're using the HTTP Redirect binding, we want to Base64 encode this XML and append it to the url as a query parameter SAMLRequest. So the location we redirect Alice to will be:
Tip: Be really careful about whitespace in your requests and responses. These can wreak havoc on digital signatures and cause errors when validating messages.
Alice sees the login page for the identity provider, types in the correct credentials, and establishes a session with the identity provider. The identity provider gathers the information it knows about Alice and builds a response with the assertions about Alice:
Again, this response is Base64 encoded. Since we've specified in our metadata to use HTTP Post binding for receiving messages, the identity provider will direct the principal to POST the encoded message back to https://flights.acme-corp.biz/saml/consume. The location was also defined in the metadata.
Tip: It's common to use the HTTP Post Binding for receiving SAML responses because browsers have url length limits that don't work with with large responses.
The Flights app sees that the authentication was successful from the StatusCode element, and can also learn more about the principal from the Assertion element; Here we see that Alice's email is firstname.lastname@example.org. Using this information, Flights can now establish a session for Alice.
To keep the introduction gentle and focused for web developers, I intentionally left out a lot of cool details. What if you have native applications that doesn't go through a web browser? What about other bindings? What if you want to extend the spec?
The documentation is fantastic, but I recommend reading them in this order:
These are interesting to skim, but work better as reference docs rather than a guide:
This document provides steps to resolve common error messages encountered during the integration or use of SAML-based Single Sign On (SSO) with G Suite when Google is the service provider (SP).Configuration and Activation
This error typically indicates that you are trying to use Single Sign On with a Standard (Free) Edition of G Suite, which is not currently supported. If you are certain that you are using G Suite, Education, or ISPs, check the configuration in your Identity Provider to ensure that you have entered your Apps domain name correctly.
This error indicates that you have not set up Single Sign On correctly in your Apps Control Panel. Please review the following steps to correct the situation:
This error message indicates that your Identity Provider is not providing Google with a valid SAML response of some kind. This problem is almost certainly due to a configuration issue in the Identity Provider.
The SAML 2.0 specification requires that Identity Providers retrieve and send back a RelayState URL parameter from Resource Providers (such as G Suite). G Suite provides this value to the Identity Provider in the SAML Request, and the exact contents can differ in every login. For authentication to complete successfully, the exact RelayState must be returned in the SAML Response. According to the SAML standard specification, your Identity Provider should not modify the RelayState during the login flow.
This error indicates that the destination or audience elements in the SAML assertion contained invalid information or were empty. Both elements must be included in the SAML assertion. Check the following table for descriptions and examples for each element.
In this article I present a few simple examples of managing SAML 2.0 content using the OpenSAML library, version 2.2.3. I have found OpenSAML to be an excellent tool, but lacking somewhat for documentation and especially for code examples. I hope that the code here will be helpful: it is beginner-level stuff, and the aim is that it will clarify some of the fundamental practices for those just getting familiar with the library.
All code here is drawn from my course, Securing Java Web Services. in which OpenSAML -- and SAML generally -- are part of a bigger picture that includes XML cryptography, WS-Security, WS-SecurityPolicy, and other standards, as well as other tools including Metro/WSIT and OpenSSO.
Having explained what it is, I want also to be clear about what this article is not. It's not a tutorial, either on SAML or OpenSAML. I also am not claiming any sort of blessing from the OpenSAML project or its authors; for all I know they would develop splitting headaches upon seeing the code here.
And, to that point: not all the code here takes full advantage of all the tools available within OpenSAML. One item that comes to mind is that I use classic JAXP code to conjure a DOM document builder; OpenSAML implements a parser pool, and for most purposes that will be a better choice.
You get the idea. Mostly, as I've been craving examples along these lines and had to build them myself, I thought they might prove useful to others. It's no more or less than that.Getting the Code
Okay, let's get to it: to see the source files, build them, and test them, download one of the following ZIP files, and unpack it anywhere you like:100k) with just the source files, make files, and javadocs -- choose this only if you already have OpenSAML 2.2.3, and the necessary SLF JAR(s) that are required at runtime, and are prepared to copy JAR files into place to get the build working; or if you just want a look at the code and don't need to build it
10meg) that includes the required OpenSAML JARs in the right places for the build -- I recommend this in spite of the more significant download time, as it builds and runs right out of the box
You'll see a simple tree /OpenSAML that forms a small Java code project, including an Ant build.xml. Source files are found in the src directory, and javadocs in doc. If you chose the larger bundle to download, then the required OpenSAML JARs are already in place in lib. and the Xerces parser and supporting JARs (on which OpenSAML insists at runtime) is in endorsed .
If you got the little archive, copy the following files from your OpenSAML distribution:
In any case, you'll also see several subdirectories with example SAML content (which was produced using these Java applications).
Also, to build and run, the example code requires two supporting tools:
Be sure that your executable path includes the Java bin directory and the Ant bin directory.
You can then build the code project by running ant from the OpenSAML directory. You'll see a new build directory with class files.Code Design
A handful of Java classes in package cc.saml are organized in an inheritance hierarchy, and each of these has a main method for testing out some part of the code:
There is also a SAMLSignature.java. which we don't discuss further in this article because it isn't really an OpenSAML example. It's just DOM code that signs a SAML assertion, request, or response, and can verify a signature and check a pre-set trust store as well. It uses the SAML.java utility, but only for testing purposes via its own main method.
Packages cc.security and cc.xml provide support for, respectively: reading keystores and trust stores, and pretty-printing XML output.
We've not bundled the javadoc, but you can create it by running makejavadoc.bat (or run similar commands on non-Windows systems). This will put the docs in a subdirectory doc .General Utilities
cc.saml.SAML can serve a few possible purposes, and we'll look at the code in sections accordingly. Skip over the main method for now, and we'll come back to it when we're ready to test the code. First, it wraps the default bootstrapping of OpenSAML such that any load of this class assures that OpenSAML is ready to roll. See the static initializer block for this, and also notice that it initializes an ID generator.
Instances of this class can be used to build new SAML content, and such instances can be created with an issuer URL that will automatically be used in many of the utility methods. See the constructors for this; they also initialize a private document builder. (See the earlier note about the option of using an OpenSAML parser pool.)
The next method is one of the most generally useful: it's a shortcut to create XML objects using the XML toolkit embedded in OpenSAML. This system is robust, flexible, and extensible; it is also a bit of work to use for most purposes, and so the create method simplifies the programming model in a small way, by assuming one QName for the schema type and resulting element, and by getting the builder and creating the object, all in one swoop:
We'll see usage examples very soon.
The next set of methods wraps uses of the toolkit's marshaller and unmarshaller system, again wrapping the behavior of finding the right marshaller/unmarshaller for a given object or element, and doing the requested marshalling/unmarshalling. In the order found in the source code these are addToElement. asDOMDocument. printToFile. fromElement. and readFromFile. Each is useful for a slightly different situation.
Next are a set of factory methods for progressively larger chunks of SAML content, starting with a method to create an <Issuer> element from the issuer URL with which the utility object was created. Here too is our first example of creating new XMLObjects from scratch, using the create method:
The next method creates a complete subject structure, based on a name, name format, and confirmation method. Only the name is required; the confirmation method can be null, sender-vouches, or bearer, while HOK would be a bad idea since this method isn't built to take the necessary key information and pack it into the XML structure. In terms of technique, createSubject doesn't do anything we haven't already seen: it's mostly creating new XMLObjects of specific types and then calling mutators on those objects to assemble the tree. (OpenSAML's design is really nice and intuitive here, and if you know the SAML structure you want to assemble, it's usually quick work to find the right methods and arguments to put it together.)
The next set of methods create assertions and responses, given various pieces and parts. More of the same techniques here, really, though the number of overloads of createResponse might be a surprise. Some of these, keep in mind, are for producing error responses, and then some will work with an inResponseTo parameter and bake that into the XML structure.
Finally there's a set of methods that create specific assertion types. These are narrower in their purpose (and are aimed at specific lab exercises in the training course whence this code comes). createAttributeAssertion can either build a list of attributes from a simple name-value map, or can leave this list empty to be built using the addAttribute helper method. Note the code comments in this latter method that explain the use of the XSAny type in lieu of AttributeValue .
We can test out some of these methods from this class' main method. Try the following, some of which uses prepared files in the Assertion subdirectory:
Two final tests drive the createAuthnAssertion and createAttributeAssertion methods; they are not shown in the usage statement. Each involves some hard-coded values and generates a pre-defined assertion directly to the console:Reading and Writing Assertions
cc.saml.SAMLAssertion extends cc.saml.SAML. but in practice it doesn't use much of the base class code, instead offering individual methods for reading and writing assertions that do the same sorts of things, but that are more self-contained, and possibly more readable as start-to-finish examples of building or parsing SAML structures. They do rely on the base class for readFromFile and printToFile methods.
The createXXXAssertion methods don't do anything we haven't already seen. But the reading methods are new, if not all that surprising. Consider readAuthenticationAssertion. which expects the contents of a given file to be an authentication assertion and simply reads out the name, name format, and authentication context classes that it finds there:
Note that we get the character content of an Issuer by calling getValue. which is actually a method on the base type NameIDType. Also, while most assertions will have but one statement, it's legal to have several, and so OpenSAML follows the assertions schema by exposing a List<Statement>. and we loop over that, looking for an instance of the type that we're actually prepared to parse.Writing Queries and Responses
cc.saml.SAMLProtocol extends cc.saml.SAMLAssertion. and has its own methods for producing canned queries and responses. The SAML query model being distinct from the assertions model, this class produces its own queries by more or less the same approach as the createXXX methods in the base class.
For responses, we do a couple new things. First, we have a single method printResponse. which just wraps a given assertion; this is in keeping with the SAML response model, which unlike the query model doesn't try to invent much new content but just serves as a vehicle for assertions traveling from an asserting to a relying party. Second, the method allows for a filename to be given, which it will parse as representing a prior query. It will loosely simulate the actual process of responding to that query, by grabbing the query ID and making it the InResponseTo value.The SOAP Binding
cc.saml.SAMLBinding then extends SAMLProtocol in one simple way: it wraps the queries and responses in SOAP envelopes and bodies. Not much here is all that surprising; we even do the same response simulation, now expecting to encounter a SOAP envelope when reading into the given file for a query ID.
I hope this has been helpful. With any questions, suggestions, criticism, or other feedback, please write to me at email@example.com .