Skip to content

Latest commit

 

History

History
150 lines (125 loc) · 4.73 KB

README.adoc

File metadata and controls

150 lines (125 loc) · 4.73 KB

Add a Welcome Page

In this section we modify the simple app we just built, by adding an explicit link to login with Facebook. Instead of being redirected immediately, the new link will be visible on the home page, and the user can choose to login or to stay unauthenticated. Only when the user has clicked on the link will he be shown the secure content.

Conditional Content in Home Page

To render some content conditional on whether the user is authenticated or not we could use server side rendering (e.g. with Freemarker or Tymeleaf), or we can just ask the browser to to it, using some JavaScript. To do that we are going to use AngularJS, but if you prefer to use a different framework, it shouldn’t be very hard to translate the client code.

To get started with AngularJS we need to mark the HTML <body> as a Angular app container:

index.html
<body ng-app="app" ng-controller="home as home">
...
</body>

and the <div> elements in the body can be bound to a model that controls which parts of it are displayed:

index.html
<div class="container" ng-show="!home.authenticated">
	Login with: <a href="/login">Facebook</a>
</div>
<div class="container" ng-show="home.authenticated">
	Logged in as: <span ng-bind="home.user"></span>
</div>

This HTML sets us up with a need for a "home" controller that has an authenticated flag, and a user object describing the authenticated user. Here’s a simple implementation of those features (drop them in at the end of the <body>):

index.html
<script type="text/javascript" src="/webjars/angularjs/angular.min.js"></script>
<script type="text/javascript">
  angular.module("app", []).controller("home", function($http) {
    var self = this;
    $http.get("/user").success(function(data) {
      self.user = data.userAuthentication.details.name;
      self.authenticated = true;
    }).error(function() {
      self.user = "N/A";
      self.authenticated = false;
    });
  });
</script>

Server Side Changes

For this to work we need some changes on the server side. The "home" controller needs an endpoint at "/user" that describes the currently authenticated user. That’s quite easy to do, e.g. in our main class:

SocialApplication
@SpringBootApplication
@EnableOAuth2Sso
@RestController
public class SocialApplication {

  @RequestMapping("/user")
  public Principal user(Principal principal) {
    return principal;
  }

  public static void main(String[] args) {
    SpringApplication.run(SocialApplication.class, args);
  }

}

Note the use of @RestController and @RequestMapping and the java.util.Principal we inject into the handler method.

Warning
It’s not a great idea to return a whole Principal in a /user endpoint like that (it might contain information you would rather not reveal to a browser client). We only did it to get something working quickly. Later in the guide we will convert the endpoint to hide the information we don’t need the browser to have.

This app will now work fine and authenticate as before, but without giving the user a chance to click on the link we just provided. To make the link visible we also need to switch off the security on the home page by adding a WebSecurityConfigurer:

SocialApplication
@SpringBootApplication
@EnableOAuth2Sso
@RestController
public class SocialApplication extends WebSecurityConfigurerAdapter {

  ...

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .antMatcher("/**")
      .authorizeRequests()
        .antMatchers("/", "/login**", "/webjars/**")
        .permitAll()
      .anyRequest()
        .authenticated();
  }

}

Spring Boot attaches a special meaning to a WebSecurityConfigurer on the class that carries the @EnableOAuth2Sso annotation: it uses it to configure the security filter chain that carries the OAuth2 authentication processor. So all we need to do to make out home page visible is to explicitly authorizeRequests() to the home page and the static resources it contains (we also include access to the login endpoints which handle the authentication). All other requests (e.g. to the /user endpoint) require authentication.

With that change in place the application is complete, and if you run it and visit the home page you should see a nicely styled HTML link to "login with Facebook". The link takes you not directly to Facebook, but to the local path that processes the authentication (and sends a redirect to Facebook). Once you have authenticated you get redirected back to the local app, where it now displays your name (assuming you have set up your permissions in Facebook to allow access to that data).