Leveraging federation capabilities of Identity Server for API gateway - Configuration Details

With this post I am to share the steps of a popular solution using WSO2 Identity Server and WSO2 API Manager. Following diagram will give an initial insight on this solution.

Overview




1.  Webapp that requires single sign on(SSO) facility with some other applications. 
                - To achieve this we are using WSO2 Identity Server(IS) as the Identity Provider(IDP). 

2.  Webapp needs to consume some APIs secured with OAuth tokens. 
                - To expose the APIs secured with OAuth tokens we are using WSO2 API Manager(AM) here.
                - Since we already have the SAML Response received at SSO step, SAML2 Bearer grant type is ideal to use at this scenario to request an OAuth token to access the required APIs.
                - Allowing AM to properly issue an OAuth token in this scenario, we add IS as a trusted IDP in AM.

3.  Webapp requires to allow users registered in another IDP like Facebook or Google to be able to login with SSO functionality. 
                - With minimum configurations to internal IS and external IDP side, we need to achieve this.
Rest of this post will deal with how we can configure the above, without sharing any databases underneath. Will setup this in multi-tenancy mode, to make it a more general scenario. Another instance of WSO2 Identity Server will be used in the place of external IDP. This can be replaced with Facebook, Google etc. according the requirement.

Pre-requisites

WSO2 Identity Server -5.0.0 - http://wso2.com/products/identity-server
WSO2 API Manager 1.7.0 - http://wso2.com/products/api-manager
                             The compiled webapp ready to deploy in a servelet container, can be found here.
As we are to run several instances of WSO2 servers we need to configure port offsets, if all are configured in one machine. Following are the port offsets and ports I am to use. I will be using two tenants in the two Identity servers and API manager will be run of super tenant mode.

1. WSO2 Identity Server -5.0.0 - Internal IDP - Offset 0 - Port 9443 
                 Tenant - lanka.com
2. WSO2 Identity Server -5.0.0 - Internal IDP - Offset 1 - Port 9444 
                 Tenant - lux.org
3. WSO2 API Manager 1.7.0 - API Gateway - Offset 2 - Port 9445
                 Tenant - carbon.super


Webapp Configurations 

If you download the webapp from the above link, the keystore configurations are already done. You will only need to import the public certificate of the tenant in internal IDP(lanka.com) to the keystore of webapp 'travelocity.jks'. 
Please note the following configurations done in travelocity.properties file found inside webapp at '/travelocity.com/WEB-INF/classes/travelocity.properties'.


EnableSAML2Grant=true

#A unique identifier for this SAML 2.0 Service Provider application
SAML.IssuerID=travelocity.com@lanka.com

#The URL of the SAML 2.0 Identity Provider
SAML.IdPUrl=https://localhost:9443/samlsso

#Password of the KeyStore for SAML and OpenID
KeyStorePassword=travelocity

#Alias of the IdP's public certificate
SAML.IdPCertAlias=lanka.com

#Alias of the SP's private key 
SAML.PrivateKeyAlias=travelocity

#Private key password to retrieve the private key used to sign 
#AuthnRequest and LogoutRequest messages
SAML.PrivateKeyPassword=travelocity

#OAuth2 token endpoint URL
SAML.OAuth2TokenEndpoint=https://localhost:9445/oauth2/token

#OAuth2 Client ID
SAML.OAuth2ClientID=FxuhFBEcX5P1wjtqPqigJ0OVP5ca

#OAuth2 Client Secret
SAML.OAuth2ClientSecret=2eqfI11Y9dRZaiijbAK3dfJFNRMa

1. SSO Setup with Internal IDP

  • Login as tenant admin - <admin>@lanka.com
  • Export the public certificate of the private key used at webapp side to sign the SAML Authentication Request. Following command can be used to export it.
keytool -export -alias travelocity -file travelocity -keystore <path to travelocity.jks(which ever keystore used at webapp side)>
  • Import the above exported public certificate to the tenant key store of the internal IDP, identity server as below.
keystore1.png













  • After the import it will listed as below.













  • Create a new Service Provider for Travelocity webapp as following.
  • Then we needs to configure it as below.    
- By enabling SaaS application, we are removing the tenant boundary for this service provider.
- Enable response and assertion signing according to your requirement.
- Enable signature verification for SAML Authentication Request



The configurations are mostly done to get the SSO scenario work with the webapp. We need to export the tenant public certificate to be imported to the trust store at webapp side. This is in order to verify the SAML Response/Assertion signed signature at the webapp side. We can export the certificate as below from the UI, using public key link.

keystore1.png


