How to Implement Spring Security With OAuth2 - DZone Security
How to Implement Spring Security With OAuth2 - DZone Security
Get the fastest log management and analysis with Graylog open source or enterprise edition free up to 5GB per day.
Presented by Graylog
Spring Security provides comprehensive security services for J2EE-based enterprise software applications. It is powerful,
flexible, and pluggable. It is not like a Proxy server, firewall, OS level Security, Intrusion Detection System, or JVM Security.
OAuth is an open-authorization protocol that allows accessing resources of the resource owner by enabling the client
applications on HTTP services, such as Gmail, GitHub, etc.
The OAuth 2.0 framework enables a third-party application to obtain limited access to an
HTTP service, either on behalf of a resource owner by orchestrating an approval interaction
between resource owner and HTTP service or by allowing the third-party application to obtain
access on its own behalf.
OAuth2 Roles: There are four roles that can be applied on OAuth2:
OAuth2 Tokens: Tokens are implementation specific random strings, generated by the authorization server.
Access Token: Sent with each request, usually valid for about an hour only.
Refresh Token: It is used to get a 00new access token, not sent with each request, usually lives longer than access token.
2
3 import org.springframework.context.annotation.Configuration;
4 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5 import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
6 import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
7 import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
8 import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
9
10 @Configuration
11 @EnableResourceServer
12 /*@EnableResourceServer enables a Spring Security filter that authenticates requests using an incoming OAuth2 tok
12
13 public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
16
17 @Override
19 resources.resourceId(RESOURCE_ID).stateless(false);
20 }
21
22 @Override
24 http.
25 anonymous().disable()
26 .requestMatchers().antMatchers("/user/**")
27 .and().authorizeRequests()
28 .antMatchers("/user/**").access("hasRole('ADMIN')")
29 .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
30 }
31
32 }
Authorization Server
1 package com.security.oauth.security;
2
3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.beans.factory.annotation.Qualifier;
5 import org.springframework.context.annotation.Configuration;
6 import org.springframework.security.authentication.AuthenticationManager;
7 import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
8 import org springframework security oauth2 config annotation web configuration AuthorizationServerConfigurerAdapt
8 import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapt
9 import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
10 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigur
11 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigure
12 import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
13 import org.springframework.security.oauth2.provider.token.TokenStore;
14
15 @Configuration
16 @EnableAuthorizationServer
21
22 @Autowired
24
25 @Autowired
27
28 @Autowired
29 @Qualifier("authenticationManagerBean")
31
32 @Override
34
35 clients.inMemory()
36 .withClient("my-trusted-client")
38 .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
43 }
44
45 @Override
47 endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
48 .authenticationManager(authenticationManager);
49 }
50
51 @Override
53 oauthServer.realm(REALM+"/client");
54 }
55
56 }
Security Configuration
1 package com.security.oauth.security;
2
3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.context.annotation.Bean;
5 import org.springframework.context.annotation.Configuration;
6 import org.springframework.security.authentication.AuthenticationManager;
7 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
8 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
9 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
10 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
11 import org.springframework.security.crypto.password.NoOpPasswordEncoder;
11 import org.springframework.security.crypto.password.NoOpPasswordEncoder;
12 import org.springframework.security.oauth2.provider.ClientDetailsService;
13 import org.springframework.security.oauth2.provider.approval.ApprovalStore;
14 import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
15 import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
16 import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
17 import org.springframework.security.oauth2.provider.token.TokenStore;
18 import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
19
20 @Configuration
21 @EnableWebSecurity
23
24 @Autowired
26
27 @Autowired
29 auth.inMemoryAuthentication()
30 .withUser("bill").password("abc123").roles("ADMIN").and()
31 .withUser("bob").password("abc123").roles("USER");
32 }
33
34
35 @Override
37 http
38 .csrf().disable()
39 .anonymous().disable()
40 .authorizeRequests()
41 .antMatchers("/oauth/token").permitAll();
42 }
43
44 @Override
45 @Bean
47 return super.authenticationManagerBean();
48 }
49
50
51 @Bean
54 }
55
56 @Bean
57 @Autowired
60 handler.setTokenStore(tokenStore);
61 handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
62 handler.setClientDetailsService(clientDetailsService);
63 return handler;
64 }
65
66 @Bean
67 @Autowired
70 store.setTokenStore(tokenStore);
71 return store;
72 }
73
74 }
2
3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.context.annotation.Configuration;
5 import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
6 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
7 import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
8 import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
9
10 @Configuration
13 @SuppressWarnings("unused")
14 @Autowired
16
17 @Override
20 }
21 }
Controller
1 package com.security.oauth.controller;
2
import java util List;
3 import java.util.List;
4
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.http.HttpHeaders;
7 import org.springframework.http.HttpStatus;
8 import org.springframework.http.MediaType;
9 import org.springframework.http.ResponseEntity;
10 import org.springframework.web.bind.annotation.PathVariable;
11 import org.springframework.web.bind.annotation.RequestBody;
12 import org.springframework.web.bind.annotation.RequestMapping;
13 import org.springframework.web.bind.annotation.RequestMethod;
14 import org.springframework.web.bind.annotation.RestController;
15 import org.springframework.web.util.UriComponentsBuilder;
16
17 import com.security.oauth.model.User;
18 import com.security.oauth.service.UserService;
19
20 @RestController
22
23 @Autowired
25
26
27 //-------------------Retrieve All Users--------------------------------------------------------
28
29 @RequestMapping(value = "/user/", method = RequestMethod.GET)
32 if(users.isEmpty()){
34 }
34 }
36 }
37
38
39 //-------------------Retrieve Single User--------------------------------------------------------
40
41 @RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALU
45 if (user == null) {
48 }
50 }
51
52
53
54 //-------------------Create a User--------------------------------------------------------
55
56 @RequestMapping(value = "/user/", method = RequestMethod.POST)
59
60 if (userService.isUserExist(user)) {
63 }
64
65 userService.saveUser(user);
66
67 HttpHeaders headers = new HttpHeaders();
68 headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.getId()).toUri());
70 }
71
72
73 //------------------- Update a User --------------------------------------------------------
74
75 @RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
78
79 User currentUser = userService.findById(id);
80
81 if (currentUser==null) {
84 }
85
86 currentUser.setName(user.getName());
87 currentUser.setAge(user.getAge());
88 currentUser.setSalary(user.getSalary());
89
90 userService.updateUser(currentUser);
92 }
93
94 //------------------- Delete a User --------------------------------------------------------
95
96 @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
bli R E i U d l U (@P hV i bl ("id") l id) {
97 public ResponseEntity<User> deleteUser(@PathVariable("id") long id) {
99
10
0 User user = userService.findById(id);
10
1 if (user == null) {
10
2 System.out.println("Unable to delete. User with id " + id + " not found");
10
3 return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
10
4 }
10
5
10
6 userService.deleteUserById(id);
10
7 return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
10
8 }
10
9
11
0
11
1 //------------------- Delete All Users --------------------------------------------------------
11
2
11
3 @RequestMapping(value = "/user/", method = RequestMethod.DELETE)
11
4 public ResponseEntity<User> deleteAllUsers() {
11
5 System.out.println("Deleting All Users");
11
6
11
7 userService.deleteAllUsers();
11
8 return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
11
9 }
12
0
12
1 }
Get the fastest log management and analysis with Graylog open source or enterprise edition free up to 5GB per day.
Presented by Graylog
Time between vulnerability disclosure and exploitation is counted in days, sometimes hours. As in many areas of IT security, the attacker is
at an advantage. Will you be able to respond fast enough? Learn More.
Presented by Veracode
SQL injection is a common form of data theft. Yet, I am hopeful we can make SQL injection protection more common.
The 2018 TrustWave Global Security Report listed SQL injection as the second most common technique for web attacks, trailing
only cross-site scripting (XSS) attacks. This is a 38 percent increase from the previous year. That same report also shows SQL
Injection ranked fifth on a list of vulnerabilities that can be identified through simple penetration testing.
You may look at the increase and think “whoa, attacks are increasing.” But I believe that what we are seeing is a rising awareness
of security. No longer the stepchild, security is a first-class citizen in application design and deployment today. As companies
focus on security, they deploy tools and systems to help identify exploits, leading to more reporting of attacks.
SQL injection is preventable. That’s the purpose of this post today — to help you understand what SQL injection is, how to
identify when it is happening, and how to prevent it from being an issue.
The most common example of SQL injection attacks is found inside username and password input boxes on a webpage. This
login design is standard for allowing users to access a website. Unfortunately, many websites do not take precautions to block
SQL injection on these input fields, leading to SQL injection attacks.
Let’s look at a sample website built for the fictional Contoso Clinic. The source code for this can be found at
https://github.com/Microsoft/azure-sql-security-sample.
On the Patients page, you will find an input field at the top, next to a ‘Search’ button, and next to that a hyperlink for ‘SQLi Hints’.
Clicking on the SQLi Hints link will display some sample text to put into the search field.
I’m going to take the first statement and put it into the search field. Here is the result:
This is a common attack vector, as the adversary can use this method to determine what version of SQL Server is running. This is
also a nice reminder to not allow your website to return such error details to the end user. But more on that later.
Let’s talk a bit about how SQL injection works under the covers.
How SQL Injection Works
The vulnerability in my sample website is the result of this piece of code:
1 return View(db.Patients.SqlQuery
This is a common piece of code used by many websites. It is building a dynamic SQL statement based upon the input fields on the
page. If I were to search the Patients page for ‘Rock,’ the SQL statement sent to the database would then become:
In the list of SQLi hints on that page, you will notice that each example starts with a single quote, followed by a SQL statement,
and at the end, is a comment block (the two dashes). For the example that I chose above, the resulting statement is as follows:
This results in the conversion error shown above. This also means that I can do interesting searches to return information about
the database. Or, I could do malicious things, like drop tables.
Chance are, you have code like this, somewhere, right now. Let’s look at how to find out what your current code looks like.
There are two tools I can recommend you use to help discover SQL injection.
(For fairness, I should mention that AWS WAF allows for SQL injection detection, but their process is a bit more manual than
Azure).
If you try to roll your own discovery, you will want to focus on finding queries that have caused errors. Syntax errors, missing
objects, permission errors, and UNION ALL errors are the most common. You can find a list of the common SQL Server error
message numbers here.
It warrants mentioning that not all SQL injection attacks are discoverable. But when it comes to security, you will never eliminate
all risk you take steps to lower your risk SQL injection discovery is one way to lower your risk
all risk, you take steps to lower your risk. SQL injection discovery is one way to lower your risk.
Prepared statements should not allow an attacker to change the nature of the SQL statement by injecting additional code into the
input field. I said “should”, because it is possible to write prepared statements in a way that would still be vulnerable to SQL
injection. You must (1) know what you are doing and (2) learn to sanitize your inputs.
Traditionally, one argument against the use of prepared statements centers on performance. It is possible that a prepared
statement may not perform as well as the original dynamic SQL statement. However, if you are reading this and believe
performance is more important than security, you should reconsider your career in IT before someone does that for you.
Like prepared statements, stored procedures are not exempt from SQL injection. It is quite possible you could put vulnerable
code into a stored procedure. You must take care to compose your stored procedures properly, making use of parameters. You
should also consider validating the input parameters being passed to the procedure, either on the client side or in the procedure
itself.
Use EXECUTE AS
You could use a security method such as EXECUTE AS to switch the context of the user as you make a request to the database. As
mentioned above, stored procedures somewhat act in this manner by default. But EXECUTE AS can be used directly for requests
such as prepared statements or ad-hoc queries.
Remove Extended Stored Procedures
Disabling the use of extended stored procedures is a good way to limit your risk with SQL injection. Not because you won’t be
vulnerable, but because you limit the surface area for the attacker. By disabling these system procedures, you limit a common
way that an attacker can get details about your database system.
Use Firewalls
Whitelisting of IP addresses is a good way to limit activity from anomalous users. Use of VPNs and VNETs to segment traffic can
also reduce your risk.
Summary
The hard truth here is that every database is susceptible to SQL injection attacks. No one platform is more at risk than any other.
The weak link here is the code written on top of the database. Most code development does not emphasize security enough,
leaving themselves open to attacks.
When you combine poor database security techniques along with poor code, you get the recipe for SQL Injection.
References
2018 TrustWave Global Security Report
Contoso Clinic Demo Application
sqlmap: Automatic SQL injection and database takeover tool
Azure SQL Database threat detection
Working with SQL Injection Match Conditions
How to Detect SQL Injection Attacks
sp executesql (Transact-SQL)
sp_executesql (Transact SQL)
EXECUTE AS (Transact-SQL)
Server Configuration Options (SQL Server)
Download the Addressing Your Open Source Risk eBook to learn more about how Veracode’s combination of machine learning and natural
language can help you efficiently and effectively manage open source risk.
Presented by Veracode
Picking Over the Bones of a SQL Injection Attack Free DZone Refcard
Introduction to DNS Security
Topics: SECURITY, SQL INJECTION, SQL INJECTION ATTACK, CYBERSECURITY, DATA PRIVACY, AZURE
Published at DZone with permission of Thomas LaRock , DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Get the fastest log management and analysis with Graylog open source or enterprise edition free up to 5GB per day.
Presented by Graylog
Top technology prognosticators have listed blockchain among the top 10 emerging technologies with the potential to
revolutionize our world in the next decade. This fact makes it well worth investing your time now to learn. If you are a developer
with a Java background and want to get up to speed on blockchain technology, this article will give you the basic information you
need to get started.
Blockchain is a huge space, and at first, it can be overwhelming to navigate. Blockchain is different from other software
technologies as it has a parallel non-technical universe with a focus on speculations, scams, price volatility, trading, ICOs,
cryptocurrencies, Bitcoin maximalism, game theory, human greed, etc. Here, we will ignore that side of blockchain completely
and look only at the technical aspects.
The two books I recommend for this purpose happen to be from the same author — Andreas M. Antonopoulos:
Mastering Bitcoin is the most in-depth, technical book out there while also being the most understandable and easy-to-
read book I could find about Bitcoin. The tens of other books I checked on this topic were either mostly philosophical and
non-technical.
On the Ethereum side, there are many more technical books, but I liked the level of detail in Mastering Ethereum most.
Building Ethereum Dapps is another book I found very thorough in covering Ethereum development very well.
It is worth stating that the popular technologies such as Java, .NET, and relational databases are not common in the blockchain
space. This space is primarily dominated by C, Go, Rust on the server side, and JavaScript on the client side. But if you know Java,
there are a few projects and components written in Java that can be used as a leveraged entry point to the blockchain space.
Assuming you've read the above two books, and want to get your hands dirty, here are a few open-source blockchain projects
written in Java: