Integrating JSF web application with Openam using Spring Saml Extension.
Or Single Sign on With JSF
Or Java Single Sign on
Or Integrate Single sign on Using Spring SAML Extension.
As discussed in my earlier article we can have an different set ups
Case1: SP (Your Java Web app) <===> IDP Proxy <=====> (IDP1, IDP2.....)
or if you just have one IDP then obviously there is no point in using IDP proxy in which case you setup will be like
Case2: SP (Your Java Web app or Openam generated Fedlet) <=====> (IDP)
So depending on CASE1 or CASE2 you will generate Fedlet on IDP Proxy or IDP respectively.
So What is Fedlet ?
- Well Fedlet is small web based openam client that can be generated once you install openam. This web application will have few jsps and will help you to test your openam setup and it has enough code to send SAML requests and receive SAML Responses
Now lets get in to details as how to plugin in your JSF webapp with Openam ?
1. Lets say you have JSF webapp with a simple page with following url
http://abc.com:8080/TST/landingPage.jsf
STEP1: Login to openam (IDP Proxy if its CASE1 else IDP if its CASE2) and click on generate the Fedlet. When you generate the Fedlet choose your
STEP2: Now in fedlet war there is a "conf" directory with 4 xmls
i.e
Copy content from idp.xml starting from to sp.xml.
<KeyDescriptor use="signing">
STEP3: We can use the idp.xml that’s found in Fedlet/conf directory. This is the xml that
will allow our JSF application to send SAML request to Openam.
STEP4:. We can use the sp.xml that’s found in the Fedlet/conf directory. This will have information for service provider (TST JSF application ).There are few changes we need to make here in order for the response url’s to be intercepted by Spring SAML extension filters.
e.g. I generated Fedlet for entity id http://abc.com:8080/TST and here is how the changes look in sp.xml.
STEP5: Change AssertionConsumerService (ACS) URL’S in sp.xml
FROM:
Here the realm I used for testing was "realm001" in case you have used root realm then your url will be saml/SSO/alias/sp
STEP6:
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</NameIDFormat>
-->
STEP7: In case you want your requests signed and assertions signed in sp.xml set
I had authentication turned and use a sample cert. For testing you can use the test cert provided by openam . Never use this "test" cert in a production environment.
STEP10:
Now in openam IDP (If you ar using proxy go to proxy) Under Federation > entity providers > your SP (ie. http://abc.com:8080/TST) and you should see signing and encryption with value of the certs.
NOTE:This note is applicable only if you are using openam as a proxy. IGNORE THIS is you are using openam as IDP.
Login in to Openam Proxy >Go to Federation > Entity Providers (http://abc.com:8080/TST) -- Basically the remote Service provider )> SP> Advanced > IDP Proxy and make sure proxy count is set to 1 (i.e number one) and proxy url is set to your IDP url (yes the proxy url is idp url).The proxy uses this value to send request to IDP.
STEP11:
Verify that the acs url you have added in sp.xml is present in openam.
Login to IDP ( if you are using proxy login into openam proxy)> Click on Federation tab
Go to Entity providers section and click on the URL that we used to generate Fedlet (In this case we used http://abc.com:8080/TST )
While on SP tab go to “Services” screen scroll down to the section which has“Assertion consumer Service”
From: http://abc.com:8080/TST/fedletapplication
To: http://abc.com:8080/TST/saml/SSO/alias/realm001/sp
NOTE: I did not use single logout service. In case you want change the logout URL’s on this page. (Locally I changed all logout urls to “TST/saml/SingleLogout/alias/realm001/sp”)
Congratulations !!!! Your configuration to plugin SP with openam is complete.
We now need to focus on Spring code changes on you JSF web app.
Spring SAML extension integration with your
JSF application
or spring security saml tutorial
or spring security saml tutorial
or spring security jsf example
Here I will brief you about how to plugin spring code with your JSF application.
I always had a question as why spring SAML uses the filters with urls patterns predefined.
<security:filter-chain pattern="/saml/login/**" filters="samlEntryPoint"/>
<security:filter-chain pattern="/saml/logout/**" filters="samlLogoutFilter"/>
//We dont need metadata to be displayed comment this.
<!-- <security:filter-chain pattern="/saml/metadata/**" filters="metadataDisplayFilter"/> -->
<security:filter-chain pattern="/saml/SSO/**" filters="samlWebSSOProcessingFilter"/>
<security:filter-chain pattern="/saml/SSOHoK/**" filters="samlWebSSOHoKProcessingFilter"/>
<security:filter-chain pattern="/saml/SingleLogout/**" filters="samlLogoutProcessingFilter"/>
//We dont need Springdiscovery as we have one idp.So commented it.
<!-- <security:filter-chain pattern="/saml/discovery/**" filters="samlIDPDiscovery"/> -->
This is how the spring filters will intercepts the urls.
Don't mess with this patterns.Thats the reason we changed the ACS and logout urls as mentioned in STEP5.
Once you have this rams-applicationContext-security.xml all it needs is the below files in your path or classpath. (See the rams-applicationContext-security.xml)
You can download the below code from
https://sites.google.com/site/reddymails/Home/SAMLUserDetailsServiceImpl.java?attredirects=0&d=1
So now you have spring security xml and the code to parse SAML repsonse ready. Just plugin. The srping xml in to your web.xml. Since the code above parsed the roles the user is we need to use those roles to enable or disable feature sin JSF pages which I will explain shortly.
In your webxml
I have attached the sample web.xml
https://sites.google.com/site/reddymails/Home/web.xml?attredirects=0&d=1
How do to we read the User name from Spring security context ?
I did some reading and here is code that saves you a day :)
The assumption is that your are sending "Username" as one of the attributes in SAML response.
Once you parse store it in Httpsession that way you don't run this code multiple times for same user.
public static final String USER_ID = "UserName";
public String getCurentUserName(){
Just follow these steps
<!-- To add Security tag tld to JSF you can read more at.
more at
http://static.springsource.org/spring-webflow/docs/2.2.x/reference/html/ch13s09.html
http://doanduyhai.wordpress.com/2012/02/26/spring-security-part-v-security-tags/
-->
Assuuming you have configured the Spring security tld now you can add name space in JSF page as shown below.
xmlns:security="http://www.springframework.org/security/tags"
And inside your JSF page now you can use tags like
rendered="#{security:areAnyGranted('FILE_READ_GROUP,FILE_EDIT_GROUP')}">
rendered="#security:areAllGranted('FILE_ALL_OPERATIONS_GROUP)"
disabled="#{security:areNotGranted('FILE_READ_GROUP)}">
Where FILE_READ_GROUP, FILE_ALL_OPERATIONS are Active directory groups the current user is in.
Hope this article take some pain of integrating openam with Spring SAML and also helps you in Spring Security integration with JSF application.
Or Single Sign on With JSF
Or Java Single Sign on
Or Integrate Single sign on Using Spring SAML Extension.
Or Integrating Spring SAML Extension with Openam (or any SAML provider).
Or Spring and Open AM security
Or Single sign on in JSF or Single Sign on with JSF
Or Spring security with openam
Or Spring and Open AM security
Or Single sign on in JSF or Single Sign on with JSF
Or Spring security with openam
As discussed in my earlier article we can have an different set ups
Case1: SP (Your Java Web app) <===> IDP Proxy <=====> (IDP1, IDP2.....)
or if you just have one IDP then obviously there is no point in using IDP proxy in which case you setup will be like
Case2: SP (Your Java Web app or Openam generated Fedlet) <=====> (IDP)
So depending on CASE1 or CASE2 you will generate Fedlet on IDP Proxy or IDP respectively.
So What is Fedlet ?
- Well Fedlet is small web based openam client that can be generated once you install openam. This web application will have few jsps and will help you to test your openam setup and it has enough code to send SAML requests and receive SAML Responses
Now lets get in to details as how to plugin in your JSF webapp with Openam ?
1. Lets say you have JSF webapp with a simple page with following url
http://abc.com:8080/TST/landingPage.jsf
STEP1: Login to openam (IDP Proxy if its CASE1 else IDP if its CASE2) and click on generate the Fedlet. When you generate the Fedlet choose your
- Realm (You can use root "/" realm, but better use different realm. I used realm001)
- Circle of Trust : Let say "Cot1"
- Identityprovider: (The url of your openam Identity provider will appear in drop down)
- Fedlet Name :http://abc.com:8080/TST (Can be anything but I just use url)
- Fedlet destination url : http://abc.com:8080/TST
STEP2: Now in fedlet war there is a "conf" directory with 4 xmls
- sp.xml
- sp-extended.xml
- idp.xml
- idp-extended.xml
i.e
Copy content from idp.xml starting from to sp.xml.
<KeyDescriptor use="signing">
……..
</KeyDescriptor>
<KeyDescriptor
use="encryption">
…….
</KeyDescriptor>
e.g. I generated Fedlet for entity id http://abc.com:8080/TST and here is how the changes look in sp.xml.
Comment the following in sp.xml
FROM:
<!-- Default Fedlet generated Log out
Urls.
<SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="http://abc.com:8080/TST/fedletSloRedirect"
ResponseLocation="http://abc.com:8080/TST/fedletSloRedirect" />
<SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://abc.com:8080/TST/fedletSloPOST"
ResponseLocation="http://abc.com:8080/TST/fedletSloPOST" />
<SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://abc.com:8080/TST/fedletSloSoap" />
-->
Change the above
Single logout service url’s to as shown below (Basically in every URL we added "/saml/SingleLogout/alias/realm001/sp" ) where realm001 is the realm and
“/sp” is the service provider url we choose when we created openam.Be extra
careful when replacing this url to have correct realm name.
In case you have used root realm then you can replace the below urls with /saml/SingleLogout/alias/sp
TO: (Within sp.xml)
<SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="http://abc.com:8080/TST/saml/SingleLogout/alias/realm001/sp"
ResponseLocation="http://abc.com:8080/TST/saml/SingleLogout/alias/realm001/sp" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://abc.com:8080/TST/saml/SingleLogout/alias/realm001/sp"
ResponseLocation="http://abc.com:8080/TST/saml/SingleLogout/alias/realm001/sp"
/>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://abc.com:8080/TST/saml/SingleLogout/alias/realm001/sp" />
FROM:
<!-- Default Fedlet
generated
<AssertionConsumerService
isDefault="true"
index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://abc.com:8080/TST/fedletapplication"
/>
<AssertionConsumerService
index="1"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="http://abc.com:8080/TST/fedletapplication"
/>
-->
TO:
<AssertionConsumerService isDefault="true"
index="0" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://abc.com:8080/TST/saml/SSO/alias/realm001/sp" />
<AssertionConsumerService index="1"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="http://abc.com:8080/TST/saml/SSO/alias/realm001/sp" />
Here the realm I used for testing was "realm001" in case you have used root realm then your url will be saml/SSO/alias/sp
STEP6:
Please comment the following name id formats in sp.xml
and leave transient name id format.
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<!-- We don't need
this as we use just transient
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat><NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</NameIDFormat>
-->
STEP7: In case you want your requests signed and assertions signed in sp.xml set
AuthnRequestsSigned="true" WantAssertionsSigned="true"
I had authentication turned and use a sample cert. For testing you can use the test cert provided by openam . Never use this "test" cert in a production environment.
STEP8:
Edit the
sp-extended.xml by fixing metalias to include realm name and also verify the
following atttiburtes
These 3 tags will have values only if you have openam proxy. If you have just openam IDP and your SP is talking to IDP directly do no set values for these tags.
<Attribute name="enableIDPProxy">
<Value>true</Value>
</Attribute>
<Attribute name="idpProxyCount">
<Value>1</Value></Attribute>
<Attribute name="idpProxyList">
<Value>http://idp.abc.com:8080/openam</Value> //Strangely you use the IDP url though the tag says proxy
</Attribute>
//Set the cert names for signing and encryption.
<Attribute name="signingCertAlias">
<Value>test</Value> //In production you can use separate cert for signing and encryption
</Attribute>
<Attribute name="encryptionCertAlias">
<Value>test</Value> //In production you can use separate cert for signing and encryption
</Attribute>
Change All want*Encrypted properties (Only if you want everything encrypted. I did it when I tested)
<Attribute
name="wantAttributeEncrypted">
<Value>true</Value>
</Attribute>
<Attribute name="wantAssertionEncrypted">
<Value>true</Value>
</Attribute>
<Attribute name="wantNameIDEncrypted">
<Value>true</Value>
</Attribute>
<Attribute
name="wantAssertionEncrypted">
<Value>true</Value>
</Attribute>
All want*Signed properties (Only if you want everything Signed. I did it when I tested)
<Attribute name="wantPOSTResponseSigned">
<Value>true</Value>
</Attribute>
<Attribute
name="wantArtifactResponseSigned">
<Value>true</Value>
</Attribute>
<Attribute
name="wantLogoutRequestSigned">
<Value>true</Value>
</Attribute>
<Attribute
name="wantLogoutResponseSigned">
<Value>true</Value>
</Attribute>
<Attribute
name="wantMNIRequestSigned">
<Value>true</Value>
</Attribute>
<Attribute
name="wantMNIResponseSigned">
<Value>true</Value>
</Attribute>
In sp-extended.xml add realm name (In case you are using root you dont need to change anything just use the existing values)
metaAlias="/realm001/sp"
metaAlias="/realm001/attrQuery"
metaAlias="/realm001/pep"
In idp-extended.xml add realm name
metaAlias="/realm001/idp"
metaAlias="/realm001/sp"
In sp-extended.xml set
hosted="0" (This tells openam that the entity you are trying to
upload (i.e. your SP) is remote and not locally hosted on Openam itself)
STEP 9:
Since we changed assertion consumer url in the sp.xml
we need to update this url in IDP proxy, as IDP proxy will have Feldet url which we have changed to keep Spring SAML
extension happy.
2. Navigate
to Federation > entity providers.
3. Delete
the service provider . ie. Entry which we added to generate Fedlet for our JSF app URL (eg: http://abc.com:8080/TST)
4. Make
sure the same entity is also removed in Circle of Trust
5. Click
on import entity and select sp.xml and
sp-extended.xml respectively
STEP10:
Now in openam IDP (If you ar using proxy go to proxy) Under Federation > entity providers > your SP (ie. http://abc.com:8080/TST) and you should see signing and encryption with value of the certs.
NOTE:This note is applicable only if you are using openam as a proxy. IGNORE THIS is you are using openam as IDP.
Login in to Openam Proxy >Go to Federation > Entity Providers (http://abc.com:8080/TST) -- Basically the remote Service provider )> SP> Advanced > IDP Proxy and make sure proxy count is set to 1 (i.e number one) and proxy url is set to your IDP url (yes the proxy url is idp url).The proxy uses this value to send request to IDP.
STEP11:
Verify that the acs url you have added in sp.xml is present in openam.
Login to IDP ( if you are using proxy login into openam proxy)> Click on Federation tab
Go to Entity providers section and click on the URL that we used to generate Fedlet (In this case we used http://abc.com:8080/TST )
While on SP tab go to “Services” screen scroll down to the section which has“Assertion consumer Service”
From: http://abc.com:8080/TST/fedletapplication
To: http://abc.com:8080/TST/saml/SSO/alias/realm001/sp
NOTE: I did not use single logout service. In case you want change the logout URL’s on this page. (Locally I changed all logout urls to “TST/saml/SingleLogout/alias/realm001/sp”)
Congratulations !!!! Your configuration to plugin SP with openam is complete.
We now need to focus on Spring code changes on you JSF web app.
or spring security saml tutorial
or spring security saml tutorial
or spring security jsf example
Here I will brief you about how to plugin spring code with your JSF application.
Please download the sample web application provided by
Vladmir Schaufer and explore a bit
You should be able to download
"spring-security-saml-1.0.0.RC2-dist.zip" or which ever is the most
recent one. Use maven and do a build and you will get a deploy-able war file
To run this example please read the java doc provided by
the author
Now in the zip file
spring-security-saml-1.0.0.RC2\sample\src\main\resources\security\securityContext.xml
Let’s use this sample spring security xml file as a
starting point for integrating our application.
If you read the documentation provided by Vladmir
Schaufer you will now be familiar with the Spring security xml. However to make
it work for our web app I really had to comment quite a few things.
So here is the Original Spring Security xml file
(original-securityContext.xml)
Here is the modified file (rams-applicationContext-security.xml).This file has comments in
each section indicating why I commented a xml entry. You can download the
modified xml file from below url
<security:filter-chain pattern="/saml/login/**" filters="samlEntryPoint"/>
<security:filter-chain pattern="/saml/logout/**" filters="samlLogoutFilter"/>
//We dont need metadata to be displayed comment this.
<!-- <security:filter-chain pattern="/saml/metadata/**" filters="metadataDisplayFilter"/> -->
<security:filter-chain pattern="/saml/SSO/**" filters="samlWebSSOProcessingFilter"/>
<security:filter-chain pattern="/saml/SSOHoK/**" filters="samlWebSSOHoKProcessingFilter"/>
<security:filter-chain pattern="/saml/SingleLogout/**" filters="samlLogoutProcessingFilter"/>
//We dont need Springdiscovery as we have one idp.So commented it.
<!-- <security:filter-chain pattern="/saml/discovery/**" filters="samlIDPDiscovery"/> -->
This is how the spring filters will intercepts the urls.
Don't mess with this patterns.Thats the reason we changed the ACS and logout urls as mentioned in STEP5.
Once you have this rams-applicationContext-security.xml all it needs is the below files in your path or classpath. (See the rams-applicationContext-security.xml)
- sp.xml
- idp.xml
- java keystore with name keystore.jks (I copied from openam for testing)- I will add one article on keystores later.
- Your openam IDP URL (I used url as http://idp.abc.com:8080/openam
Ok now if you see my modified spring xml the only code you
need to write is the class com.tst.web.security.SAMLUserDetailsServiceImpl.java
which
is implementation for org.springframework.security.saml.userdetails.SAMLUserDetailsService
I will add the sample code here. I had integrated openam with Active directory and had configured openam to retrun the following attributes.
"ActiveDirGroups" and "UserName"
So when Openam sent the SAML Response it was sending these attributes. So we need to parse and build UserDetails object as below.
You can download the below code from
https://sites.google.com/site/reddymails/Home/SAMLUserDetailsServiceImpl.java?attredirects=0&d=1
package com.tst.web.security;package com.tst.web.security; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.log4j.xml.DOMConfigurator; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.saml.SAMLCredential; import org.springframework.security.saml.userdetails.SAMLUserDetailsService; /** * @author twreddy The SAMLUserDetailsService interface is similar to * UserDetailsService with difference that SAML data is used in order * obtain information about the user. So inspect the SAMLCredential * object and return such a data in a form of application specific * UserDetails object */ public class SAMLUserDetailsServiceImpl implements SAMLUserDetailsService { // SAML Response PAY load attributes. // Some of the attributes we get back in SAML RESPONSE // We mapped this in openam so it should be there in SAML response. public static final String GROUP_MEMBER_ATTR_NAME = "ActiveDirGroups"; public static final String USER_ID = "UserName"; private static Logger logger = LogManager.getLogger(FMSAMLUserDetailsService.class); /* * This is the method spring will invoke. */ public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException { logger = getLOSLogger(this); // Want to see if this object is null ... logger.info("credential=" + credential); if (credential != null) { String samlCredentilAsStr = ""; if (logger.isDebugEnabled()) { // I dont want read this object every time. // Will do only of we have enabled debugging. samlCredentilAsStr = ToStringBuilder.reflectionToString(credential); logger.debug("samlCredentilAsStr=" + samlCredentilAsStr); } String userId = getUserId(credential); logger.debug("userId=" + userId); UserDetails userDetails = getUserWithRoles(credential, userId); return userDetails; } throw new UsernameNotFoundException( "SAMLCredential is null. Cant extract " + GROUP_MEMBER_ATTR_NAME + " and or " + USER_ID + " in Saml Response. " ); } /** * Extracts all groups and creates a UserDetail object * and returns it. * @param credential * @param userId * @return */ private UserDetails getUserWithRoles(SAMLCredential credential, String userId) { UserDetails userDetails = null; // We dont have access to password ?? // So using name as password for now. List<SimpleGrantedAuthority> grantedRolesList = getGrantedAuthorities( GROUP_MEMBER_ATTR_NAME, credential); logger.info(" roles For :" + userId + " grantedRolesList=" + grantedRolesList); // This object needs userid and password. I dont have password // Faking it with user id. Password may really be needed when // you try to Authenticate this object using authManager. userDetails = new User(userId, userId, grantedRolesList); return userDetails; } /** * Reads the Attributes that are in SAML Pay load response. Our Group Meber * ship Is a long String: * CN=FILE_EDIT_USER,OU=Devtest,DC= We need to get only Group name which FILE_EDIT_USER * * @param name * @param credential * @return */ private List<SimpleGrantedAuthority> getGrantedAuthorities( final String name, final SAMLCredential credential) { List<SimpleGrantedAuthority> grantedRolesList = new ArrayList<SimpleGrantedAuthority>(); List<String> attrValueList = getAttributeValue(name,credential); for (String attrValue : attrValueList) { if (attrValue != null) { // All we are doing here is extracting the first part in the // group membership // eg: // CN=FILE_EDIT_USER,OU=Devtest,DC= We need to get only Group name which FILE_EDIT_USER logger.debug(" Raw Attribute=" + attrValue); String roleName = attrValue.split(",")[0].split("=")[1]; // We need just "FILE_EDIT_USER" logger.debug(" Cleaned up group name=" + roleName); logger.debug(" group name with case changed=" + roleName); SimpleGrantedAuthority grantedAuthority = new SimpleGrantedAuthority( roleName); grantedRolesList.add(grantedAuthority); } else { logger.warn("One of the Group attrValue was null."); } } return grantedRolesList; } /** * Given SAMLCredential inspects the object and returns the values * for give attribute name. * @param name * @param credential * @return */ public static List<String> getAttributeValue(final String name, final SAMLCredential credential) { List<String> attrValList = new ArrayList<String>(); Attribute attribute = credential.getAttributeByName(name); logger.debug(" Parsing name=" + name + " in SAMLCredential"); if (attribute != null) { List<XMLObject> attributes = attribute.getAttributeValues(); if ((attributes != null) && (attributes.size() > 0)) { for (XMLObject object : attributes) { XSString attrb = (XSString) object; String attrValue = attrb.getValue(); if (attrValue != null) { // clean unwanted strings here in the role logger.debug("name=" + name + " attrValue=" + attrValue); attrValList.add(attrValue); } } } } return attrValList; } /** * Reads the uid from SAML credential if present * @param credential * @return */ public static String getUserId(SAMLCredential credential) { String userId = null; List<String> userIdValueList = getAttributeValue(USER_ID, credential); logger.debug(" USER_ID="+ USER_ID +" userIdValueList=" + userIdValueList); if (userIdValueList.size() > 0) { userId = userIdValueList.get(0); } return userId; } }
So now you have spring security xml and the code to parse SAML repsonse ready. Just plugin. The srping xml in to your web.xml. Since the code above parsed the roles the user is we need to use those roles to enable or disable feature sin JSF pages which I will explain shortly.
In your webxml
I have attached the sample web.xml
https://sites.google.com/site/reddymails/Home/web.xml?attredirects=0&d=1
<listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/rams-applicationContext-security.xml </param-value> </context-param> <!-- Spring Security --> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
How do to we read the User name from Spring security context ?
I did some reading and here is code that saves you a day :)
The assumption is that your are sending "Username" as one of the attributes in SAML response.
Once you parse store it in Httpsession that way you don't run this code multiple times for same user.
public static final String USER_ID = "UserName";
public String getCurentUserName(){
// Read from Security context as SAML Pay loads gets your name. Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); SAMLCredential samlCredential = (SAMLCredential) authentication.getCredentials(); String userName = getUserId(samlCredential); return userName; } /** * Reads the uid from SAML credential if present * @param credential * @return */ public static String getUserId(SAMLCredential credential) { String userId = null; List<String> userIdValueList = getAttributeValue(USER_ID, credential); logger.debug(" USER_ID="+ USER_ID +" userIdValueList=" + userIdValueList); if (userIdValueList.size() > 0) { userId = userIdValueList.get(0); } return userId; }Once you have all this code you can plugin spring role based security if you need.With this you are done with single sign on. Howevere If you want to use Spring Security you can read th below few lines
Just follow these steps
<!-- To add Security tag tld to JSF you can read more at.
more at
http://static.springsource.org/spring-webflow/docs/2.2.x/reference/html/ch13s09.html
http://doanduyhai.wordpress.com/2012/02/26/spring-security-part-v-security-tags/
-->
Assuuming you have configured the Spring security tld now you can add name space in JSF page as shown below.
xmlns:security="http://www.springframework.org/security/tags"
And inside your JSF page now you can use tags like
rendered="#{security:areAnyGranted('FILE_READ_GROUP,FILE_EDIT_GROUP')}">
rendered="#security:areAllGranted('FILE_ALL_OPERATIONS_GROUP)"
disabled="#{security:areNotGranted('FILE_READ_GROUP)}">
Where FILE_READ_GROUP, FILE_ALL_OPERATIONS are Active directory groups the current user is in.
Hope this article take some pain of integrating openam with Spring SAML and also helps you in Spring Security integration with JSF application.
NOTE:If your web application is .net based you can try using .net fedelt
provided by openam.I don't have much knowledge to comment on .net.
If you like my articles or have some suggestion feel free to drop a message.
Hi
ReplyDeleteOpenAM
OpenAM 11.0.0 (2013-November-08 10:40). I followed the steps provided by you.
It's not working. I am using default releam. Deployed fedlet directly under webapps in tomcat folder and OpenAM.
Kindly help me out with some solutions.
hi,
ReplyDeleteI am using OpenAM 11. It works little different. First, I have to create IdP and then only I can create Fidlet.
When I was creating Fidlet, I was asked not asked to provide Realm, it was taken as root ("/").
I do not have created Service Provider . Do I need to create Service Provider ?
I am confused in one "Step 4":
Change the above Single logout service url’s to as shown below (Basically in every URL we added "/saml/SingleLogout/alias/realm001/sp" ) where realm001 is the realm and “/sp” is the service provider url we choose when we created openam.Be extra careful when replacing this url to have correct realm name.
as I have not created Service Provider, I don't know what to use as "/sp".
Pls. help me.
thanks
Dhiren
Hello,
ReplyDeleteWe have spring security based JAVA application and want to use office365 authentication for SSO. Can you please let me know the best way to implement this. Does openam is required for this kind of integration. Any help regarding this would be appreciated!!! Thanks.
Jayesh
hi i want some guidance in OpenAM May in know ur emaild
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThanks a lot! You made a new blog entry to answer my question; I really appreciate your time and effort.
ReplyDeletejava training in chennai | java training institutes in chennai | java j2ee training institutes in velachery
Amazing tutorial.We share this JAVA J2EE tutorial very helpful to us.I read now this tutorial very interesting. Java world popular developer work and Mostly IT People working background for Java Developer.Thanks for this useful tutorial.
ReplyDeleteSelenium Training in Chennai | Selenium Training Institute in Chennai |
Java Training in Chennai
Best Java Training Institute in Chennai
great article and tutorial, thanks for your valuable information and time. it is very useful to learn and understand.
ReplyDeleteJava Training in chennai|Best Java Training institute in chennai
Once you have all this code you can plugin spring role based security if you need.
ReplyDeleteAs u said we can do role based security post implementing this code. Can you share how because i dont want the user to be authenticated again,but as per my requirement i need to show him pages as per his/her role. In the authorities i am getting a role of a user from file. I need to add below code
Any help would be appreciated
Nice blog has been shared by you. before i read this blog i didn't have any knowledge about this but now i got some knowledge so keep on sharing such kind of an interesting blogs.mulesoft training hyderabad
ReplyDelete
ReplyDeleteThis is most informative and also this post most user friendly and super navigation to all posts... Thank you so much for giving this information to me..
best rpa training in chennai |
rpa training in chennai | rpa online training |
rpa training in chennai |
rpa training in bangalore
rpa training in pune
rpa training in marathahalli
rpa training in btm
Inspiring writings and I greatly admired what you have to say , I hope you continue to provide new ideas for us all and greetings success always for you..Keep update more information.
ReplyDeleterpa training in chennai |
best rpa training in chennai
rpa online training
rpa course in bangalore
rpa training in pune
rpa training in marathahalli
rpa training in btm
Really great post, Thank you for sharing This knowledge.Excellently written article, if only all bloggers offered the same level of content as you, the internet would be a much better place. Please keep it up!
ReplyDeletepython course in pune | python course in chennai | python course in Bangalore
This is most informative and also this post most user friendly and super navigation to all posts... Thank you so much for giving this information to me.
ReplyDeletebest rpa training in chennai
rpa training in chennai |
rpa online training
rpa course in bangalore
rpa training in pune
rpa training in marathahalli
rpa training in btm
Thank you for taking the time and sharing this information with us. It was indeed very helpful and insightful while being straight forward and to the point.
ReplyDeleteData Science Training in Chennai | Best Data science Training in Chennai
Data Science training in anna nagar | Data science training in Chennai
Data Science training in chennai | Best Data Science training in chennai
Data science training in Bangalore | Data Science training institute in Bangalore
Data Science training in marathahalli | Data Science training in Bangalore
Data Science interview questions and answers
Hello! This is my first visit to your blog! We are a team of volunteers and starting a new initiative in a community in the same niche. Your blog provided us useful information to work on. You have done an outstanding job.
ReplyDeleteAWS Training in Bangalore | Amazon Web Services Training in Bangalore
AWS Interview Questions And Answers
Learn Amazon Web Services Tutorial |AWS Tutorials For Beginners
Amazon Web Services Training in OMR , Chennai | Best AWS Training in OMR,Chennai
AWS Training in Chennai |Best Amazon Web Services Training in Chennai
It’s great to come across a blog every once in a while that isn’t the same out of date rehashed material. Fantastic read.
ReplyDeleteDevops Course Training in Chennai |Best Devops Training Institute in Chennai
Selenium Course Training in Chennai |Best Selenium Training Institute in Chennai
Java Course Training in Chennai | Best Java Training Institute in Chennai
Attend The Python training in bangalore From ExcelR. Practical Python training in bangalore Sessions With Assured Placement Support From Experienced Faculty. ExcelR Offers The Python training in bangalore.
ReplyDeletepython training in bangalore
Being new to the blogging world I feel like there is still so much to learn. Your tips helped to clarify a few things for me as well as giving.devops Training in Bangalore
ReplyDeletevery interesting, good job and thanks for sharing such a good blog. Thanks a lot…
ReplyDeleteBangalore Training Academy is a Best Institute of Salesforce Admin Training in Bangalore . We Offer Quality Salesforce Admin with 100% Placement Assistance on affordable training course fees in Bangalore. We also provide advanced classroom and lab facility.
I am happy for sharing on this blog its awesome blog I really impressed. Thanks for sharing.
ReplyDeleteBecame An Expert In UiPath Course ! Learn from experienced Trainers and get the knowledge to crack a coding interview, @Softgen Infotech Located in BTM.
Mindblowing blog very useful thanks
ReplyDeleteSEO Training in OMR
SEO Training in Chennai
kralbet
ReplyDeletebetpark
tipobet
slot siteleri
kibris bahis siteleri
poker siteleri
bonus veren siteler
mobil ödeme bahis
betmatik
BS301X