Showing posts with label spring-mvc. Show all posts

Spring security & subdomains

As previously mentioned, I have been working with a Spring MVC app that has had to deal with multiple subdomains for the one app (in other words, the subdomain really needs to just be considered as part of the normal URL path in all routing/security configuration and concerns).

Having gone through the details on how to make the @Controller and @RequestMapping routing to play nicely with subdomains, here is a quick overview of how to handle subdomains in Spring security.


A custom matcher

The main thing we really need to handle with security, is how to configure Spring-security so we can define permissions for URLs that include the subdomain.

Normally, Spring MVC permissions looks something like this:

As you can see, this just specifies a URL path to authenticate.


The specific details of how you implement the matcher exactly will be dependent on your applications approach to identifying and extracting the subdomain (maybe from http request, maybe just use a regex on the request etc)

As you can see above, the matcher we have created is just a convenient wrapper around another two spring matchers to let you match easily on both the full URL and subdomain.

Now, with a little convenience method, we can make some pretty nice Spring security configuration:

As you can see, the subdomain makes a difference to the permissions and who should access the two /dashboard/ URLs in the different contexts, but with the above simple code, we can make some pretty convenient & readable configuration to take subdomains into account.

Spring MVC & custom routing conditions

I have recently been building a Spring MVC app (well, actually using the Spring Boot project - which is quite nice in parts, and crazy frustrating in others - but the underlying mechanics are the same).  The application is actually a re-build of another application, so it has involved a lot of playing and exploring Spring source code to try and replicate the apps functionality like for like.

One of the first things I found, was that Spring doesn't really cater for the concept of a single app running on different sub-domains.  I assume the thinking is that you would build separate applications for different sub-domains, but in this case, we just have a single app.

There are two main speed-bumps I have come across so far:
  1. Controller routing based on subdomain
  2. Security considerations based on subdomain

