Build React Native App (4) - Redux, Jest, and NativeBase

Image
From this blog, typescript feature will be added. There are couple of ways to implement static type checking like; flow from facebook, PropTypes and Typescript. Typescript is well integrated with Visual Studio Code and supports better linter, error messages, and intellisense. Reference site Github Sample Ex4 Currnet version D:\GitRepo\reactnative>npm --version 6.3.0 D:\GitRepo\reactnative>react-native --version react-native-cli: 2.0.1 react-native: n/a - not inside a React Native project directory D:\GitRepo\reactnative>yarn --version 1.9.4 Creating React Native App $ react-native init ex4 If you want to specify the version, add "--version 0.57.3" at the end. Add NativeBase to React Native $ npm install native-base --save ... + native-base@2.8.1 added 71 packages from 42 contributors, removed 50 packages, updated 829 packages and audited 34989 packages in 138.542s found 0 vulnerabilities $ $ yarn yarn install v1.9.4 warning package-lock.json found. You...

Sample application for Active Directory SSO with Spring Security 4 and Waffle

Introduction

I've developed quotation program with Mybatis, Spring MVC, and SQL Server, but I had a request of integrating this module with Spring Security and Active Directory. I've researched about possible solutions and I've spent quite bit of time with Waffle and SAML. SAML is more ideal, but I found out that the entire implementation is too complicated and I decided to use Waffle for this purpose. One of drawback of Waffle is that the Tomcat server must be runned from Windows platform.

I tried to find out spring security example with Waffle, but it is hard to find out the sample from Internet. It took so many hours to create this simple example.

Tools
Spring STS: 3.6.4
Spring Security : 4.0.1
Spring framework: 4.x.x
Waffle: 1.7.4

Implementation
Creating Spring MVC Project
Create New Project -> Spring Project -> Spring MVC
Updating POM
To make easy of managing version, added two versions under "properties"

       <properties>
              <java-version>1.6</java-version>
              <org.springframework-version>4.1.6.RELEASE</org.springframework-version>
              <org.springsecurity-version>4.0.1.RELEASE</org.springsecurity-version>
              <waffle-version>1.7.4</waffle-version>
              <org.aspectj-version>1.6.10</org.aspectj-version>
              <org.slf4j-version>1.6.6</org.slf4j-version>
         </properties>



Adding spring security components
 

 
<dependency>
                     <groupId>org.springframework.security</groupId>
                     <artifactId>spring-security-core</artifactId>
                     <version>${org.springsecurity-version}</version>
              </dependency>
              <dependency>
                     <groupId>org.springframework.security</groupId>
                     <artifactId>spring-security-config</artifactId>
                     <version>${org.springsecurity-version}</version>
              </dependency>
              <dependency>
                     <groupId>org.springframework.security</groupId>
                     <artifactId>spring-security-web</artifactId>
                     <version>${org.springsecurity-version}</version>
              </dependency> 
 
Adding Waffle components
              <dependency>
                     <groupId>com.github.dblock.waffle</groupId>
                     <artifactId>waffle-jna</artifactId>
                     <version>${waffle-version}</version>
              </dependency>
              <dependency>
                     <groupId>com.github.dblock.waffle</groupId>
                     <artifactId>waffle-spring-security4</artifactId>
                     <version>${waffle-version}</version>
              </dependency>
              <dependency>
                     <groupId>com.google.guava</groupId>
                     <artifactId>guava</artifactId>
                     <version>18.0</version>
              </dependency>
              <dependency>
                     <groupId>net.java.dev.jna</groupId>
                     <artifactId>jna-platform</artifactId>
                     <version>4.1.0</version>
              </dependency>
              <dependency>
                     <groupId>net.java.dev.jna</groupId>
                     <artifactId>jna</artifactId>
                     <version>4.1.0</version>
              </dependency>
             
Web.xml modification
Save Waffle configuration into separate file
       <context-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>
                  /WEB-INF/spring/root-context.xml
                     /WEB-INF/waffle-auth.xml
              </param-value>
       </context-param>

Adding Spring Security filter chain
       <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>