The exported key needs to be imported to webapp truststore(in this case travelocity.jks we located inside the webapp).

keytool -import -alias <The given alias name. Here lanka.com> -file <path to downloaded public certificate> -keystore <path to trust store of webapp. Here the travelocity.jks file>

Now if you try to login to travelocity web app as a tenant user, it should succeed.

2. External federation


Following configuration will demonstrate how to configure an external identity provider in Identity Server. Here we will use another instance of identity server as the external IDP. The scenario will be extended from the previous scenario. 


At internal federation, we had 'Travelocity' webapp registered as a Service Provider in the IDP which decided the authenticity of user. Now we will federate the decision on the authenticity of the user to an external IDP. For the demonstration purposes I am using a tenant(named lux.org) in the external IDP(idp.lanka.com).

Configuring another IS instance to act as an external IDP (idp.lanka.com)

  • Create a tenant named ‘lux.org’ and login with this tenant.
  • First we need to import the public certificate of the internal IS into tenant key store, which is paired with the private key used to sign the SAML Request. This time it is 'wso2carbon'.
  • Configure the internal IS as a service provider here. This is because now the SAML request is to be sent to this IS by the internal IS, we configured before.
  • Note that ‘Assertion Consumer URL’ is pointed to ‘https://localhost:9443/commonauth’ of the internal IS. Also note the certificate alias we have selected to use at SAML Request signature validation. This is the one that we imported here.




Configure Internal IS to federate SSO requests from Travelocity webapp to the external IDP

In the internal IS, we need to configure it to make use of the external IDP we just configured.
  • Create a Identity Provider as below. 
  • Upload the public certificate we can download from the external IDP, tenant keystore. This is to validate the signatures of SAML Response and Assertions that will be sent to this internal IS from the external IS.



We have to make some additional changes in the service provider configuration for Travelocity webapp as well. 
  • In the drop down list of federated authenticators select the identity provider we just configured.


There is one more addition we have to do as following to meet the requirement of audience restriction validation in SAML SSO scenario. This is not a requirement for federation, but for API access. The value we give here for audience is the OAuth token endpoint, which we will consume to exchange the SAML token for an OAuth token.



Now we are in a position to test the external federation scenario with Travelocity webapp sample. After hosting it in a tomcat server, hit the URL, ‘http://localhost:8080/travelocity.com/index.jsp’, which will take us to a page as below. Click on the link to login with SAML.


This will take us to following screen. Note the page is from our external IDP (idp.lanka.com), where we can enter credentials of a user in this IDP to get successfully authenticated. If our external authenticator was Google this will be a page from Google, submitted to enter the credentials.

After successful authentication, following screen will be shown.


Now the external federated SAML scenario is completed.

3. API Access leveraging the federation

To achieve this we need following configurations present at Webapp side.
  • Register an application in API-M store, subscribe to some APIs, provide the generated client id and client secret values in travelocity.properties file of the sample webapp.
  • Point SAML.OAuth2TokenEndpoint=https://localhost:9445/oauth2/token to OAuthtoken endpoint of API-M.
  • Import the public certificate of internal IS, to the  keystore used by webapp. The given alias value should be provided at ‘SAML.IdPCertAlias=lanka.com’ in travelocity.properties file.

IDP Configuration at API-M

  • Configure ‘host name’ and ‘mgt host name’ in APIM_HOME/repository/conf/carbon.xml 
  • Login as super admin and add an identity provider as following.

  • Following fields needs to be filled. Note that we have imported the public certificate of the internal IS here, so that we can validate it’s SAML token.
  • API-M is not aware of the federation happening at the internal IS node.

  • When configuring the federated authenticator, we should note that Identity Provider entity id should be as same as the issuer of the SAML Response coming to API-M, to exchange for an OAuth token. SSO URL, is the redirect URL for internal IS.

  • Once these configurations are done, we can test the end-to-end scenario. Now from the page we left at ‘Travelocity’ webapp, if we click on the link ‘Request OAuth2 Access Token’ following page will appear. It is showing the details of the OAuth token, it received in exchange to the provided SAML token.

Now we can use this access token at webapp side to consume any APIs we got subscribed to.

Hope this helps. We can expand and customize this scenario in several ways according to requirements, with options provided with federation, provisioning and extension points. Will discuss those in a latter post.

Cheers!