Basically, as you can probably imagine, once you have subdomains on a single web application, the URL path is no longer unique (e.g. http://automateddeveloper.blogspot.com/ is clearly not the same as http://blogspot.com/ )


The rest of this post, I will look at the routing element of it. I will do another post later in the week about the Spring security stuff (I haven't solved all of that yet - but got far enough to make it work).


Understanding the subdomain

The first thing you need to sort out is a common and consistent way to determine the subdomain of any given request. There are a variety of ways to do this, for example, you could parse it from the request in apache and set a header, so your app doesn't have to worry about it, or you could just parse it from the request object server name. I will assume you have some bean/service/helper class to do this everywhere (although for now we only need it in one place).


An annotation

First up, we need a new annotation, that we can easily apply to a Controller, just like we would use the @RequestMapping - at the moment, the nice built in Spring RequestMapping handling allows you to define a URL path (plus other bits and pieces) to map a request to a URL to a given controller & method - what we want is to also specify the subdomain element of the requested URL

Defining an annotation is simple:

For the sake of simplicity of this example, I will only allow it to be used at class level (so no method based subdomain routing - but that will be pretty easy to do once you have understood the rest of the post).  You will also note that the value is defined as a String array, this will allow us to define mappings to multiple subdomains if needed.


The mapping condition

So, that was easy. Obviously, at this point the annotation doesn't actually do anything - you can add it to all the controllers you like, but it won't actually make any difference to your request routing.

To get our new annotation involved, we can implement something called a RequestCondition.  This is exactly what it sounds like, Spring lets you implement additional request conditions that must be satisfied for a request mapping.

The condition could be based on any logic you like, but in our case we just simply need to check for an annotation and then examine the value provided.  If the annotation value matches our incoming request then the condition is met, easy!  Returning the condition indicates to Spring that the condition has been met, returning the null value indicates that the condition is not met.


Adding the condition to the mapping handler

Usually, we would use the standard Spring RequestMappingHandlerMapping to handle all the routing of requests based on the URLs, but now we need to also ask Spring to consider our new custom condition from above.

This is a simple case of extending the normal RequestMappingHandlerMapping class and adding our new condition as a custom condition.  Luckily, this is really easy:

Allwe are doing is checking to see if the handler class (our controller) has our new @Subdomain annotation and if it does, we register our new custom condition for consideration.



Basically..

That's really all there is to it - we can then decorate our controller class with @Subdomain("subdomain") and have them handle the routing of requests. 

As you may have noticed, this is a pretty nice pattern for any kind of custom routing you might want to use - the same template could be used for routing by any request info/header or any user info (e.g. routing requests to different controllers based on their logged in role etc)

Cream money management - A Side project

Cash rules everything around me, it's all about the money, dollar dollar bill yo



I have for some time been bemoaning the state of online banking in the UK offered by the major banks I have banked with. It feels like they just can't be bothered - they are confident that no-one is going to disrupt them so they just don't make any effort.

My current bank makes it almost impossible to manually pay off your own credit card online, and all it really offers is a list of transactions against an account - the only good thing it offers is the ability to download your transactions.

It's frustrating. They have so much information, but provide so little.  So I told my wife I would make us an app to make this better.

Features of the app are:

  • create multiple accounts to manage together
  • upload statement/transaction lists as exported from online bank providers
  • automatically categorise and tag as many imported transactions as possible based on a set of rules
  • using sensible full text search, attempt to categorise and tag any remaining transactions based on other similar transactions that have been tagged
  • allow manual tagging/categorisation of transactions (that will then feed back into later imports of transactions etc)
  • link together transaction groups - identify recurring transactions and group them so they can be automatically categorised and tagged and also provide alerts/warnings on changes in payments (e.g. if a recurring transaction suddenly increases in cost, then it likely suggests that a fixed price deal has come to an end etc, so the system identifies this and alerts the user to the change
  • easy filtering and cutting up of data based on category, tags, date, price, description etc.. basically anything
  • tonnes of charts to show the different cuts of data and interesting points


Securing your mobile API - Spring Security

Having recently posted an article on an approach to securing an API for a mobile app to use, here are the details of how something similar can be configured using Spring-MVC and Spring-Security (this post uses Java config - if you are un-familiar with Java config rather than XML then check out my previous post on the topic).


Basic webapp registration and authentication

The first thing we need is a basic web app that supports user registration and authentication.  I am not going to go into the details of how to build a Spring MVC app with basic security and users etc, so will assume you are familiar with basic Spring MVC architectures. For an example Spring webapp that supports user security and registration, you can check out one of my several random webprojects on GitHub.


As I am only looking at an API application - no web client right now - All I need to start with is to set up the security for registration and login:



Ok, so the above is my web security config - the configure() method is what is defining my URLs and the security - it's pretty basic, I state that anyone can access the resources (for css etc), the log-in and the sign-up and everything else should be authenticated.

The only parts of interest are:
  1. In the registerAuthentication() method, as well as the normal setting of UserServices and password encryptor, I am also adding a Remember Me Authentication provider
  2. In the configure() method on the formLogin component we are also setting a RemeberMeService
  3. We are setting @Order annotation on the class with value 2

This class basically just sets up the web part of the security, so all pretty straight forward.


API security configuration

For clarity and readability of code, I like to create separate configuration classes for the different aspects of security - Below is the security config for the API endpoints:



This file is a little more interesting, let's have a look at what is going on:
  1. First of all, we define @Order with value 1 - as you have probably guessed, this defines the order in which the security config is loaded/considered - we want the API security to kick in first
  2. In our configure() method, we first specify an ant matcher so the rules in this config only apply to URLs that start /api/
  3. We state that all requests to this pattern must be authenticated and apply a RememberMeAuthenticationFilter to run before the Basic authentication chain runs
  4. We also set the session management to be stateless - this refers to serverside sessions, as we don't want to retain server session state
  5. We then configure the Remember Me beans - this is all standard and as per the Spring guidelines here.  The only difference is that we have a custom TokenBasedRememberMeService - that we will look at later.


Security flow

Below is the basic security chain that we get as a result of the above confirmation
  1. Request comes in - we check if it matches /api/**
  2. If it does match, then all requests must be authenticated - and run the RememberMeAuthenticationFilter 
  3. The filter simply uses the RememberMeService and AuthenticationProvider to check the token/cookie value to see if it can pre-authenticate the request.
  4. If it has matched the URL but doesn't authenticate on the filter, then it will 403
  5. If the URL does not match /api/** then the request starts the second security config
  6. If the url matches the resources, sign-up, sign-in then allow the request to complete, otherwise require authentication, so (default spring behaviour) direct all other requests to the registered login page ("/")


Customising remember me

 So the good news is we have been able to re-use core Spring Security functionality so far, so no dubious hand-rolled solutions - We use the standard security chain, username/password authentication provider and Remember Me filter/provider. The only thing that we have to modify slightly is the RememberMeTokenService - the default behaviour for Remember Me assumes that the token will always be provided in a cookie (designed for auto-login websites if you tick "remember me"), and as we are extracting the token from the cookie and passing it in the request header instead, we need to modify the service class to grab it from the header.

As you can see, it's pretty simple - all we are doing is overriding the default extract cookie method so it looks in the request header instead.  I would really recommend you read through the source code for the RememberMe classes - starting with the filter - and seeing what is actually happening between the Filter, token service and auth provider, it's pretty clear to read and will help get a good understanding of what is going on.


Caveats

There are a few things to consider here:
  • This is fairly basic security - requests should be made over https to prevent man-in-the-middle attacks, alternatively look at a solution like Amazon use whereby the token isn't passed, rather it is used to hash the request body which is then checked on the server side (prevent the need for sending the user token every request)
  • This is currently open to anyone to use/build against - there aren't any checks for app key/secret etc - so you would probably want to build that in to prevent other parties building apps against the api and getting a user token in the same way.
  • I'm not a security expert - this is just my interpretation of the Google guidelines using Spring Securities RememberMe classes. This is really just a thought experiment, getting up to speed with how Spring Security works in more details and experimenting with mobile app fun. Use at your own risk..

Securing your API for mobile access

So I have been thinking about potential options regarding securing a server side API for use by mobile apps. No matter what question you ask on the stack exchange network, the answer will always come back as "you should really use oauth", which I guess we should consider as a half truth.

Having used OAuth on several occasions as a client (accessing Facebook/Twitter/LinkedIn/GitHub etc), it was naturally the first option that came to mind for securing my API.


My requirements right now are simple:
  • I am experimenting building an Android mobile app that will use a server API (webapp & API will be built using Java & Spring stack)
  • The app I am experimenting is mobile-only (no web client)
  • It is not going to become a public API (e.g. won't be supporting other apps/sites)


I guess the key point is that I only intend to expose the API to my mobile app, and not have lots of comsumers of the API - and given the complexity of implementing OAuth, it seemed like it would be overkill as a solution.  A big benefit of OAuth is that it supports client/application keys.


So I started looking around for other ideas as to how to do this - I was (and still am) curious as to how Twitter/Instagram secure their APIs for their own applications - I know that the Twitter API is secured for public use using OAuth, but the interesting question is how they secure their own application key/secret. The problem with mobile apps is that an application key needs to be stored on the device - and whilst Twitter offers severely throttled API access using OAuth (register an application, get a secret app key etc), their own apps are obviously not throttled, so it seems like it would be a challenge to keep their application key secured, as if its in the app code, then its subject to de-compilation.

Anyway, getting close to resigning to the fact that I was going to have to use OAuth I came across this one-pager from Google. The guide suggests a much simplified approach with the following basic steps:

  • Build an webapp on your server that has a login page 
  • From your mobile app, embed a WebView of the login page
  • Upon login to your app, return a cookie with a token value that can be used to log in your user on future requests - ideally re-using your frameworks Remember-Me type services so not to have to hand-roll your own
  • On every API request include the token in your request header to authenticate (again using the Remember Me services)

The fact that it was a suggested approach from Google is pretty good, and it's a tonne simpler than negotiating the OAuth dance, so I thought I would have a look at getting this setup.


This is all good - but really, the advice to use OAuth is a half-truth, as if you ever have to scale your application, and think you might one day have/want to open it up do other developers/clients then OAuth is the way to go - You won't get much love from third-party developers with a non-standard approach to securing your API.


So.. how can it be done with Spring? I will cover that in my next post later this/next week!

Spring MVC 4.0

I have had a post coming for some time on my thoughts experience in starting to play with the changes that come as part of the latest major upgrade to the Spring suite.

There are lots of changes, that were announced at last year's Spring One event - including a flashy new spring.io website and several new packages to the framework such as Spring Boot (which they describe as an oppionated way to start building Spring apps - basically out of the box components that reduce work, but configured to Spring's tastes and conventions).



The interesting parts for me are in Spring MVC (as that is where I don most of my Spring dev) - most notably, the ability to write Spring apps in pure Groovy is of interest (as I do a lot of Groovy dev, and once you get used to the luxuries of its collection based closure functions then its hard to go back!) and also the ability to now configure the Spring Security stuff also entirely programatically (my previous attempt of pure code config spring app were thwarted only by having to use XML configuration for the security).

I am yet to convert an app to Groovy, but I have created a basic web app using the Spring 4.0 Milestone releases and converted the security config to code.  Full source code of the webapp is on github.

I will stick that up on GitHub soon, and when I do I will write in more detail about it (I also played around with LESS on that project and configured MAven/Eclipse to build the LESS/CSS files nicely, which I will also write up soon)

As it happens, I also stuck the demo app up on cloud hosting service AppFog.com (given that CloudFoundry is no longer with us in it's free form.. which kinda sucks, as that was really nice). It's by no means a complete app, and doesn't really do anything - just lets you connect your Facebook/Twitter accounts and see all your contacts etc - but as you can see - there is a lot of filler text and the LogOut link is always in the navbar etc.. But anyway, its here, for now..

Spring 4 App homepage


Spring 4 App Dashboard


  http://socialcrm.eu01.aws.af.cm/