The new Certification Class of REST With Spring is out:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we’ll secure a REST API with OAuth and consume it from a simple AngularJS client.

The application we’re going to build out will consist of four separate modules:

  • Authorization Server
  • Resource Server
  • UI implicit – a front end app using the Implicit Flow
  • UI password – a front end app using the Password Flow

Further reading:

Simple AngularJS Front-End for a REST API

A quick intro to consuming a RESTful API from AngularJS.

Read more

Using JWT with Spring Security OAuth

A guide to using JSON Web Tokens with both symmetric and asymmetric signing in Spring Security OAuth.

Read more

OAuth2 for a Spring REST API – Handle the Refresh Token in AngularJS

We learned how to store the Refresh Token in an AngularJS client app, how to refresh an expired Access Token and how to leverage the Zuul proxy.

Read more

2. The Authorization Server

First, let’s start setting up an Authorization Server as a simple Spring Boot application.

2.1. Maven Configuration

We’ll set up the following set of dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>    
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
</dependency>  
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>${oauth.version}</version>
</dependency>

Note that we’re using spring-jdbc and MySQL because we’re going to use a JDBC backed implementation of the token store.

2.2. @EnableAuthorizationServer

Now, let’s start configuring the authorization server responsible for managing access tokens:

@Configuration
@EnableAuthorizationServer
public class AuthServerOAuth2Config
  extends AuthorizationServerConfigurerAdapter {
 
    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(
      AuthorizationServerSecurityConfigurer oauthServer) 
      throws Exception {
        oauthServer
          .tokenKeyAccess("permitAll()")
          .checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) 
      throws Exception {
        clients.jdbc(dataSource())
          .withClient("sampleClientId")
          .authorizedGrantTypes("implicit")
          .scopes("read")
          .autoApprove(true)
          .and()
          .withClient("clientIdPassword")
          .secret("secret")
          .authorizedGrantTypes(
            "password","authorization_code", "refresh_token")
          .scopes("read");
    }

    @Override
    public void configure(
      AuthorizationServerEndpointsConfigurer endpoints) 
      throws Exception {
 
        endpoints
          .tokenStore(tokenStore())
          .authenticationManager(authenticationManager);
    }

    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource());
    }
}

Note that:

  • In order to persist the tokens, we used a JdbcTokenStore
  • We registered a client for the “implicit” grant type
  • We registered another client and authorized the “password“, “authorization_code” and “refresh_token” grant types
  • In order to use the “password” grant type we need to wire in and use the AuthenticationManager bean

2.3. Data Source Configuration

Next, let’s configure our data source to be used by the JdbcTokenStore:

@Value("classpath:schema.sql")
private Resource schemaScript;

@Bean
public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {
    DataSourceInitializer initializer = new DataSourceInitializer();
    initializer.setDataSource(dataSource);
    initializer.setDatabasePopulator(databasePopulator());
    return initializer;
}

private DatabasePopulator databasePopulator() {
    ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
    populator.addScript(schemaScript);
    return populator;
}

@Bean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
    dataSource.setUrl(env.getProperty("jdbc.url"));
    dataSource.setUsername(env.getProperty("jdbc.user"));
    dataSource.setPassword(env.getProperty("jdbc.pass"));
    return dataSource;
}

Note that, as we are using JdbcTokenStore we need to initialize database schema, so we used DataSourceInitializer – and the following SQL schema:

drop table if exists oauth_client_details;
create table oauth_client_details (
  client_id VARCHAR(255) PRIMARY KEY,
  resource_ids VARCHAR(255),
  client_secret VARCHAR(255),
  scope VARCHAR(255),
  authorized_grant_types VARCHAR(255),
  web_server_redirect_uri VARCHAR(255),
  authorities VARCHAR(255),
  access_token_validity INTEGER,
  refresh_token_validity INTEGER,
  additional_information VARCHAR(4096),
  autoapprove VARCHAR(255)
);

drop table if exists oauth_client_token;
create table oauth_client_token (
  token_id VARCHAR(255),
  token LONG VARBINARY,
  authentication_id VARCHAR(255) PRIMARY KEY,
  user_name VARCHAR(255),
  client_id VARCHAR(255)
);

drop table if exists oauth_access_token;
create table oauth_access_token (
  token_id VARCHAR(255),
  token LONG VARBINARY,
  authentication_id VARCHAR(255) PRIMARY KEY,
  user_name VARCHAR(255),
  client_id VARCHAR(255),
  authentication LONG VARBINARY,
  refresh_token VARCHAR(255)
);

drop table if exists oauth_refresh_token;
create table oauth_refresh_token (
  token_id VARCHAR(255),
  token LONG VARBINARY,
  authentication LONG VARBINARY
);

drop table if exists oauth_code;
create table oauth_code (
  code VARCHAR(255), authentication LONG VARBINARY
);

drop table if exists oauth_approvals;
create table oauth_approvals (
	userId VARCHAR(255),
	clientId VARCHAR(255),
	scope VARCHAR(255),
	status VARCHAR(10),
	expiresAt TIMESTAMP,
	lastModifiedAt TIMESTAMP
);

drop table if exists ClientDetails;
create table ClientDetails (
  appId VARCHAR(255) PRIMARY KEY,
  resourceIds VARCHAR(255),
  appSecret VARCHAR(255),
  scope VARCHAR(255),
  grantTypes VARCHAR(255),
  redirectUrl VARCHAR(255),
  authorities VARCHAR(255),
  access_token_validity INTEGER,
  refresh_token_validity INTEGER,
  additionalInformation VARCHAR(4096),
  autoApproveScopes VARCHAR(255)
);

