preface

In the last article, we set up a process for client_credentials with Oauth2 authorization in the simplest way possible. Now, on this basis, we will go one step further, we store the client information and token in the database, convenient for us to manage. And the password needs to be secure, so it needs to be encrypted. With a clear goal, let’s do it!

Client&token is stored in the database

Steps:

  1. Database preparation: Create only the tables we need to use
  2. Add database dependencies: use the mysql database
  3. Oauth Storage configuration Settings
  4. validation

Database preparation

In the local database, create two tables:

  • A table stores client information
  • The other table stores the tokens
# Client informationcreate table oauth_client_details
(
    client_id               VARCHAR(256) PRIMARY KEY comment 'Required, Oauth2 client_id',
    resource_ids            VARCHAR(256) comment 'Optional, set of resource ids, separated by commas.',
    client_secret           VARCHAR(256) comment 'Required, Oauth2 client_secret'.scope                   VARCHAR(256) comment 'Mandatory, Oauth2 permission scope, such as read, write, etc. Customizable',
    authorized_grant_types  VARCHAR(256) comment 'Mandatory, Oauth2 authorization type, supported types: authorization_code,password,refresh_token,implicit,client_credentials, separated by commas.',
    web_server_redirect_uri VARCHAR(256) comment 'Optional, client redirection URI, this field is required when grant_type is authorization_code or implicit',
    authorities             VARCHAR(256) comment 'Optional, specify the client's Spring Security permission value',
    access_token_validity   INTEGER comment 'optional, access_token value (unit: second), the duration of your framework (refreshTokenValiditySeconds) don't fill in the default 12 hours',
    refresh_token_validity  INTEGER comment 'optional, refresh_token effective time value (unit: second), not fill in the framework (refreshTokenValiditySeconds) default 30 days',
    additional_information  VARCHAR(4096) comment 'Reserved field, format must be JSON',
    autoapprove             VARCHAR(256) comment 'This field applies to whether the user automatically approves the action when grant_type="authorization_code"'); # token storagecreate table oauth_access_token
(
    token_id          VARCHAR(256) comment 'ACCESS_token stored after MD5 encryption',
    token             BLOB comment 'Binary data format for access_token serialization',
    authentication_id VARCHAR(256) PRIMARY KEY comment 'primary key, its value is based on the current username (if any), client_id and scope through the MD5 encryption generated, concrete implementation see DefaultAuthenticationKeyGenerator',
    user_name         VARCHAR(256),
    client_id         VARCHAR(256),
    authentication    BLOB comment 'Binary data after serialization of OAuth2Authentication object',
    refresh_token     VARCHAR(256) comment 'MD5 encrypted data for refresh_token'
);
Copy the code

After that, we need to add custom client information. The client information added in this demo is as follows (still in accordance with the principle of not configuring as much as possible) :

INSERT INTO oauth_client_details (client_id, resource_ids, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove) VALUES ('gold'.'res'.'{noop}123456'.'write'.'client_credentials'.null.null.null.null.null.null);
Copy the code

instructions

  1. In the official source code, there is a corresponding schema. SQL file. Here, only the tables involved in our example are created
  2. For two table operations, we can look at these two classes: JdbcClientDetailsService & JdbcTokenStore
  3. In addition, this example adds resource_ids, note in the configurationResourceServerSecurityConfigurerIn the corresponding

Pom

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
Copy the code

The authentication server code is modified

@Configuration
@EnableAuthorizationServer
public class MyAuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {

    private final DataSource dataSource;

    public MyAuthorizationServerConfigurer(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(newJdbcTokenStore(dataSource)); }}Copy the code

The above code only shows the changed part, modify the client configuration and tokenStore configuration, add data source can be done

The request token

The following request is made in Postman. Base_url is the set global variable, which is actually http://127.0.0.1:8080

Access to resources

Observation database

Since the token is stored in binary form in the database, we can see from the client_id data that it is the client we just requested.

So far we have been implemented, the client and token information stored in the database, so that we are more convenient to the client and token data management. But it is not secure for a database to store plaintext passwords, so next, we encrypt client_secret.

Client_secret encryption

Configuration passwordEncoder

You can check the PasswordEncoderFactories (MD5, SHA, bcrypt) with SpringBoot Oauth. So direct configuration support passwordEncoder of all algorithms, namely DelegatingPasswordEncoder.

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        	  		clients.jdbc(dataSource).passwordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());

}
Copy the code

Encryption client_secret

Since we use bcrypt encryption this time, we can directly find the BCryptPasswordEncoder, which can encrypt our password and store the password in the database.

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class PasswordEncodeUtil {

    private static final BCryptPasswordEncoder bcryptEncoder = new BCryptPasswordEncoder();

    public static String bcryptEncode(String password) {
        return bcryptEncoder.encode(password);
    }

    public static String genOauthEncodePwd(String password) {
        return "{bcrypt}" + bcryptEncode(password);
    }


    public static void main(String[] args) {
        String oriPwd = "123456"; System.out.println(genOauthEncodePwd(oriPwd)); }}Copy the code

Old password: 123456

Encrypted password: {bcrypt} 2 a2a2a10 $NPxtsEUMmBGTlzVXlT. ScubSCXNEDlBAq2r2t7iQFB /. RaNBlh0nO

Note: The encryption password is prefixed with curly braces “{XXX}”, which specifies the encryption algorithm name. Because the framework supports multiple encryption algorithms, it must be prefixed with the specified encryption algorithm.

Request to Obtain token

The following request is made in Postman. Base_url is the set global variable, which is actually http://127.0.0.1:8080

Request resources

summary

In this paper, client and token information is stored in the database in the mode of client_credentials for easy management. Meanwhile, in order to ensure password security, client_secret is encrypted with bcrypt algorithm and stored in the database. With the foundation of the previous article, this article as a whole looks quite simple. Let’s do it, guys!

Personal level is limited, welcome to correct, exchange oh ~~~

The demo:Github.com/goldpumpkin…

Reference:

  1. Spring-oauth-server database table description