Monthly Archives: October 2018

Use of clockskew in SAML Assertion in SAML Protocol

In this post, I will explain how we can use clockskew in SAML Assertion to avoid a general problem when a Service Provider (SP) receives a SAML response from Identity Provider (IdP) and if both of them are on different machines which is generally the scenario.

So when a user accesses a SP application, SP sends an authentication request to IdP and IdP sends a SAML response to SP. The typical SAML response looks like below:

<saml2p:Response Destination="https://localhost:8443/spring-security-saml2-sample/saml/SSO"
                 ID="_8ced26c57648ea420c5e27ac7f3d78b3"
                 InResponseTo="a3ei0bej41ie0dg738jji60271f1bca"
                 IssueInstant="2018-10-31T18:39:05.109Z"
                 Version="2.0"
                 xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 >
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://sts.betterjavacode.com/sts</saml2:Issuer>
    <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:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
            <ds:Reference URI="#_8ced26c57648ea420c5e27ac7f3d78b3">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                        <ec:InclusiveNamespaces PrefixList="xsd"
                                                xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"
                                                />
                    </ds:Transform>
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                <ds:DigestValue>k6k9seVwZT8qEfainB+HDUJmv7wLwPjJxRARgrFLk3E=</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>
eYl7/5Bg4f2ZtXYl1Tp/ZW4CIqna1sjHjVSB/zhj3NHncQu7pq9PBTdWz0JEaE8+efICz7trDQvI
J0tih35Vg7NqDtOeps7vMttV0XvrnWKIXEqrscyNgkhwy+KW2oprKIWTJq6y3Z0kQ7n2DlTRkfAE
yLRPxqr8AZU+77Tbv4DmTQVp934ivibUaMNU79nkhMMo7vf0ldpeNCe5Ll5Q7nxgNBCrL4mhbGdU
DNJDVqJIhQZDJUYhBVZSgLo6mYLxf0ndQr5+GdcvO3i8VlooH49I5ZO6LfsBlNiSU6WezC0Fcz8J
biodrT3h62Jny8FKUgYfXA8i0ZoAerCxHmLGFQ==
</ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>MIICpTCCAY2gAwIBAgIHAKQk/Tty7TANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhJbmZvclNU
UzAeFw0xNzExMTAxNjIwMjVaFw0xOTExMTAxNjIwMjZaMBMxETAPBgNVBAMMCEluZm9yU1RTMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuy40GofgfSldiu7AXRSWQZo8YIUmdJOXV5gd
YUiIBggcm5J+jttd21av9AWBDLtvekIqgG+nM1SEarDNlCgrnThqDtdsBDnT+B5FQowLwqNQZb0C
6PSWccp484OLHhv3YwbjV/IxgW6wlv2EejPF93NTPc5TkkpIKIEARJwKiUvuwzkcX1atD8HESj8/
5wZhK3g3MSv+CaJb1Y732U2aa34RI6HYRNlKRsqRj55SZnPs3AmIBL/rdVbt5eYJdK+jXSOMQ9Sb
TNkgTAYKnlSQP8NhsNc1Y5ZJ231KD3rSqHEXwpKVXFuEgtBnCL9utqyUU0Fu9PNJJj0hf9otMJw2
pQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAsqxA/+llqNtJq/VPtAa0XwtldB7/4Gew5LgfU5Yj7
/ruHuxCh03xfnLyjo0bxrFeMbhHMg4MzJhgah0zTIl4WMRI781CiMxGfMdvQAHhY5hgpryqKUTbH
qcIoW1WkTEL+TrOSk2gjL/n/4KsUJ3XKeI4j4h2RDvbIF8u9cbrB5RupEwJlo/pK3mCr3GQGFxVX
4yli+AysMmz8JWz2hWQad0QQr9KIYmZdgauNt7uYn4u+7cngtTtQF/EMoZU1pAFI5lDP13mxI1rR
eYGzoKhGfHIy7TiXYvqX0vFomzkgr6D0DnRlRkQR8J5EVtnGZ7sF50KlNviG+IxrPNndUdeX</ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>
    <saml2p:Status>
        <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
    </saml2p:Status>
    <saml2:Assertion ID="_43514fee402111bfa8ef07e2bb3e1816"
                     IssueInstant="2018-10-31T18:39:05.109Z"
                     Version="2.0"
                     xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                     >
        <saml2:Issuer>https://sts.betterjavacode.com/sts</saml2:Issuer>
        <saml2:Subject>
            <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
                          NameQualifier="https://sts.betterjavacode.com/sts"
                          SPNameQualifier="https://localhost:8443/spring-security-saml2-sample/saml/metadata"
                          >-74375301938178262591541011144180</saml2:NameID>
            <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml2:SubjectConfirmationData InResponseTo="a3ei0bej41ie0dg738jji60271f1bca"
                                               NotOnOrAfter="2018-10-31T18:44:05.109Z"
                                               Recipient="https://localhost:8443/spring-security-saml2-sample/saml/SSO"
                                               />
            </saml2:SubjectConfirmation>
        </saml2:Subject>
        <saml2:Conditions NotBefore="2018-10-31T18:39:05.109Z"
                          NotOnOrAfter="2018-10-31T18:44:04.109Z"
                          >
            <saml2:AudienceRestriction>
                <saml2:Audience>https://localhost:8443/spring-security-saml2-sample/saml/metadata</saml2:Audience>
            </saml2:AudienceRestriction>
        </saml2:Conditions>
        <saml2:AttributeStatement>
            <saml2:Attribute Name="http://schemas.microsoft.com/claims/Tenant">
                <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                      xsi:type="xsd:string"
                                      >ABC Company</saml2:AttributeValue>
            </saml2:Attribute>
            <saml2:Attribute Name="http://schemas.microsoft.com/claims/Identity">
                <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                      xsi:type="xsd:string"
                                      >testuser</saml2:AttributeValue>
            </saml2:Attribute>
            <saml2:Attribute Name="http://schemas.xmlsoap.org/claims/CommonName">
                <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                      xsi:type="xsd:string"
                                      >Test User</saml2:AttributeValue>
            </saml2:Attribute>

            <saml2:Attribute Name="http://schemas.microsoft.com/claims/Email">
                <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                      xsi:type="xsd:string"
                                      >test.user@betterjavacode.com</saml2:AttributeValue>
            </saml2:Attribute>
            <saml2:Attribute Name="http://schemas.microsoft.com/claims/Session">
                <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                      xsi:type="xsd:string"
                                      >-65311121040491585821541011144177</saml2:AttributeValue>
            </saml2:Attribute>                        
        </saml2:AttributeStatement>
        <saml2:AuthnStatement AuthnInstant="2018-10-31T18:39:05.109Z"
                              SessionIndex="31079178551135950171541011144177"
                              >
            <saml2:AuthnContext>
                <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
            </saml2:AuthnContext>
        </saml2:AuthnStatement>
    </saml2:Assertion>