Note that we don’t necessarily need the explicit DatabasePopulator bean – we could simply use a schema.sql – which Spring Boot makes use of by default.

2.4. Security Configuration

Finally, let’s secure the Authorization Server.

When the client application needs to acquire an Access Token, it will do so after a simple form-login driven auth process:

@Configuration
public class ServerSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) 
      throws Exception {
        auth.inMemoryAuthentication()
          .withUser("john").password("123").roles("USER");
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() 
      throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/login").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin().permitAll();
    }
}

A quick note here is that the form login configuration isn’t necessary for the Password flow – only for the Implicit flow – so you may be able to skip it depending on what OAuth2 flow you’re using.

3. The Resource Server

Now, let’s discuss the resource server; this is essentially the REST API which we ultimately want to be able to consume.

3.1. Maven Configuration

Our Resource Server configuration is the same as the previous Authorization Server application configuration.

3.2. Token Store Configuration

Next, we will configure our TokenStore to access the same database that authorization server uses to store access tokens:

@Autowired
private Environment env;

@Bean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
    dataSource.setUrl(env.getProperty("jdbc.url"));
    dataSource.setUsername(env.getProperty("jdbc.user"));
    dataSource.setPassword(env.getProperty("jdbc.pass"));
    return dataSource;
}

@Bean
public TokenStore tokenStore() {
    return new JdbcTokenStore(dataSource());
}

Note that, for this simple implementation, we’re sharing the SQL backed token store even though the Authorization and Resource servers are separate applications.

The reason, of course, is that the Resource Server needs to be able to check the validity of the access tokens issued by the Authorization Server.

3.3. Remote Token Service

Instead of using a TokenStore in our Resource Server, we can use RemoteTokeServices:

@Primary
@Bean
public RemoteTokenServices tokenService() {
    RemoteTokenServices tokenService = new RemoteTokenServices();
    tokenService.setCheckTokenEndpointUrl(
      "http://localhost:8080/spring-security-oauth-server/oauth/check_token");
    tokenService.setClientId("fooClientIdPassword");
    tokenService.setClientSecret("secret");
    return tokenService;
}

Note that:

  • This RemoteTokenService will use CheckTokenEndPoint on Authorization Server to validate AccessToken and obtain Authentication object from it.
  • The can be found at AuthorizationServerBaseURL +”/oauth/check_token
  • The Authorization Server can use any TokenStore type [JdbcTokenStore, JwtTokenStore, …] – this won’t affect the RemoteTokenService or Resource server.

3.4. A Sample Controller

Next, let’s implement a simple controller exposing a Foo resource:

@Controller
public class FooController {

    @PreAuthorize("#oauth2.hasScope('read')")
    @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}")
    @ResponseBody
    public Foo findById(@PathVariable long id) {
        return 
          new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4));
    }
}

Note how the client needs the “read” scope to access this Resource.

We also need to enable global method security and configure MethodSecurityExpressionHandler:

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class OAuth2ResourceServerConfig 
  extends GlobalMethodSecurityConfiguration {

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }
}

And here’s our basic Foo Resource:

public class Foo {
    private long id;
    private String name;
}

3.5. Web Configuration

Finally, let’s set up a very basic web configuration for the API:

@Configuration
@EnableWebMvc
@ComponentScan({ "org.baeldung.web.controller" })
public class ResourceWebConfig extends WebMvcConfigurerAdapter {}

4. Front end – Password Flow

We’re now going to look at a simple front-end AngularJS implementation for the client.

We’re going to be using the OAuth2 Password flow here – which is why this is just a proof of concept, not a production ready application. You’ll notice that the client credentials are exposed to the front end – which is something we’ll address in a future article.

Let’s start with the two simple pages – “index” and “login”; once a user provides their credentials, the front-end JS client uses them to acquire an Access Token from Authorization Server.

4.1. Login Page

Here is our simple login page:

<body ng-app="myApp" ng-controller="mainCtrl">
<h1>Login</h1>
<label>Username</label><input ng-model="data.username"/>
<label>Password</label><input type="password" ng-model="data.password"/>
<a href="#" ng-click="login()">Login</a>
</body>

4.2. Obtain Access Token

Now, let’s see how to obtain our access token:

var app = angular.module('myApp', ["ngResource","ngRoute","ngCookies"]);
app.controller('mainCtrl', 
  function($scope, $resource, $http, $httpParamSerializer, $cookies) {
    
    $scope.data = {
        grant_type:"password", 
        username: "", 
        password: "", 
        client_id: "clientIdPassword"
    };
    $scope.encoded = btoa("clientIdPassword:secret");
    
    $scope.login = function() {   
     	var req = {
            method: 'POST',
            url: "http://localhost:8080/spring-security-oauth-server/oauth/token",
            headers: {
                "Authorization": "Basic " + $scope.encoded,
                "Content-type": "application/x-www-form-urlencoded; charset=utf-8"
            },
            data: $httpParamSerializer($scope.data)
        }
        $http(req).then(function(data){
            $http.defaults.headers.common.Authorization = 
              'Bearer ' + data.data.access_token;
            $cookies.put("access_token", data.data.access_token);
            window.location.href="index";
        });   
   }    
});

Note that:

  • To get an Access Token we send a POST to the “/oauth/token” endpoint
  • We’re using the client credentials and Basic Auth to hit this endpoint
  • We’re then sending the user credentials along with the client id and grant type parameters URL encoded
  • After we obtain the Access Token – we store it in a cookie

