Security and single sign-on are main aspects of Web application development. App Manager is capable of providing a security layer which handles single sign-on, on top of all the Web applications registered within. The flow of the single sign-on is depicted in the diagram below.
Securing with SAML2 SSO is handled according to the following sequence of events.
- Once a request comes to the application gateway, it checks for an authenticated cookie. If the cookie is found in the request, request is sent to the actual Web application URL. If not, request will be redirected to a login page, where user has to provide credentials.
- If authentication is successful IDP redirects the user back to the gateway URL with SAML response. At the gateway URL, SAML response is validated and Web application can be accessed by the user. Application gateway uses a JWT to send logged in user details to the actual Web application.
Enabling single sign-on
Follow the steps below to enable SAML SSO:
- Once a Web application is published from App Manager publisher, synapse handler for SAML SSO is attached to the synapse configurations as follows.
<handler class="org.wso2.carbon.appmgt.gateway.handlers.security.saml2.SAML2AuthenticationHandler"/>
The
SAML2AuthenticationHandler
validates incoming requests. If authenticated cookie is not found, request is sent to the IDP. The IDP URL is configured as a synapse sequence as follows.If App Manager is running with a port offset of zero and default IDP is used, then these configurations need not to be changed.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="saml2_sequence"> <property name="uri.var.saml2.request" expression="get-property('SAMLRequest')" /> <call> <endpoint xmlns="http://ws.apache.org/ns/synapse" name="HTTPEndpoint"> <http uri-template="https://localhost:9443/samlsso?SAMLRequest={uri.var.saml2.request}" method="POST"> </http> </endpoint> </call> <respond/> </sequence>
Add the Web application as a service provider in service provider configurations in IDP. For more information on configuring a SAML2 service provider in WSO2 Identity Server, go to Adding a Service Provider.
When setting up a service provider;
Web application name should be provided as the issuer in the service provider configuration.
Assertion consumer URL should be gateway URL of the Web application.
Once above setup is done, subscribed users can access the Web application in SSO mode. In SSO mode, you only needs authentication done once. If you access another subscribed application from the same browser, you will be logged in to the second application automatically.
Enabling JWT generation
App Manager uses JWT as the medium to send user details to the Web application. All the claims which are returned from IDP together with the user name will be included in the JWT.
In order to enable JWT generation, uncomment the EnableTokenGeneration element
and change the value to true in the <PRODUCT_HOME>/repository/conf/app-manager.xml
file as follows:
<APIConsumerAuthentication> <EnableTokenGeneration>true</EnableTokenGeneration> </APIConsumerAuthentication>
Now SSO is configured properly and user details are sent to the Web application through a JWT. JWT token is BASE64 encoded and this needs to be decoded before using at the Web application. A sample decoded JWT is shown below.
{"iss":"wso2.org/products/am","exp":1394072102566,"Subject":"admin","http://wso2.org/claims/emailaddress":"appm@wso2.com", "http://wso2.org/claims/mobile":"123123213","http://wso2.org/claims/role":"admin,subscriber,Internal/everyone"}
Sending SAML response to backend
In addition to sending JWT token to backend, App Manager can be configured to send the whole SAML response which generated by IdP as a transport header to the backend Web application. This is useful if the backend Web application is already aware of handling SAML responses or it can be decoded and get the authenticated user details.
In order to send SAML response to backend Web application, uncomment the AddSAMLResponseHeaderToOutMessage element
and change the value to true in the <PRODUCT_HOME>/repository/conf/app-manager.xml
file as follows:
<APIConsumerAuthentication> <AddSAMLResponseHeaderToOutMessage>true</AddSAMLResponseHeaderToOutMessage> </APIConsumerAuthentication>
This will send URL + Base64 encoded SAML response as a header to backend Web application. A sample decoded SAML response is shown below.
<?xml version="1.0" encoding="UTF-8"?> <saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="http://10.216.198.146:8280/tommy/1.0.0/" ID="aneajbllipgjddmbfaidejhkchfoddifjjpacokg" InResponseTo="0" IssueInstant="2015-01-30T02:03:00.621Z" Version="2.0"> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">localhost</saml2:Issuer> <saml2p:Status> <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </saml2p:Status> <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="lobpplgkoddjikdbhbpleclmpdfhgkmdlpbgfmjp" IssueInstant="2015-01-30T02:03:00.621Z" Version="2.0"> <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">localhost</saml2:Issuer> <saml2:Subject> <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin</saml2:NameID> <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml2:SubjectConfirmationData InResponseTo="0" NotOnOrAfter="2015-01-30T02:08:00.621Z" Recipient="http://10.216.198.146:8280/tommy/1.0.0/"/> </saml2:SubjectConfirmation> </saml2:Subject> <saml2:Conditions NotBefore="2015-01-30T02:03:00.621Z" NotOnOrAfter="2015-01-30T02:08:00.621Z"> <saml2:AudienceRestriction> <saml2:Audience>Tomcat-App-1.0.0</saml2:Audience> </saml2:AudienceRestriction> </saml2:Conditions> <saml2:AuthnStatement AuthnInstant="2015-01-30T02:03:00.621Z" SessionIndex="88b62069-16b4-4c77-87c4-68ff8b9326f6"> <saml2:AuthnContext> <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef> </saml2:AuthnContext> </saml2:AuthnStatement> <saml2:AttributeStatement> <saml2:Attribute Name="http://wso2.org/claims/role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">admin,Internal/subscriber,Internal/publisher,Internal/Tomcat-App-1.0.0,Internal/everyone</saml2:AttributeValue> </saml2:Attribute> </saml2:AttributeStatement> </saml2:Assertion> </saml2p:Response>