AngularJS: Automatically submitting HTML forms

Our yearlong delve into the sea that is Angular Js has kept our engineering team busy for quite some time now. Throughout this fun time of exploration there have been ups and downs, muddled coding snares caused by niche problems that are almost impossible to conform to the constantly looming “Angular Way”, and complicated problems that could be solved so easily you wished you had a Staples button just so you could push it for the “That was easy”.

One invaluable resource that has continually helped guide us through our use of this robust MVC framework is the vast Angular Js community, that has helped answer most of our questions, from questions about basic tutorials, to more overarching questions about best practices when structuring applications.

On one of our more recent Angular projects, we ran into an issue implementing a fairly common need among web applications - generating an auto submit form. After poking around Google and StackOverflow for a bit, surprisingly, there was a lot less information on this subject than expected. So, we decided to write a blog post on the subject, giving back to the AngularJS community, which has given so much to us.

Interestingly, this problem can be solved quite easily once you have a more comprehensive understanding about the Angular directive’s Link function. Here’s a good StackOverflow answer if you’re interested in some light reading: AngularJS: What is the need of the directive’s link function when we already had directive’s controller with scope?. However, if you’re anything like us then you’re probably solely interested in learning just enough to solve the immediate problem at hand, so for you, the main “gotcha” that you need to know is that the template for any directive is wrapped as an angular element, and can be accessed inside of the Link function using the angular.element() function.

The basic idea is simple, create a custom directive for your auto submit form, make the template for this directive a form element with the information you want to send, and control its rendering using an ng-if directive. Using ng-if is important in this instance because this directive doesn’t just show/hide a portion of the DOM tree, but actually removes/recreates it, allowing you to take advantage of the directives Link function. Then, inside of the link function for the auto submit form directive, grab the form element using the angular.element() function and submit it using the javascript function submit().

If the above paragraph didn’t completely explain it to you, please don’t worry, here is a nice, concrete example to help you solve this problem quickly should you ever run into it again in the future.

angular.module('angularDemoApp', [])

.directive('autoSubmitForm', function($timeout){
    return {
        restrict: 'E',
        replace: true,
        scope: {submitForm: '='},
        templateUrl: 'hiddenForm.html',
        link: function(scope, el, attr){
            $timeout(function() {
                angular.element(el).submit();
            });
        }
    };
})

.controller('DemoCtrl', function ($scope){
    $scope["utilizeInfo"] = function(){
        $scope["submitForm"] = {url: "echoForm.php", values: [{name: "name", value: "Phil"}, {name: "age", value: "23"}]};
    };
})
;     

// hiddenForm.html
<form method="POST" action="" class="hidden">       
    <input ng-repeat="field in submitForm.values" type="hidden" name="" value="" />     
</form>

Spring Boot: Authentication with custom HTTP header

For the last few months we’ve been working on a Spring Boot project and one of the more challenging aspects has been wrangling Spring’s security component. For the project, we were looking to authenticate users using a custom HTTP header that contained a token generated from a third party service. There doesn’t seem to be a whole lot of concrete examples on how to set something like this up so here’s some notes from the trenches. Note: I’m still new to Spring so if any of this is inaccurate, let me know in the comments.

Concretely, what we’re looking to do is authenticate a user by passing a value in an X-Authorization HTTP header. So for example using cURL or jQuery:

:~$ curl -H "X-Authorization: $some_secret_token" http://localhost/user

$.ajax({
    url: 'http://localhost/user',
    headers: { 'X-Authorization': '$some_secret_token' }
});