The cookie storage is especially important here, because we’re only using the cookie for storage purposes and not to drive the authentication process directly. This helps protect against cross-site request forgery (CSRF) type of attacks and vulnerabilities.

4.3. The Index Page

Here is our simple index page:

<body ng-app="myApp" ng-controller="mainCtrl">
<h1>Foo Details</h1>
<label>ID</label><span>{{foo.id}}</span>
<label>Name</label><span>{{foo.name}}</span>
<a href="#" ng-click="getFoo()">New Foo</a>
</body>

4.4. Authorize Client Requests

As we will need to authorize our requests to the resource using our access token, we will append a simple authorization header with access token:

var isLoginPage = window.location.href.indexOf("login") != -1;
if(isLoginPage){
    if($cookies.get("access_token")){
        window.location.href = "index";
    }
} else{
    if($cookies.get("access_token")){
        $http.defaults.headers.common.Authorization = 
          'Bearer ' + $cookies.get("access_token");
    } else{
        window.location.href = "login";
    }
}

If no cookie is found, the user will be redirected to login page.

5. Front End – Implicit Grant

Now, let’s take a look at our client application that uses the implicit grant.

Our client application is a separate module that tries to access resources server after obtaining an access token from authorization server using implicit grant flow.

5.1. Maven Configuration

Here are pom.xml dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Note: we didn’t need OAuth dependency – as we will handle it using AngularJS directive OAuth-ng which can connect to OAuth2 server with implicit grant flow.

5.2. Web Configuration

And here is our simple web configuration:

@Configuration
@EnableWebMvc
public class UiWebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public static PropertySourcesPlaceholderConfigurer 
      propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Override
    public void configureDefaultServletHandling(
      DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        super.addViewControllers(registry);
        registry.addViewController("/index");
        registry.addViewController("/oauthTemplate");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
          .addResourceLocations("/resources/");
    }
}

5.3. The Home Page

Next, here is our home page:

OAuth-ng directive needs:

  • site: authorization server URL
  • client-id: application client id
  • redirect-uri: the URI to be redirected to after obtaining an access token from the authorization server
  • scope: privilege requested from Authorization Server
  • template: rendered custom HTML template
<body ng-app="myApp" ng-controller="mainCtrl">
    <oauth
      site="http://localhost:8080/spring-security-oauth-server"
      client-id="clientId"
      redirect-uri="http://localhost:8080/spring-security-oauth-ui-implicit/index"
      scope="read"
      template="oauthTemplate">
    </oauth>

<h1>Foo Details</h1>
<label >ID</label><span>{{foo.id}}</span>
<label>Name</label><span>{{foo.name}}</span>
</div>
<a href="#" ng-click="getFoo()">New Foo</a>

<script 
  src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js">
</script>
<script 
  src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-resource.min.js">
</script>
<script 
  src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-route.min.js">
</script>
<script 
  src="https://cdnjs.cloudflare.com/ajax/libs/ngStorage/0.3.9/ngStorage.min.js">
</script>
<script th:src="@{/resources/oauth-ng.js}"></script>
</body>

Note how we’re using the OAuth-ng directive to obtain the Access Token.

Also, here’s the simple oauthTemplate.html:

<div>
  <a href="#" ng-show="show=='logged-out'" ng-click="login()">Login</a>
  <a href="#" ng-show="show=='denied'" ng-click="login()">Access denied. Try again.</a>
</div>

5.4. AngularJS App

And here is our AngularJS app:

var app = angular.module('myApp', ["ngResource","ngRoute","oauth"]);
app.config(function($locationProvider) {
  $locationProvider.html5Mode({
      enabled: true,
      requireBase: false
    }).hashPrefix('!');
});

app.controller('mainCtrl', function($scope,$resource,$http) {
    $scope.$on('oauth:login', function(event, token) {
        $http.defaults.headers.common.Authorization= 'Bearer ' + token.access_token;
    });

    $scope.foo = {id:0 , name:"sample foo"};
    $scope.foos = $resource(
      "http://localhost:8080/spring-security-oauth-resource/foos/:fooId", 
      {fooId:'@id'});
    $scope.getFoo = function(){
        $scope.foo = $scope.foos.get({fooId:$scope.foo.id});
    } 
});

Note how, after obtaining the Access Token, we’re using it via the Authorization header whenever we consume protected resources from within the Resource Server.

6. Conclusion

We learned how to authorize our application using OAuth2.

The full implementation of this tutorial can be found in the GitHub project – this is an Eclipse based project, so it should be easy to import and run as it is.

Go deeper into building a REST API with Spring:

