In this post we would talk about a User’s identity in LC once he has authenticated.
Any service operation exposed by a DSC can be invoked either anonymously or after performing authentication. Authentication can be performed in two ways
h3. Implicit authentication
Implicitly via creation of @ServiceClientFactory@ – When you create a @ServiceClientFactory@ instance you can provide the credentials through the poperties. This information is later used by the DSC container for authentication purpose. Here you are limited to username/password based authentication.
Properties props = new Properties(); props.setProperty("DSC_DEFAULT_EJB_ENDPOINT", "jnp://localhost:1099"); props.setProperty("DSC_TRANSPORT_PROTOCOL","EJB"); props.setProperty("DSC_SERVER_TYPE", "JBoss"); //Here we are setting the credentials which would later be used while invoking the services props.setProperty("DSC_CREDENTIAL_USERNAME", "administrator"); props.setProperty("DSC_CREDENTIAL_PASSWORD", "password"); //Create a ServiceClientFactory object ServiceClientFactory myFactory = ServiceClientFactory.createInstance(props);
h3. Explicit authentication
Explicitly via obtaining an @AuthResult@ by authenticating using one of the methods exposed by @AuthenticationManager@. The @AuthenticationManagerServiceClient@ implements this interface and you would use it for performing authentication. It provides methods for
* Username/password based authentication
* Certificate based authentication
* Impersonating a user
Apart from that there are overloaded methods for performing __domain based authentication__. We would discuss these modes in later parts of this series. For now lets authenticate a user
... //Create a ServiceClientFactory object ServiceClientFactory myFactory = ServiceClientFactory.createInstance(props); AuthenticationManagerServiceClient authClient = new AuthenticationManagerServiceClient(myFactory); //Now use the client to perform authentication using the username and password AuthResult authResult = authClient.authenticate(username, password.getBytes());
Once you authenticate you get an “@AuthResult@”:http://livedocs.adobe.com/livecycle/8.2/programLC/programmer/javadoc/com/adobe/idp/um/api/infomodel/AuthResult.html@. It contains an @assertion@ which acts as a sort of security token in LiveCycle. If this token is passed through any of the supported remote access mechanism then LiveCycle would use it for authentication purpose. Before examining the assertion contents lets see how it can be used
//Create an instance of com.adobe.idp.Context Context context = new Context(); context.initPrincipal(authResult); //Set the context in your ServiceClientFactory instance. myFactory.setContext(context);
Here we create a @Context@ and initialized it with the @AuthResult@ obtained previously. This context is then set in the @ServiceClientFactory@ instance. Now any call made using this factory instance would carry the context and at server side the user’s identity would be established using this context object. At first instance it would look more complicated than the implicit authentication but soon we would see how it can be more useful for us.
h3. SAML Assertion
The @assertion@ which is present in the @AuthResult@ object is actually a serialized SAML assertion. As a user you need not have to interpret its content. You can treat it as an opaque object and just pass it back to LiveCycle for each invocation.
<Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" AssertionID="fd4bd0c87302780e0d9bbfa8726d5bc0" IssueInstant="2008-04-17T13:47:00.720Z" Issuer="LiveCycle" MajorVersion="1" MinorVersion="1"> <Conditions NotBefore="2008-04-17T13:47:00.720Z" NotOnOrAfter="2008-04-17T15:47:00.720Z"> </Conditions> <AuthenticationStatement AuthenticationInstant="2008-04-17T13:47:00.720Z" AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:unspecified"> <Subject> <NameIdentifier NameQualifier="DefaultDom">administrator</NameIdentifier> <SubjectConfirmation> <ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</ConfirmationMethod> </SubjectConfirmation> </Subject> </AuthenticationStatement> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"></ds:SignatureMethod> <ds:Reference URI="#fd4bd0c87302780e0d9bbfa8726d5bc0"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="code ds kind rw saml samlp typens #default"> </ec:InclusiveNamespaces> </ds:Transform> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod> <ds:DigestValue>hVrtqjWr+VzaVUIpQx0YI9lIjaY=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>UMbBb+cUcPtcWDCIhXes4n4FxfU=</ds:SignatureValue> </ds:Signature> </Assertion>
Following are the important aspects for this assertion
* It is valid for certain duration – By default for 2 hrs
* It is issued for a particular user – Here its for @administrator@
* It is digitally signed. So any modification done to it would break the signature – This is an imporatant point. This assertion content is protected by a xml signature. So any modification done to it would make it invalid.
* It can be presented to LiveCycle as a token of user’s identity similar to username,password
This assertion is confirming to the “SAML 1.0”:http://en.wikipedia.org/wiki/SAML specification. As it is xml based you can also pass it as a part of the Web Service Security Header.
h3. Benefits of explicit authentication
Explicit authentication is beneficial in following ways
Firstly you can use it to authenticate using more secure ways like certificates – How would be part of some future post
Secondly you can use it to invoke the LiveCycle services in a more secure way – Lets say you are creating a custom application which invokes the services exposed by LiveCycle. In that a typical requirement is that User A login to the system. Here he authenticates say by providing his credentials. Now at later stage you want to invoke some LiveCycle service on behalf of this user. For this you have following options
* Store the user’s credential locally and make a call to LiveCycle using them – This has an issue that you are holding the user’s credentials in memory. Which is not a good practice in terms of security. If you pass these credentials *everytime* to the LiveCycle server then you risk them being exposed. You can make it secure by using a secure way to communicate
* Authenticate against the LiveCycle server and store the @assertion@ obtained. Reuse this assertion everytime you communicate with the server. This way even if someone obtains this assertion he can only use it for a certain period time (before the assertion expires). This provides a better level of security than the previous option
* Have a trust relationship with the LiveCycle server and obtain an assertion on behalf of that user. This is called as impersonation and we would talk about it in later part of the series
Hence the SAML assertion stored in @AuthResult@ acts as a security token for a user in LiveCycle. In later part of this series we would see how it can be passed as a part of WS-Security header to impersonate a user. The next post in series would talk of one of the SSO mechanism supported by LiveCycle which is HTTP Header based SSO.
fn1. Using SAML assertion in web service authentication is explained at “Using SAML based authentication”:http://livedocs.adobe.com/livecycle/8.2/programLC/programmer/help/001503.html at LiveDocs