</saml2p:Response>

Now SP and IdP are on different machine. And there can be a case that their clocks are not synced. So when IdP generates the response, it has an element SubjectConfirmationData that contains NotBefore and NotOnOrAfter. Subject indicates details about the user and relying party who is receiving the assertion. Relying party has to verify that the assertion is coming from the right issuer.

NotBefore – Time before which subject can not be validated.

NotOnOrAfter – Time on or after which subject has expired.

Similarly, there will be Conditions element in the assertion and this element will also contain attributes NotBefore or NotOnOrAfter. These two attributes indicate at what time assertion will be valid and after what time, it will be expired.

Problem

Now if we take into account a scenario where system clocks of IdP and SP are not in sync and if Idp clock is ahead of Sp clock, how do we handle this scenario?

Solution

So as described in above scenario, then assertion validation will fail because of NotBefore time will be greater than the time on SP machine.

To solve this issue, we can either make sure IdP and SP clocks are in sync. But this seems human-dependent solution and getting clocks in sync is not always practical solution.

Another way this can be solved by adding a clockskew in SAML assertion. A relying party that is consuming the assertion should apply small clockskew to time to accommodate small changes in time.

private int clockSkew = 120;

SubconfirmationData subjectConfirmationData = subjectConfirmation.getSubjectConfirmationData();

if(subjectConfirmationData.getNotOnOrAfter().plusSeconds(clockSkew).isBeforeNow())
{
 // throw error - Subject Confirmation Data has expired
}