>> CHECK OUT THE CLASSES

  • Felipe Borella

    Hi

    How can I run the four modules and test the flow?

    Thanks

    • Hey Felipe – you just need to deploy the modules into a web server together – I’m simply using Eclipse with a Tomcat server for local work. Now – they’re separate apps, so with a bit of configuration they can of course run separately – but yeah, the simplest way to do it is to deploy them together. Cheers,
      Eugen.

      • Felipe Borella

        Thanks! It worked! o/

        • Sounds good, happy to help. Cheers,
          Eugen.

          • Craig Doremus

            Sorry to barge into the middle of this thread, but the OAuth-ng directive seems to have disappeared from the web. Any other ideas?

          • No idea Craig – I’m not really keeping a close eye on the front-end ecosystem and AngularJS.
            One thing I’d recommend is to reach out to the team directly – I’m sure there’s an official channel for that. Cheers,
            Eugen.

  • Felipe Borella

    Hey Eugen!

    I’m trying to run the spring-security-oauth-ui-implicit module.
    When I click on the Login Button, I got an error.

    Whitelabel Error Page
    This application has no explicit mapping for /error, so you are seeing this as a fallback.
    Thu Nov 26 10:20:28 BRST 2015
    There was an unexpected error (type=Forbidden, status=403).
    Access Denied

    Any idea?

    Thanks
    Felipe

    • Hey Felipe – I can reproduce the problem – looking into it. Cheers,
      Eugen.

      • Felipe Borella

        I don’t know whats happends. The error persist.
        There was an unexpected error (type=Forbidden, status=403).
        Access Denied

        Thanks

        • Hey Felipe – I can’t reproduce this one – I’m able to log in and consume the API just fine. If you have the exact steps to reproduce it – go ahead and open an issue on the github project and we’ll track it there. Thanks,
          Eugen.

        • Arthur Carvalho

          Felipe, this error happened to me, you’re probably with the tomcat port other than 8081

          • Felipe Borella

            Correct! Where are you from? Brazil?

          • Arthur Carvalho

            Brazil! 🙂

      • Felipe Borella

        It works now! Thanks

  • maruf571

    It would be great if you provide some demo data with schema

    • Well, there is an operation to create a new resource after login, so that’s a quick way to create some data. What other types of data would be help here? Cheers,
      Eugen.

  • Johhny

    Hi Eugen,

    What about acces_token refresh? What happens when the acces_token expires, in the password flow scenario?

    • Hey Johny – so that depends on if the Resource Server is issuing refresh tokens (or not). If not – then you really don’t have any other option than go through the process again and get a new token. That’s of course going to inform your decision regarding the expiration period for these access tokens. But – if you do have refresh tokens – than you’ll use that to get a new access token. That way – access tokens can be very short-lived and it’s only the refresh token that is longer lived.
      Of course that also leads into things like – how do you store the refresh token safely, etc – but that’s way beyond this introductory article. I’m considering making that – Advanced API Security – a topic for my next webinar (I’m getting a lot of questions similar to yours). But – for now – hope that helps. Cheers,
      Eugen.

      • Johnny

        Well, that was the interesting question: how to store refresh tokens in order not to have security issues? It seems that I’ll have to wait until the Advanced API Security is written. Thanks.

  • Gaurav Dighe

    Hi Eugene,

    1. How to integrate User and Role saved in Database.
    2. Here you have your HTML in the same project. How to integrate it with login page kept in different AngularJS project? Say my api at localhost:8080 and ui at localhost/login

    • Hey Gaurav,
      1. Have a look at my registration tutorial for a working example – but very quickly, you’d simply use your own UserDetailsService
      2. That’s a complex issue, so I won’t get into all of it, but you need to look into the CORS support in Spring to allow your JS to consume the API across origins and then you of course also need to make sure that your front end points to the correct URLs where your API is deployed.
      Hope that helps. Cheers,
      Eugen.

  • Emil Ifrim

    Hi Eugen,

    What if the ResourceServer and the Authorization server run in the same application (they are one and the same server)? I did some minor changes by copying the OAuth2ResourceServerConfig next to the OAuth2AuthorizationServerConfig class and the implicit flow is not working anymore. It seems that the /login (whiltelabel form login) is not available anymore (protected). What is require in order to make it work in this configuration?

    • Hey Emil – that’s certainly a potential usecase that I considered for the article. I wanted the implementation to be entirely separated though. In your case, I’d have to look at the code before knowing what the problem is, so my suggestion is to post the full details on StackOverflow and then shoot me an email with the link to the question. Cheers,
      Eugen.

      • Euclides Junior

        Would be very nice to have a article on this.

  • Zaier

    Hi Eugen,
    I have a question is a CSRF-protection is needed in BackEnd security when I don’t use cookie from the FrontEnd Client (just sending requests in the header)?
    My clients are a mobile and an AngularJs clients .
    They take the body-json data sent back from server, they parse it to get the AccessToken and then every client has it own way to save it :
    “The JS client save it in the cookie where the android client will save it in a file-storage.”

    I think that CSRF protection is needed only with browser , because bad-user or attacker will try to stole the cookie from his-website and will try to make some users to make some POST/PUT/DELETE request to the backEnd that he want to attack.
    So if I have a good understanding “and I hope”, I think that communication from client to its server using headers is quite secure, but we only have to care about how to secure the storage placement of the Access-Token whether our client is a browser or mobile.

    I ask you this question because I knew that before the communication from the client to the server was a cookie-based “using JSession ” and sending this cookie for every request. But when I use the OAuth password flow everything has to change, and I think that we don’t need a CSRF security but we only need to protect the token saved on the client side.
    Is it right Sir Eugen 🙂
    Sorry about this long comment 🙂

    • Hey Zaier – that’s an interesting question.
      One aspect here is indeed cookies – which is the main way CSRF attacks are implemented. Cookies will be automatically send by the browser when a request is made that matches the criteria of that cookie. That’s why it is definitely a browser specific type of attack.
      However, authentication headers can also be sent automatically and can also identify the user within your system. So – cookies are not the only way to carry out a CSRF attack – no.
      Have a read of this article on the official Spring blog – it goes into more detail about that. Hope it helps. Cheers,
      Eugen.

  • Vinayaka Malya

    Hi Eugen,

    Can you please tell me how to store access token into db using xml appraoach. I am beginner in spring and in my project they have used InMemoryTokenStore but now we want to store it in the db. Please help me in this. It would be great if you provide some example on it.

    • So, the tokens are managed by the framework, but you have the option to provide a Token store when you’re setting up your configuration. That’s the standard way you would do that.
      As for a sample – that’s the way the configuration is set up in the Github project, so definitely have a look at that – it’s using a JDBC token store.
      Cheers,
      Eugen.

  • Iliescu Iulian-Alex

    Hi Eugen,

    How can I start the 4 projects together?
    Can I configure the IDE to do that?
    Or by script?

    Thanks

    • Hey Iulian – sure, that’s the way they’re meant to run. If you’re doing it from your IDE, you can simply have all 4 run in the same server. For instance, I’m using Eclipse and a Tomcat 8 server and everything runs smoothly. Cheers,
      Eugen.

  • Soufiane

    Hi Eugen,
    First i’d like to thank you for your amazing tutorial, it was pretty clear and simple and very efficient.
    Second, i have a question for you.
    I need to secure the access to some rest apis not from applications only, but also from and end-user, in case some one using the application that hosts the rest web services, attempts to access the web service via the url, i’d like to stop him if he doesn’t have the right to access it. do you think oauth 2.0 will satistfy this need. (The same application).

    • Hey Soufiane – first, I’m glad you’re enjoying the material.
      OAuth2 is very flexible, and as long as you’re running the right flow – yes, you should have authorization required for your API regardless of who accesses it.
      Hope that helps – and best of luck with the implementation. Cheers,
      Eugen.

      • Soufiane

        Hi Eugen,
        I tried to run the spring-security-oauth-server module, but i always get this FileNotFoundException:
        “class path resource [mytest.jks] cannot be opened because it does not exist”
        Though the jks file exists in the classpath.
        Cheers

        • That’s odd – I just ran everything and the file is there and should be fully accessible. If you still have problems running the system, go ahead and open an issue on Github with the full details and I’ll have another look. Cheers,
          Eugen.

          • Soufiane

            Hi Eugen, Robert and everyone else
            I did what robert suggested, and it worked.
            I ran the 4 applications on difference ports.
            The resource on 8081
            The server on 8082
            The implicit on 8083
            The password on 8084
            i configured the Html files on the new ports.
            I got a successful access to the page, when i attempted to retrieve some data, i was redirected to the authorization-server login page, successfully logged in, i authorized the access, i was given an access token and redirected to the implicit index page again, but when i tried to submit some data, i got nothing, no errors no response.
            This link below contains some screen-shots of the running 4 applications.
            Any help will be appreciated.
            Thanks in advance.

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

        • Hi! I had the same problem and I think that I found reason. In pom.xml of module spring-security-oauth-server is exclusion of all jks files (*.jks). After removing this block of code everything work great.

          • Soufiane

            I’ll try it as soon as possible.
            Thank you Robert.

  • Bro Bro

    Maybe I don’t understand something… but where I have to put may twitter or facebook api key and secret key?

    • There are a few options to do configuration when you need to manage keys. You can use an external property file and set that up on deployment. You could look at the new spring-cloud project for native support for this kind of scenario. You can use something else other than properties files for your sensitive configuration. Or you can go another route as well.
      There’s no single answer here, but I’d recommend looking at Spring Boot + Spring Cloud if you have that option.
      Hope it helps. Cheers,
      Eugen.

  • jhiguerafonseca

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘springSecurityFilterChain’ defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method ‘springSecurityFilterChain’ threw exception; nested exception is java.lang.IllegalStateException: @Bean method OAuth2ResourceServerConfig.tokenServices called as a bean reference for type [org.springframework.security.oauth2.provider.token.DefaultTokenServices] but overridden by non-compatible bean instance of type [com.sun.proxy.$Proxy52]. Overriding bean of same name declared in: class path resource [org/baeldung/config/OAuth2ResourceServerConfig.class]..any idea?? thanks

    • mohamed chaarana

      Hello , Excuse me ,since two day i search a solution to the same issue .
      I have an issue ”
      org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘springSecurityFilterChain’ defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method ‘springSecurityFilterChain’ threw exception; nested exception is java.lang.IllegalStateException: @Bean method OAuth2ResourceServerConfig.tokenServices called as a bean reference for type [org.springframework.security.oauth2.provider.token.DefaultTokenServices] but overridden by non-compatible bean instance of type [com.sun.proxy.$Proxy62]. Overriding bean of same name declared in: class path resource [org/baeldung/config/OAuth2ResourceServerConfig.class]

      in spring-security-oauth-resource .

      Can you help me please !

      • Hey Mohamed – that looks like an interesting context creation problem, but I’m afraid that’s not enough information to really diagnose it. Is there a sample project/test that you can point at where the problem exists? Cheers,
        Eugen.

        • mohamed chaarana

          Thank you Eugen for your reponse ,
          I resolved the probleme , but i forgot what it the issue 🙂 .
          THank very very much , you solved me due this post

          • Glad it worked out 🙂
            Cheers,
            Eugen.

          • Vasunath

            Hi Mohamed, Could you please let me know what the issue was and how it is resolved?

          • Kopax Anderson

            Could you please share how you solved this ?

  • Ignacio Cañon

    Hi Eugen,
    great article, as always!!
    I’m developing a very simple version of Oauth Authentication Server following your tutorial. I’ve developed a basic client app, and when it tries to call oauth auth server endpoint for initiating the authorization code flow it does not present the expected login page, but a trace of “DefaultOAuth2ExceptionRenderer : Written [error=”unauthorized”, error_description=”Full authentication is required to access this resource”] ” is displayed at console.
    Login endpoint it’s supposed to have free acces upon configuration, do you think I’m missing something?
    Thank you in advance.

  • Rubén Pahíno Verdugo

    HI Eugen,

    could you explain this method please?

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    oauthServer.tokenKeyAccess(“permitAll()”).checkTokenAccess(“isAuthenticated()”);
    }

    what are the tokenKeyAccess and checkTokenAccess?

    also, could you explain a little bit what do you mean with this afirmation? “this is just a proof of concept not a production ready application”.

    Lastly, if I develop a web and a native mobile application, is it correct to use the password grant flow on them, or should I use another flow?

    Thank you,
    Rubén

  • Abha

    Hi Eugen,
    Great Article ! So i was trying to implement the project as described. I am able to run the 4 servers on different ports. I get into the login page but i am not able to proceed from there. Can you provide the data i should use?

    • Hey Abha – have a look at the WebSecurityConfig – you’ll find some simple users to authenticate with there. Of course that’s an im-memory set for demo purposes, so use it as such. Cheers,
      Eugen.

  • Lev Merenkov

    Hi Eugen,
    I am thinking of taking your Authorization Server as a template for my application. I would need some means for testing it. I tried to use old good CURL for this but every time I try to issue a token request, I get the same response:
    {“error”:”invalid_request”,”error_description”:”Missing grant type”}

    I use a following command:
    curl -X POST -H -d “client_id=fooClientIdPassword&client_secret=secret&grant_type=password&username=john&password=123” http://localhost:8081/spring-security-oauth-server/oauth/token

    Nevertheless, when I try to login from your password flow app, everything works smoothly (i.e. auth server responses with the new token generated).
    Could you please tell me what do I do in a wrong way with Curl – do I miss some param? Seems like your web app does some tricks with the response prior to send it to auth server, I would be very thankful if you could explain how to achieve the same using Curl.

    • Hey Lev,
      From a high level look at your command, the syntax you’re using to pass parameters is the cause of your problems. The syntax should be: -d key1=val1 -d key2=val2. So – individual key value pairs, not one large String.
      Hope that helps. Cheers,
      Eugen.

      • Sebastian

        curl -X POST -d “client_id=clientIdPassword” -d “client_secret=secret” -d “grant_type=password” -d “username=john” -d “password=123” http://localhost:8080/oauth/token

        Does the above look right? I get the following response: {“error”:”unauthorized”,”error_description”:”Full authentication is required to access this resource”}

        • Looks right – yes. You’re missing Basic Auth though – keep in mind that this endpoint is secured with Basic Auth, using the client credentials as well. Cheers,
          Eugen.

  • muttonUp

    Hi Eugen,
    I wonder if I could ask your opinion about the pros and cons of using Springs own spring-security-(OAUTH, OAUTH2, SAML) versus spring-security-pac4j?

    • Well, there are many things to cover here, but I’d say simply the fact that it’s a non-standard project that’s of course a lot less active/maintained/used will tip the scale.

  • Vlad Neghina

    Any change of adapting this tutorial for Angular 2?

    • Hey Vlad, I did think about that, and it’s on the Content Calendar list. The reason it’s not high priority is simply that the focus of the article isn’t the Angular part, but the back-end implementation. But, yes, the upgrade is on the list. Cheers,
      Eugen.

  • Vetal

    Hi Eugen. Looks like good tutorial, but i wonder, that i can’t find tutorial without spring-boot. I belive, that it’s a cool feature, but it’s hide some stuff, needed for undestanding. I have a REST-project ( springMVC + spring security ), all configurated by using annotations, and i just want to add OAuth2 authentiction + authorization(password grant type, i think), by using spring-security-oauth library. Is there a big difference between configuration using spring-boot, and without it?

  • ojus kulkarni

    I am not getting how to do forgot password using angularJs and Spring Security with security question. so I will like for some help from anyone

    • Hey Ojus – given that your question is somewhat generic, I’m going to assume your main focus is how to do Security Questions.
      I don’t have a reference article about that on the site, but there is one in progress, based on one of the lessons in the course.
      Cheers,
      Eugen.

      • ojus kulkarni

        Ok please share the link once you complete that article.

  • Gary Waddell

    Hey Eugen,

    This post was very helpful to me, thank you!

    I have a couple of questions on the approach and in general that I am hoping are covered in the Master Class, but I will ask here none the less.

    1. Can I assume the master class explains the details of the DB schema for storing tokens etc and the purpose of each table you created? I only see one or two tables being populated during the flow.
    2. It appears Spring Security OAuth includes a /check_token endpoint on the Auth Server that seems to only be secured by the user ID and password. So could a hacker not consistently hit that URL trying to identify a valid token as the token is passed around between the client and the resource provider (ie potentially exposed?). Perhaps that is indeed enough security or would it make more sense to have that /check_token endpoint secured to only ADMIN roles?
    3. Since you are using the token store for the resource provider, is there any reason the resource provider does not communicate directly with the auth server to validate tokens instead of having reference to that JDBC token store?

    Thanks in advance and keep up the great work!
    Gary

    • Hey Gary,
      Sorry for the late response – I’ve been focused on the launch during these past couple of weeks.
      1. That’s an interesting idea; no – I haven’t detailed the tables in any lesson but I’m adding it on the bonus lessons list.
      2. Let’s take a step back here and start with a few notes.
      First – you can enable and disable that framework endpoint.
      Second – you can of course also fully control the authorization that’s required to hit the endpoint (including allowing only admins to hit it).
      One quick note also – when we’re configuring the auth of that specific URL, it’s not “secured with just user ID and password” – it’s secured with whatever authentication you have set up in your system.

      Now, coming back to the scenario you’re thinking of – if an Access Token is exposed, then the attacker would be able to use it to consume the API (as long as the token is valid). So – if that happens, the problem isn’t going to be this endpoint, but the entire system.
      And if they try to “guess” a token from scratch, that’s not going to be a good attack vector. For one – an attacker just generating a token and then checking if it’s valid that would simply be a brute-force attack.
      And of course they’d still need to know the user credentials as well – and if they know these, they can simply generate their own tokens, they don’t need to check existing one.

      3. When you say “communicate direct” what do you have in mind exactly? Using the API exposed by the Authorization Server? Or something else?

      Cheers,
      Eugen.

      • Gary Waddell

        Hey Eugen,

        No worries on the response. I appreciate you taking the time to respond and excited on the new course material as well. I am really enjoying the course.

        There were a couple of things here. I found it kind of confusing to figure out how to lock down the API for the check_token specifically for Admins only as it does not seem to follow the same approach as the WebSecurityConfigurerAdapter approach. I will continue to research this as I don’t expect you to answer every question. For now, I am just leaving that API exposed.

        With regards to the 3rd item, I am hoping the resource service can invoke the check_token API on the Authorization server without it having to use a TokenStore reference. The protected resource that is consuming the token does not have access to a database (oddly enough) so in order to validate the token, I was hoping to have the protected resource simply invoke the Authorization Server’s check_token endpoint in order to validate the token, and wondering if there are any reasons this may not be a good approach to follow?

        Thanks again!

        Regards,
        Gary

        • Glad you’re getting a lot out of the course.
          One quick note about locking down certain URI paths.
          Keep in mind that /oauth/check_token is simply a standard API, so you can secure it just as you’d secure any other.

          Now, moving on to your other question about the Resource Server.
          First, have a look at the Javadoc of the token store.
          You’ll notice that, even though from the name, the class is a store – which is a bit unfortunate – it’s not necessarily a store. It also have a critical responsibility of (simply put) retrieving the auth data out of the token.
          That’s why I’m using it here.
          Looking for a better approach though – since I agree, it is slightly confusing.

          Cheers,
          Eugen.

  • Fholisani Mashegana

    Hi Eugen,

    I downloaded the project from git and i am trying to run it using maven command “mvn spring-boot:run” however i get this exception…

    Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat servlet container

    Can you please explain how you run this project

    • Which exact project are you trying to run? There are several modules there and of course these run independently.
      Cheers,
      Eugen.

  • Sam

    Hi Eugen,

    I’m trying to integrate LDAP into this project, i need to authenticate a user using LDAP. I tried to change the method “globalUserDetails” of the WebSecurityConfig class as following:

    auth
    .ldapAuthentication()
    .userDnPatterns(“uid={0},ou=people”)
    .groupSearchBase(“ou=groups”)
    .contextSource()
    .ldif(“classpath:test-server.ldif”);

    But i’m getting errors regarding AuthenticationManager , can you help me where should I change the code?

    • Hey Sam – so what’s the exact exception you’re getting (the root cause)?
      Also, I’m assuming you had a look at the LDAP article – which of course looks at how to set things up in more detail. Cheers,
      Eugen.

  • P Kumar

    Hi @@baeldung:disqus ,
    I have googled 2 days but didn’t find a complete solution for registration and login using MySQL + Spring OAuth2. Could you please share the complete solution. This is a part of the solution and I am unable to convert it. Please help.

    • Hey Kumar – so, as it’s so often the case with custom development, you’ll first have to understand the building blocks of that solution and then you’ll be able to create it yourself. This article is one such building block. My registration series is another.
      But if you’re implementing a non-trivial scenario – you’re never going to find a full, start to finish solution to fit that exactly. And I’m not only referring to your example here, with Registration + MySQL + Spring OAuth2 – but in general.
      Hope that makes sense. Cheers,
      Eugen.

      • P Kumar

        Thanks Eugen… I do understand the modules, but my concern is the entity model is different in your “Rest Api Spring OAuth2” in comparision with the “Registration” (https://github.com/eugenp/spring-security-registration/tree/master/src/main/java/org/baeldung/persistence/model) series, if I am not wrong… Any way thanks for the tutorial… Still I am not getting the way to connect MySQL with this implementation.,.. Thanks again

        • Sure – these two are different tutorials, focused on different things. So, yes – you’re not wrong – the entities are different.
          Now, about “connecting to MySQL” – it depends on exactly what you’re trying to connect. Is it your entire app, or specifically the OAuth2 aspects? Cheers,
          Eugen.

  • Excellent article! Does this works with google, facebook and twitter as well?

    • Hey Oscar – that’s a good question, but in order to answer it I’ll have to take a step back.
      What this article shows you how to do is to set up the Authorization Server as well as the Resource Server.
      Now, when you’re interacting with a third-party – you’re interacting with their Authorization Server – so at that point you don’t need to build your own.
      You could do that in a more manual way – using Spring OAuth – sure. But you could also use the higher level Spring Social to do that – that’s going to be easier to set up.
      But, to give you a simple answer – yes it does.
      Hope that helps. Cheers,
      Eugen.

  • Tobi Olanrewaju

    This tutorial was very helpful. I’ve gotten the knowledge in bits and pieces before, but this just sums it all up for me. Thumbs up!

  • prithivi

    HI Eugen,
    I implemented the same in webservice, so everytime access token will be used as a key to access the webservice.
    now we have additional requirement to use Google sign In too. How can I get the access token if I use google sign In?

    • Hey Prithivi,
      Yes, you can definitely set things up to use Google as an Auth provider as well.
      However, my suggestion in that case is to use Spring Social – that has out of the box support for integrating with Google. If you do things manually – that’s still an option of course, but you will have to do a lot more work and understand the details of Google’s solution much better.
      Hope that helps. Cheers,
      Eugen.

  • Kopax Anderson

    This tutorial was very helpful.

    Unfortunately, I wasn’t able to make it work with a database.
    I switch your code for db use, and then after a successful first login, I keep having errors more or less randomly :
    – success first login
    – refuse all refresh token
    – any user can login
    – prompt for user and password
    I repeatedly get an error on the refresh token.
    They are some issues open in spring-projects/spring-security-oauth on github.
    The examples with tonr2 and sparle on the official repo are working, but I wonder if this plugin is ready for use in a client-side server-side environment, my client will be a mobile application.

    • Hey Kopax,
      While persistence isn’t the focus of the article, I’d love to have a look at the problems you’re seeing. However, your description here is a bit vague, so it’s better to open an issue (or multiple issues) on the Github project. I’ll try to replicate the problems at that point.
      Cheers,
      Eugen.

  • Shashank Sh

    Hi Eugen,

    I have a specific requirement where in the username and password needs to be validated by another separate endpoint. Can you help me where I can plugin the code to make an api call to verify the username password instead of getting the userdetails from database. API takes username and password and return if they are correct or not.

    I tried adding new provider. And override configure(AuthenticationManagerBuilder auth) of WebSecurityConfigurerAdapter by adding auth.authenticationProvider({new provider}); But I think is not getting reflected.

    • A provider is indeed a good way to go.
      Unfortunately going to be difficult to answer without a lot more detail or looking at the code.
      Generally speaking my suggestion is – try to dig deeper and isolate your problem. A good way to do that is – don’t stop until you have a working code example and a failing test.
      That way when you do ask the question – it’s going to be a lot more concrete and you’ll of course get help a lot faster.
      Hope that helps. Cheers,
      Eugen.

      • Shashank Sh

        Thanks for reply Eugen. I checked actually it’s working for grant type authorization_code, refresh_token just not for password. So far I was testing with grant type password only 🙁
        Now I am wondering why it worked for authorization_code, refresh_token but not for password. Its a very simple setup of spring boot with just two important classes https://gist.github.com/sharmasha2nk/8390bf9962cc941070ac9b87fd557176.

  • Alexei Essine

    Hi, the link to Oauth-ng is outdated, I think this is the right one : https://github.com/angularjs-oauth/oauth-ng

    • Grzegorz Piwowarek

      Thanks 🙂 we will update the article soon

  • Emil Ifrim

    Hi Eugen,

    Because Spring framework evolves (xml based configuration, web.xml spring configuration, Java Configuration for Spring Servlet, Spring boot) your samples also evolve. Is it possible to use release tags on git when a major refactoring is done? For example I’m intrested in a Standalone Resource Server example that does not use Spring Boot.

  • zakaria

    One question: why did you use ResourceDatabasePopulator while Spring Boot automatically pick ups the .sql and apply them on start up?

  • Benoit

    Hi, this tutorial seems to be what i’m looking for. I still have one question, is-it possible de have it working with 1 frontend application (JS app with Angular) which is not one the same domain than the backend (Spring) ?

    • Grzegorz Piwowarek

      I am not sure if I understood correctly but there should not be any problems with this. Remember only about handling CORS headers properly.

    • Hey Benoit,
      As Grzegorz mentioned here – yes, CORS will naturally be the issue you’ll need to deal with first.
      Second, you do of course have to make sure you’re selecting the right OAuth2 flow for a JS app; for example the Authorization Code flow is out.
      If you select the right type of flow and deal with CORS, you should be good to go.
      Cheers,
      Eugen.

    • Benoit

      Thanks a lot both of you. I will check if the backend dev team deals with CORS.

  • Ged

    I have extended the sample controller shown in the tutorial to include current user (principal)
    However, even after successful login, principal appears to be null

    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity user(Principal principal){
    System.out.ptintln(principal.getName()); //always returns null
    }

    However if i attempt to get principal using below, it works fine
    SecurityContextHolder.getContext().getAuthentication().getName()

    I wonder what is missing in the above configuration that Principal does not get injected in the controllers?

    • Hey Ged, jumping in here with regards to both of your comments.
      Unfortunately this isn’t the kind of thing we can debug here by just describing the problem. I’ll need to look at code to see what’s going on.
      The way to go here would be a PR on Github with a failing test – and I’d be happy to have a look.
      Hope that helps. Cheers,
      Eugen.

  • Ged

    It appears that all the tokens currently are stored in the database which is great as they can be accessed from different servers in the cluster. However, if the server goes down it seems that all the tables are recreated having the user to log in again even though their tokens may not have yet expired.

    I have changed the SQL query to only create tables if they dont exist, then i restarted the server and unfortunately that caused an exception while i was trying to login:

    HTTP Status 401 – Error creating bean with name ‘scopedTarget.clientDetailsService’ defined in class path resource [org/springframework/security/oauth2/config/annotation/configuration/ClientDetailsServiceConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.oauth2.provider.ClientDetailsService]: Factory method ‘clientDetailsService’ threw exception; nested exception is org.springframework.security.oauth2.provider.ClientAlreadyExistsException: Client already exists: my-client

    How would you assure that users dont get logged out even though the server is restarted?