-
Notifications
You must be signed in to change notification settings - Fork 61
Store Clients and Users' Credentials to DB
For clients and users' credentials, you can store them into memory or database. It is better to store in a database rather than hard-coded in code. If you want to add a new client after starting the authentication service, you can insert a new record to the database rather than changing the code.
- Set dependencies
- Create DB schema
- Configure Spring to validate credentials with DB
- Encode password
- References
For connecting the database, you need to set the dependencies for JDBC connections.
dependencies {
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '1.5.0.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-autoconfigure', version: '1.5.0.RELEASE'
compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.38'
}
You need to create tables for storing clients' details and users' details to the database.
For storing clients' details, you need to create the following tables:
- oauth_client_details
You need to create the schema.sql
into the resources directory.
CREATE TABLE oauth_client_details (
client_id VARCHAR(256) PRIMARY KEY, -- the id of the client
resource_ids VARCHAR(256),
client_secret VARCHAR(256), -- the password of the client
scope VARCHAR(256), -- the types of the client can get the access token from the service, separated by comma (,)
authorized_grant_types VARCHAR(256), -- the list of the authorization grant types, separated by comma (,)
web_server_redirect_uri VARCHAR(256),
authorities VARCHAR(256), -- the list of roles for the client
access_token_validity INTEGER, -- the expiry of an access token, by second
refresh_token_validity INTEGER, -- the expiry of a refresh token, by second
additional_information VARCHAR(4096),
autoapprove VARCHAR(256)
);
You can also create client records when you start the authentication service, you can also insert new clients to the database when the service is running. For example
INSERT INTO oauth_client_details
(client_id, client_secret, scope, authorized_grant_types,
web_server_redirect_uri, authorities,
access_token_validity, refresh_token_validity,
additional_information, autoapprove)
VALUES
('eagleeye', 'thisissecret', 'webclient,mobileclient', 'refresh_token,password,client_credentials',
null, null,
36000, 36000,
null, true);
For storing users' details, you need to create the following tables:
- users
- authorities (for roles)
You can add the SQL statements in schema.sql
for creating those tables.
CREATE TABLE users (
username VARCHAR(256) NOT NULL PRIMARY KEY,
password VARCHAR(256) NOT NULL,
enabled BOOLEAN NOT NULL
);
CREATE TABLE authorities (
username VARCHAR(256),
authority VARCHAR(256)
);
You can also create user records with authorities when you start the authentication service, you can also insert new users and authorities to the database when the service is running. For example
INSERT INTO users(username,password,enabled) VALUES ('john.carnell', 'password1', true);
INSERT INTO users(username,password,enabled) VALUES ('william.woodward','password2', true);
INSERT INTO authorities(username,authority) VALUES ('john.carnell', 'ADMIN');
INSERT INTO authorities(username,authority) VALUES ('john.carnell', 'USER');
INSERT INTO authorities(username,authority) VALUES ('william.woodward','ADMIN');
Note that if you don't use any password encoder, you need to store plain text in the password column.
If you want to store credentials in DB and also validate clients and users with DB to give access tokens, you need to configure Spring to do them with DB rather than memory.
@Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource; // autowire the DataSource for building the connection with DB
@Autowired
private UserDetailsService userDetailsService;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource); // specify Spring to use JDBC (DB) for client's authentication
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
}
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource; // autowire the DataSource for building the connection with DB
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
@Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource); // specify Spring to use JDBC (DB) for client's authentication
}
}
Without password encoders, any password will be stored as plain text in the database, and it is not a good practice for security. Spring supports several types of password encoder so that any password can be stored as encrypted text in the database.
There are several password encoders in Spring Security (Deprecated password encoders are not listed):
Package | Class | Description |
---|---|---|
org.springframework.security.crypto.bcrypt | BCryptPasswordEncoder | BCrypt strong hashing |
org.springframework.security.crypto.password | Pbkdf2PasswordEncoder | PBKDF2 with a configurable number of iterations and a random 8-byte random salt value |
org.springframework.security.crypto.scrypt | SCryptPasswordEncoder | SCrypt hashing |
org.springframework.security.crypto.password | DelegatingPasswordEncoder | A password encoder that delegates to another PasswordEncoder based upon a prefixed identifier (format: {password_encoder_name}encrypted_password ) |
You can set the password encoder for clients and users. This is an example of setting BCryptPasswordEncoder
at user level.
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); // define password encoder
/* omit other lines */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder); // set password encoder
}
}
In the database, you need to store the encrypted password based on the password encoder you chose. There are several ways to get the encrypted password:
You can create a Java class with the main function so that you can run it independently for generating the encrypted password.
public class Run {
public static void main(String[] args) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encryptedPassword = passwordEncoder.encode("password1");
System.out.println(encryptedPassword);
}
}
You can use online tools to generate an encrypted password.
Encoder | Tool |
---|---|
BCryptPasswordEncoder | https://www.devglan.com/online-tools/bcrypt-hash-generator |
Pbkdf2PasswordEncoder | https://8gwifi.org/pbkdf.jsp |
SCryptPasswordEncoder | https://8gwifi.org/scrypt.jsp |
You can create an API endpoint to encrypt the password based on the password encoder you chose.
You can create an API endpoint for adding clients and users. Before inserting a new client or a user into the database, you can encrypt the password.
- Overview
- Getting Started
-
Technical Essentials
- Autowired
- SpringData JPA
- Configuration File Auto-loading
- Configuration Encryption
- Service Discovery with Eureka
- Resiliency Patterns with Hystrix
- Configure Hystrix
- Service Gateway with Zuul
- Zuul Filters
- Protect Service with Spring Security and OAuth2
- Use JWT as Access Token
- Store Clients and Users' Credentials to DB
- Integrate with Message Queue (Kafka)
- Integrate with Redis
- Tune Logging
- Log Aggregation
- Send Trace to Zipkin
- Build Runnable Jar
- Core Application Logic
- Components