In addition to insuring that the token is valid, we also want to setup Spring Security so that we can access the user’s details using “SecurityContextHolder.getContext().getAuthentication()”. So how do you do this? Turns out, you need a couple of classes to make this work:

  • An Authentication Token: You need a class that extends AbstractAuthenticationToken so that you can let Spring know about your authenticated user. The UsernamePasswordAuthenticationToken class is a pretty good starting point.
  • The Filter: You’ll need to create a filter to inspect requests that you want authenticated, grab the X-Authentication filter, confirm that it’s a valid token, and set the corresponding Authentication. Since we only want this to run once per request you can extend the OncePerRequestFilter class to set this up. You can see an example class below:

    import java.io.IOException;
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.web.filter.OncePerRequestFilter;
    
    public class DemoAuthenticationFilter extends OncePerRequestFilter {
    
        @Override
        protected void doFilterInternal(HttpServletRequest request,
                HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
            
            String xAuth = request.getHeader("X-Authorization");
            
            // validate the value in xAuth
            if(isValid(xAuth) == false){
                throw new SecurityException();
            }                            
            
            // The token is 'valid' so magically get a user id from it
            Long id = getUserIdFromToken(xAuth);
            
            // Create our Authentication and let Spring know about it
            Authentication auth = new DemoAuthenticationToken(id);
            SecurityContextHolder.getContext().setAuthentication(auth);            
            
            filterChain.doFilter(request, response);
        }
    
    }
  • An Authentication Provider: The final piece is a class that extends AuthenticationProvider which handles retrieving a JPA entity from the database. By implementing an AuthenticationProvider instead of doing the database lookup in the filter, you can keep your filter framework agnostic by not having to autowire in a JPA repository. My implementation looks similar to:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.authentication.AuthenticationProvider;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.stereotype.Component;
    import com.pearson.reader.error.UnknownUserException;
    import com.pearson.reader.models.User;
    import com.pearson.reader.repositories.UserRepository;
    
    @Component
    public class DemoAuthenticationProvider implements AuthenticationProvider {
    
        // This would be a JPA repository to snag your user entities
        private final UserRepository userRepository;
        
        @Autowired
        public DemoAuthenticationProvider(UserRepository userRepository) {
            this.userRepository = userRepository;
        }    
        
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            
            DemoAuthenticationToken demoAuthentication = (DemoAuthenticationToken) authentication;        
            User user = userRepository.find(demoAuthentication.getId());
            
            if(user == null){
                throw new UnknownUserException("Could not find user with ID: " + demoAuthentication.getId());
            }
            
            return user;
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return DemoAuthenticationToken.class.isAssignableFrom(authentication);
        }
    
    }

And finally, the last step is to wire this all up. You’ll need a class that extends WebSecurityConfigurerAdapter with two ovveridden configure methods to configure the filter and the authentication provider. For example, the following works at a bare minimum:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfigDemo extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private DemoAuthenticationProvider demoAuthenticationProvider;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {        
                
        http
        .authorizeRequests()
            .antMatcher("/user")
                .addFilterBefore(new DemoAuthenticationFilter(), BasicAuthenticationFilter.class)                
        ;
                        
    }
    
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {        
        auth.authenticationProvider(demoAuthenticationProvider);        
    }    
    
}

And then finally to access the authenticated user from a controller you’d do:

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User user = (User) auth.getPrincipal();

Anyway, hope this helps and as mentioned above if there’s anything inaccurate feel free to post in the comments.

Setfive: Looking back on a summer of shenanigans

Labor day has come and gone so summer is officially over. We sat down with our intern Phil to chat about his time interning at Setfive.

Favorite Part About Interning At Setfive?

My favorite part about interning at Setfive was being introduced to so many different programming tools, and having the ability to increase my programming skill set. This summer I learned about PHP, the Symfony 2 Framework, MYSQL, I improved my JavaScript skills, learned some Angular.js, and even learned how to write unit tests. I was exposed to so many new things that everyday was fun and no two days were ever the same.

The environment here encouraged questions, and allowed me to ask and receive answers to anything I wanted to know more about. Some of the guys would even go out of their way to send me related documentation about something if they felt that they couldn’t confidently answer it themselves.