Comments

  1. Thanks for a great read. As Steve Jobs said : “Innovation is what separates leaders from followers.”

    ReplyDelete
  2. If you want to have the tenant concept effective in the external IS as external IDP here, this property with be helpful "UseAuthenticatedUserDomainCrypto". A usage description can be found at "https://docs.wso2.com/display/IS500/Configuring+identity.xml"

    ReplyDelete
  3. Hi I am trying to follow your article and I found I can not find travelocity.crt under certificat alias drop down. What do I missing?

    ReplyDelete
    Replies
    1. Hi Wah,

      It seems you have missed to import it to the tenant key store. Please double check the steps in topic "1. SSO Setup with Internal IDP"

      Delete
  4. I also followed this below command
    keytool -import -alias -file -keystore
    and I am using "keytool -import -alias lanka.com -file lanka-com-54402.cert -keystore travelocity.jks"
    However, it shows me this error "keytool error: java.lang.Exception: Certificate not imported, alias already exists", and when I login http://localhost:8080/travelocity.com/samlsso
    It returns me "An error has occurred, Signature validation failed for SAML Response ", so what could be the issue here?

    ReplyDelete
    Replies
    1. Hi Wah,

      That's because I have packed the keystore which I used to run this sample. So the I have already imported the public key of my tenant to this key store with the alias 'lanka.com'. So in order to recover, you should delete this existing public key with lanka.com alias and then try to import your tenant's public key.

      To delete the existing public key for alias 'lanka.com', follow the below command.
      keytool -delete -alias lanka.com -keystore travelocity.jks
      Then use your command,
      keytool -import -alias lanka.com -file lanka-com-54402.cert -keystore travelocity.jks

      Hope this will resolve your problem.

      Delete
  5. Thanks for the reply Pushpalanka.

    I have a few other questions when I did the set up following the article:
    1. In the 2nd screen shot under "1. SSO Setup with Internal IDP", I saw there are two available certificates, one is travelocity.crt and follow by wso2carbon. Where is this wso2carbon come from? I don't see this when I create the tenant lanka.com so just want to know where do you create it?

    2. In "2. External federation", you mentioned "First we need to import the public certificate of the internal IS into tenant key store, which is paired with the private key used to sign the SAML Request. This time it is 'wso2carbon'." , so like my first question, where is this wso2carbon come from? The "public certificate" you mentioned here is it same as you exported using below command?
    keytool -export -alias travelocity -file travelocity -keystore

    3. In "Configure Internal IS to federate SSO requests from Travelocity webapp to the external IDP", I followed the step to create a Identity Provider in Internal IS, but when I go to "Local & Outbound Authentication Configuration", the Federated Authentication option is disabled, there is not way to select it. What could be the problem?

    ReplyDelete
  6. I also had the same problem as Wah Vincent.

    3. In "Configure Internal IS to federate SSO requests from Travelocity webapp to the external IDP", I followed the step to create a Identity Provider in Internal IS, but when I go to "Local & Outbound Authentication Configuration", the Federated Authentication option is disabled, there is not way to select it. What could be the problem?

    ReplyDelete
    Replies
    1. The cause would be none of authentication protocols been enabled for that IDP.. Please check at least one protocol as enabled by default for that IDP and check this scenario..

      Delete
  7. Federated auth disabled also. Any config missing

    ReplyDelete
  8. Do you have any example where in the login page comes from external application? I followed https://docs.wso2.com/display/IS500/Customizing+Login+Pages#CustomizingLoginPages-Configuringtheloginpage
    but unable to configure successfully the external app for which there is no example. the url i'm returning from my external app is https://localhost:9444/commonauth

    ReplyDelete
  9. Hi, I followed your example. I see that my SAML Assertion is getting submitted to the /oauth2/token/ endpoint. I am getting a 400 response when this happens. I turned on the debugging and I see that SAML Assertion Audience validation is failing.

    Here is what I have in the Assertion:



    travelocity.com
    https://localhost:9444/oauth2/token/



    I am missing something. Thanks for your help.

    ReplyDelete
  10. Federated auth disabled also. Any config missing

    ReplyDelete
  11. What is this diagram type is called ?

    Regards,

    Shalin @ creately

    ReplyDelete
  12. ERROR
    {org.wso2.carbon.identity.sso.saml.validators.SPInitSSOAuthnRequestValidator}

    - A Service Provider with the Issuer 'travelocity.com' is not registered. Service Provider should be registered in advance

    User will be redirected to
    https://localhost:9443/authenticationendpoint/samlsso_notification.do?status=Error+when+processing+the+authentication+request!&statusMsg=Please+try+login+again.&SAMLResponse=

    ReplyDelete
  13. please reply its really important for me

    ReplyDelete

Post a Comment

Popular posts from this blog

Signing SOAP Messages - Generation of Enveloped XML Signatures

How to send an HTML email in Java (Using Google SMTP Server)

Install Liferay over a MySQL Database