Giter VIP home page Giter VIP logo

two-factor's Introduction

Sample project with basic 2-factor authentication using Spring Security. The source code is in github.

The first factor is a standard login form (username and password), but any Spring Security login will work the same way. The second factor in this sample is a toy one (the user's favourite colour), but it is easy to change that bit into something more realistic. The key parts of the implementation are as follows.

Use a Special Role

The application resources are protected with an additional role that would not be present in a normal authentication:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
       ...
       .authorizeRequests().antMatchers("/factor/**").authenticated()
            .anyRequest().hasRole("FACTOR");
}

So there is a special role that protects all resources except "/factor/**", which is where we are going to handle the second factor.

Custom Access Denied Handler

An AccessDeniedHandler is used that checks for the special role, and redirects to a prompt for the additional information:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.requestCache().requestCache(requestCache)
        .and().exceptionHandling().accessDeniedHandler(accessDeniedHandler())
        ...;
}

Handler for the Extra Factor

A @Controller is provided that prompts the user for the extra factor and handles the response. The implementation here is super simple: it just presents the user with a form to type in their favourite colour:

@GetMapping("/factor")
public String factor() {
    return "factor";
}

If the favourite colour is "red" then they are authenticated, and the response is handled by a SavedRequestAwareAuthenticationSuccessHandler (just like a normal login success):

@PostMapping("/factor")
public void accept(@RequestParam String factor, Principal principal,
        HttpServletRequest request, HttpServletResponse response) throws Exception {
    if (!"red".equals(factor)) {
        response.sendRedirect("/factor?error=true");
        return;
    }
    Authentication successful = addFactorRole(principal);
    SecurityContextHolder.getContext().setAuthentication(successful);
    handler.onAuthenticationSuccess(request, response, successful);
}

For a real implementation you could do a token-based authentication (for instance) instead.

Saving the Request

We want to remember the user's original request across the whole authentication, and the default strategy provided by Spring Security discards the saved request after the first stage. So to extend its memory, we add a request cache and set it up so that only an authentication with the special role causes the saved request to be discarded:

@Bean
public RequestCache savedRequestCache() {
    return new HttpSessionRequestCache() {
        @Override
        public void removeRequest(HttpServletRequest currentRequest,
                HttpServletResponse response) {
            Authentication authentication = SecurityContextHolder.getContext()
                    .getAuthentication();
            if (authentication != null && authentication.getAuthorities()
                    .contains(new SimpleGrantedAuthority("ROLE_FACTOR"))) {
                super.removeRequest(currentRequest, response);
            }
        }
    };
}

two-factor's People

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.