Working under the guys here was an incredible experience, I was given the freedom to make mistakes and figure out problems on my own, but at the same time was given sufficient structure to make consistent progress. It was awesome to have the comfort of knowing I had a smart, qualified person to guide me in the right direction if I ever got too stuck on any one problem.

Most important thing that you learned?

The most important skill that I learned was definitely an improved conceptual understanding of MVC, and that while sometimes using this pattern slows down your programming, in the long run it helps you create readable, modular code.

I also learned that installation is just the worst.

Most Memorable Moment?

The most memorable moment of the summer was the first time we used the Txty Jukebox in the office. It didn’t quite work the first time around, however, watching people use and get enjoyment out of something that I helped to create was something that I’ will never forget.

Where do you want to go from here?

From here I definitely want to continue building custom applications. I’ve spent the last part of the summer teaching myself objective-c, and the skills that I’ve learned here will definitely help me make the transition into developing iOS applications.

Top 5 Things To Eat

  1. Buffalo Soulja - Darwins (Only available on Thursdays)
  2. Mango Bubble Tea - Dosa Factory
  3. Steak Sammy - Orinoco
  4. Burger topped with shortrib meat – Charlies Beer Garden
  5. Chicken Pad Thai - Thelonious Monkfish
  6. Honorable Mention: Cuban Sammy - Plough and Stars

Interns: We interviewed our intern and you won't believe what happened next

This summer we have an engineering intern from Tufts University (go Jumbos) joining the team. He’ll be working on internal projects including Rotorobot and a couple of new ideas. Here’s Phil in his own words.

Could you tell us a little bit about yourself?

Sure. I’m from Haverhill, MA originally so I’d call Boston home. I’m currently attending Tufts University and pursuing a BA in both Computer Science and Cognitive Science. At Tufts, I’m also working with the linguistics department on a couple of research projects surrounding the structure of the mental lexicon.

Where can we find you outside of work and school?

I’ve been playing Rugby at Tufts for the past few years so probably on the pitch, or maybe relaxing in my hammock with a book and an IPA.

What’s been the hardest part about learning PHP and Symfony2?

The hardest parts about learning Symfony2 have been recognizing how the many components of the framework fit together, and allowing the framework to take care of some of the heavy lifting. It was a leap to go from hacking away with straight PHP to designing an application, keeping both structure and modularity in mind.

Which computer science course has helped the most in transitioning to “real world” programming?

The computer science curriculum at Tufts has definitely helped me make the transition into real world programming. In particular, the course: Comp20 - Introduction to Web Development has given me exposure to the many tools that are used in the creation of web applications.

What technology/language/framework/etc. are you excited to learn more about?

This summer I’m excited to learn more about back end programming, the SQL language in particular as well as learning Bash more in depth so I can improve my use of the shell.

So far, what’s your favorite lunch spot been?

My favorite lunch spot so far has definitely been Orinoco in Harvard Square. I will buy some of their hot sauce by the summers end.

And finally, movie quote you live by?

“Crying: Acceptable only at funerals and the Grand Canyon”

For the uninitiated, Orinoco has an authentic Venezuelan hot sauce which has been known to destroy even veteran hot sauce connoisseurs. Here’s Phil deciding to take the plunge:

Are You a Developer? Know a Developer? We're hiring!

As we continue to expand in 2015 we’re looking to add another developer to our team.  Currently we’re seeking a junior level engineer to join us!  A few attributes of a person that we’re looking for:

  1. 1-2 years of experience with MVC based frameworks (we use Symfony2)
  2. 1-2 years of real world experience
  3. Comfortable talking directly with clients, no account managers here!
  4. Works well in a team environment, but also self-managed.
A few of the perks:
  1. Flexible hours
  2. 100% paid health care (PPO)
  3. 401(k) with matching
  4. Company outings
For some more detailed information on the job please visit the posting.  If you are, or know, a developer who is looking for a new opportunity lets connect!