Adding Waffle Security Filter
       <filter>
              <filter-name>SecurityFilter</filter-name>
              <filter-class>waffle.servlet.NegotiateSecurityFilter</filter-class>
       </filter>
       <filter-mapping>
         <filter-name>SecurityFilter</filter-name>
         <url-pattern>/*</url-pattern>
       </filter-mapping>

Adding Waffle-auth.xml
Adding security namespace. Please careful this namespace. If you use the namespace provided from the Waffle site, there will be a complaining about using wrong namespace version.

 xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sec="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

Adding sample Waffle-auth code into this file which provided from the Waffle web site. Please note that there is some modification about access usage and please refer the Spring Security Manual.
       <sec:http auto-config="true">
             
              <sec:form-login
                     login-page="/login.jsp"
                     login-processing-url="/j_spring_security_check"
                     default-target-url="/index.jsp"
                     authentication-failure-url="/login.jsp?login_error=1" />
       </sec:http>
      
      
       <sec:authentication-manager alias="authenticationProvider">
              <sec:authentication-provider ref="waffleSpringAuthenticationProvider" />
       </sec:authentication-manager>
      
      
       <bean id="waffleWindowsAuthProvider" class="waffle.windows.auth.impl.WindowsAuthProviderImpl" />
      
      
    <bean id="waffleSpringAuthenticationProvider" class="waffle.spring.WindowsAuthenticationProvider">
        <property name="allowGuestLogin" value="false" />
        <property name="principalFormat" value="fqn" />
        <property name="roleFormat" value="both" />
        <property name="authProvider" ref="waffleWindowsAuthProvider" />
    </bean>
One of example from the Waffle used the "AllowGuestLogin" from the property and this will cause another error. The property function maps the field name in the class and the first letter must be lower case as you see from the example.
Adding log4j debugging code
       <logger name="waffle.servlet.NegotiateSecurityFilter">
              <level value="debug" />
       </logger>
       <logger name="waffle.servlet.spi.SecurityFilterProviderCollection">
              <level value="debug" />
       </logger>
       <logger name="waffle.servlet.spi.NegotiateSecurityFilterProvider">
              <level value="debug" />
       </logger>
       <logger name="waffle.servlet.spi.BasicSecurityFilterProvider">
              <level value="debug" />
       </logger>
 
Adding login.jsp and index.jsp page from Sample code
index.jsp
<%
  if (request.getParameter("logoff") != null) {
    session.invalidate();
    response.sendRedirect("index.jsp");
    return;
  }
%>
<html>
 <head>
  <title>Protected Page for Examples</title>
 </head>
 <body style="background-color:white;">
  You are logged in as remote user <b><%= request.getRemoteUser() %></b> in session <b><%= session.getId() %></b>.
  <br><br>
  <%
       if (request.getUserPrincipal() != null) {
  %>
  Your user principal name is <b><%= request.getUserPrincipal().getName() %></b>.
  <br><br>
  <%
   } else {
  %>
   No user principal could be identified.
   <br><br>
  <%
  }
  %>
  <%
  String role = request.getParameter("role");
  if (role == null)
    role = "";
  if (role.length() > 0) {
    if (request.isUserInRole(role)) {
  %>
  You have been granted role <b><%= role %></b>.
  <br><br>
  <%
   } else {
  %>
  You have <i>not</i> been granted role <b><%= role %></b>.
  <br><br>
  <%
   }
  }
  %>
  To check whether your username has been granted a particular role, enter it here:
  <form method="GET" action='<%= response.encodeURL("index.jsp") %>'>
   <input type="text" name="role" value="<%= role %>">
  </form>
  <br><br>
  You can logoff by clicking
  <a href='<%= response.encodeURL("index.jsp?logoff=true") %>'>here</a>.
  This should cause automatic re-logon with Waffle and a new session ID.
 </body>
</html>

login.jsp

<html>
 <head>
  <title>Login</title>
 </head>
</html>
<body>
 <form method="POST" action="j_spring_security_check">
  <table style="vertical-align: middle;">
   <tr>
    <td>Username:</td>
    <td><input type="text" name="j_username" /></td>
   </tr>
   <tr>
    <td>Password:</td>
    <td><input type="password" name="j_password" /></td>
   </tr>
   <tr>
    <td><input type="submit" value="Login" /></td>
   </tr>
  </table>
 </form>
</body>


Final folder structure
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiUwlMQq9pluqA8YTVLPL6J-MtROW5GBPGDSUsy5xKL2J8br1IKsi7yak1cAXwbACOxgwf7bR0E9kNuC29o9PFCGnXHNH9JTDkqs3MdsV9sr7D1OX6Mr7gJ_kBvSvGfaZpFmRYPY7PvFyi/s320/Waffle-FolderStructure.png

Result
Web result
You are logged in as remote user DomainName\alex.joh in session89E052662368DCB7502F15A65D9F20EE.

Your user principal name is DomainName\alex.joh.

To check whether your username has been granted a particular role, enter it here:
Top of Form
Bottom of Form


You can logoff by clicking here. This should cause automatic re-logon with Waffle and a new session ID.

Debug Result 

Jun 08, 2015 10:08:26 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 552 ms
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
INFO : org.springframework.web.context.support.XmlWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Mon Jun 08 10:08:28 MDT 2015]; root of context hierarchy
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/spring/root-context.xml]
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/waffle-auth.xml]
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 871 ms
DEBUG: waffle.servlet.NegotiateSecurityFilter - [waffle.servlet.NegotiateSecurityFilter] loaded
DEBUG: waffle.servlet.NegotiateSecurityFilter - initializing default security filter providers
INFO : waffle.servlet.NegotiateSecurityFilter - [waffle.servlet.NegotiateSecurityFilter] started
INFO : org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'appServlet': initialization started
INFO : org.springframework.web.context.support.XmlWebApplicationContext - Refreshing WebApplicationContext for namespace 'appServlet-servlet': startup date [Mon Jun 08 10:08:28 MDT 2015]; parent: Root WebApplicationContext
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/spring/appServlet/servlet-context.xml]
INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.alexjoh.waffle.HomeController.home(java.util.Locale,org.springframework.ui.Model)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - Looking for @ControllerAdvice: WebApplicationContext for namespace 'appServlet-servlet': startup date [Mon Jun 08 10:08:28 MDT 2015]; parent: Root WebApplicationContext
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - Looking for @ControllerAdvice: WebApplicationContext for namespace 'appServlet-servlet': startup date [Mon Jun 08 10:08:28 MDT 2015]; parent: Root WebApplicationContext
INFO : org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped URL path [/resources/**] onto handler 'org.springframework.web.servlet.resource.ResourceHttpRequestHandler#0'
INFO : org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'appServlet': initialization completed in 611 ms
Jun 08, 2015 10:08:30 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 4471 ms
DEBUG: waffle.servlet.NegotiateSecurityFilter - GET /waffle/, contentlength: -1
DEBUG: waffle.servlet.NegotiateSecurityFilter - authorization required
DEBUG: waffle.servlet.NegotiateSecurityFilter - GET /waffle/, contentlength: -1
DEBUG: waffle.servlet.spi.NegotiateSecurityFilterProvider - security package: Negotiate, connection id: 127.0.0.1:62105
DEBUG: waffle.servlet.spi.NegotiateSecurityFilterProvider - token buffer: 123 byte(s)
DEBUG: waffle.servlet.spi.NegotiateSecurityFilterProvider - continue token: oYH4MIH1oAMKAQGhDAYKKwYBBAGCNwICCqKB3wSB3E5UTE1TU1AAAgAAAAoACgA4AAAAFcKJ4pyBB8CuwWAaUEGzAwAAAACaAJoAQgAAAAYBsR0AAAAPRgBMAEEASQBSAAIACgBGAEwAQQBJAFIAAQAUAEYATABDAEEARAAwADMAMAAyADkABAAWAGYAbABhAGkAcgAuAGwAbwBjAGEAbAADACwARgBMAEMAQQBEADAAMwAwADIAOQAuAGYAbABhAGkAcgAuAGwAbwBjAGEAbAAFABYAZgBsAGEAaQByAC4AbABvAGMAYQBsAAcACADqlmBgBaLQAQAAAAA=
DEBUG: waffle.servlet.spi.NegotiateSecurityFilterProvider - continue required: true
DEBUG: waffle.servlet.NegotiateSecurityFilter - GET /waffle/, contentlength: -1
DEBUG: waffle.servlet.spi.NegotiateSecurityFilterProvider - security package: Negotiate, connection id: 127.0.0.1:62105
DEBUG: waffle.servlet.spi.NegotiateSecurityFilterProvider - token buffer: 121 byte(s)
DEBUG: waffle.servlet.spi.NegotiateSecurityFilterProvider - continue token: oRswGaADCgEAoxIEEAEAAABDh+CIwTbjqQAAAAA=
DEBUG: waffle.servlet.spi.NegotiateSecurityFilterProvider - continue required: false
DEBUG: waffle.servlet.NegotiateSecurityFilter - logged in user: DomainName\alex.joh (S-1-5-21-755196386-1090219167-4272789823-3182)
DEBUG: waffle.servlet.NegotiateSecurityFilter - roles: DomainName\alex.joh, FLAIR\Domain Users, Everyone, .......... Remove rest of roles
INFO : waffle.servlet.NegotiateSecurityFilter - successfully logged in user: FLAIR\alex.joh
INFO : com.alexjoh.waffle.HomeController - Welcome home! The client locale is en_US.
Summary
It is not easy to come to this point and I almost spent 2 weeks to run this simple example under Spring Security. I wish this article could save someone's time who is struggling to use Waffle from the Spring framework.

Project file
https://drive.google.com/file/d/0B2pxwYP3VWWFc0taeFRxRVVyM2M/view?usp=sharing

Comments

  1. Hey Alex..
    Thanks a lot for this working sample !!! I had gone crazy searching for something like this !!! Glad I landed here.. worked like a charm !!
    Thanks again !!
    Mukta

    ReplyDelete
  2. Hi Alex, I need some help with this. How may I contact you ?

    ReplyDelete
  3. Hi Alex, Nice Artical, we are looking for angular js with waffle-spring security. Let me know

    ReplyDelete
  4. Does it pick the windows logged in user as the remote user ?

    ReplyDelete
  5. Thanks a lot very much for the high quality and results-oriented help.
    I won’t think twice to endorse your blog post to anybody who wants
    and needs support about this area.
    hire angularjs developer

    ReplyDelete
  6. Great work, Thank you..
    Do you have a sample with annotations?

    ReplyDelete

Post a Comment

Popular posts from this blog

Build React Native App (4) - Redux, Jest, and NativeBase

Replacing text in PDF file using iTextSharp

Using GIT(Bitbucket), Visual Studio Code