/***
*
*
*/

if (conditions.getNotBefore() != null && conditions.getNotBefore().minusSeconds(clockSkew).isAfterNow()) 
{
      throw new SAMLException("Assertion condition notBefore is not valid");
}

if (conditions.getNotOnOrAfter() != null && conditions.getNotOnOrAfter().plusSeconds(clockSkew).isBeforeNow()) 
{
      throw new SAMLException("Assertion condition notOnOrAfter is not valid");
}

 

References

  1. SAML Specification
  2. SAML assertion with NotBefore and NotOnOrAfter

Building user interface for Social KPI

As part of building the web application Social KPI SocialPie, we will be building the backend and frontend in module forms. Eventually, the plan is to deploy the application on the cloud. But backend and frontend are not different services as Microservice architecture generally dictates. In this post, I will show how we will be building a user interface for Social KPI using thymeleaf and angular JS.

The idea is to create a skeleton of UI by bringing different points in the discussion to make our decisions about choosing different parts of UI. In the previous post here, we discussed user flow.

User Story for user interface

  1. A user will access the application and will see the initial screen for login or sign up.
  2. If the user has not signed up before, he will sign up with the first name, last name, email, company name, password.
  3. Once the user signs up, the user will receive a confirmation email to sign in. This user will be the administrator to manage its company.
  4. A user can come back to the login screen through confirmation email. Then the user will enter credentials.
  5. User will see the company profile. User will have the option to modify company profile details as well as to add users with role REPORT.
  6. Administrator when adding these users will submit their first name, last name, email, and role as REPORT. Administrator will have an option to send emails to these users through portal or provide them username and password.
  7. Once the users with role REPORT login, they will have the option to change their temporary password. Once the password has been changed, he will be redirected to the reports screen.
  8. Administrator can also access reports screen any time.
  9. On Reports screen, user will have an option to synchronize the data with social media APIs to get the latest data. This will be once in a day option considering the limitation on access of APIs.
  10. On Reports screen, user will have an option to generate the report post-synchronization. User will be able to see Jasper reports in graph as well in data form. User will have an option to send these reports to other people in email.
  11. There will be logout and home screen options on the screen all the time.
  12. Home for user with Report role will be their profile information.

The skeleton of the user interface

Screen 1:

First Page

Screen 2:

Second Page

Screen 3:

Third Page

Screen 4:

Forth Page

Screen 5:

Fifth Page

Screen 6:

Sixth Page

Screen 7:

Seventh Page

Conclusion

In this post, we showed the skeleton of the user interface for the Social KPI web application. Of course, this is not a final design, but as we go on building it, we will have our changes and I will also show the code for this design. In future posts, I will be showing the functioning UI for login and sign-up pages.

 

 

 

Difference between java.home and JAVA_HOME

When setting up environments, one of the few things we have to do is set up environment variables. JAVA_HOME is the most common environment variable you have to set up, especially if doing Java development. So previously, I had asked this question about knowing the difference between java.home and JAVA_HOME on StackOverflow here.

Question

Basically, I was using System.getProperty("java.home") in my code and it would return difference value from what I had set for JAVA_HOME. I was wondering why the difference. This post is about the explanation of the difference between these two properties.

Answer

There are some contradictory answers about the difference. But what I found on my own is that java.home is a system variable created based on Java Runtime Environment (JRE). This is more like a system variable. JAVA_HOME is an environment variable, this is required when you install JDK. Java Development Kit(JDK) is an environment based software that an individual installs and this software needs Java Runtime Environment (JRE).  So JDK is a superset of JRE.

On any system, when you ask for JAVA_HOME environment variable, you generally get the path of your JDK installation. But since java.home is a system variable, the only way to find out that variable is through system properties. Also some machines have default Oracle installed JRE path and java.home might point to that path. You won’t be able to do any Java-based development if you do not have JAVA_HOME defined.

But the interesting fact is when you install JDK, it also installs JRE. But when you verify java.home , it doesn’t point to the same root path where JDK has been installed. One main reason for this, is that despite when you install JDK, JRE and JDK are two different products and many machines have default JRE installed.

Conclusion

In this post, I showed the difference between JAVA_HOME and java.home. Subscribe to my blog here.

References

  1. System Properties – Oracle Documentation