What is OAuth
The OAuth 2.0 authorization 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 the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf
OAuth Roles
OAuth defines four roles:
- resource owner:
Could be you. An entity capable of granting access to a protected resource. When the resource owner is a person, it is referred to as an end-user.
- resource server:
The server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.
- client:
An application making protected resource requests on behalf of the resource owner and with its authorization. It could be a mobile app asking your permission to access your Facebook feeds, a REST client trying to access REST API, a web site [Stackoverflow e.g.] providing an alternative login option using Facebook account.
- authorization server:
The server issuing access tokens to the client after successfully authenticating the resource owner and obtaining authorization.
OAuth Authorization Grant types
An authorization grant is a credential representing the resource owner’s authorization (to access its protected resources) used by the client to obtain an access token. The specification defines four grant types:
- authorization code
- implicit
- resource owner password credentials
- client crederce owner password credentials grant type.
1.Resource Server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.security; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; | |
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; | |
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; | |
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; | |
@Configuration | |
@EnableResourceServer | |
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { | |
private static final String RESOURCE_ID = "my_rest_api"; | |
@Override | |
public void configure(ResourceServerSecurityConfigurer resources) { | |
resources.resourceId(RESOURCE_ID).stateless(false); | |
} | |
@Override | |
public void configure(HttpSecurity http) throws Exception { | |
http. | |
anonymous().disable() | |
.requestMatchers().antMatchers("/user/**") | |
.and().authorizeRequests() | |
.antMatchers("/user/**").access("hasRole('ADMIN')") | |
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); | |
} | |
} |
2.Authorization Server
3.REST API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.controller; | |
import java.util.List; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.http.HttpHeaders; | |
import org.springframework.http.HttpStatus; | |
import org.springframework.http.MediaType; | |
import org.springframework.http.ResponseEntity; | |
import org.springframework.web.bind.annotation.PathVariable; | |
import org.springframework.web.bind.annotation.RequestBody; | |
import org.springframework.web.bind.annotation.RequestMapping; | |
import org.springframework.web.bind.annotation.RequestMethod; | |
import org.springframework.web.bind.annotation.RestController; | |
import org.springframework.web.util.UriComponentsBuilder; | |
import com.websystique.springmvc.model.User; | |
import com.websystique.springmvc.service.UserService; | |
@RestController | |
public class HelloWorldRestController { | |
@Autowired | |
UserService userService; //Service which will do all data retrieval/manipulation work | |
//-------------------Retrieve All Users-------------------------------------------------------- | |
@RequestMapping(value = "/user/", method = RequestMethod.GET) | |
public ResponseEntity<List<User>> listAllUsers() { | |
List<User> users = userService.findAllUsers(); | |
if(users.isEmpty()){ | |
return new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);//You many decide to return HttpStatus.NOT_FOUND | |
} | |
return new ResponseEntity<List<User>>(users, HttpStatus.OK); | |
} | |
//-------------------Retrieve Single User-------------------------------------------------------- | |
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE,MediaType.APPLICATION_XML_VALUE}) | |
public ResponseEntity<User> getUser(@PathVariable("id") long id) { | |
System.out.println("Fetching User with id " + id); | |
User user = userService.findById(id); | |
if (user == null) { | |
System.out.println("User with id " + id + " not found"); | |
return new ResponseEntity<User>(HttpStatus.NOT_FOUND); | |
} | |
return new ResponseEntity<User>(user, HttpStatus.OK); | |
} | |
//-------------------Create a User-------------------------------------------------------- | |
@RequestMapping(value = "/user/", method = RequestMethod.POST) | |
public ResponseEntity<Void> createUser(@RequestBody User user, UriComponentsBuilder ucBuilder) { | |
System.out.println("Creating User " + user.getName()); | |
if (userService.isUserExist(user)) { | |
System.out.println("A User with name " + user.getName() + " already exist"); | |
return new ResponseEntity<Void>(HttpStatus.CONFLICT); | |
} | |
userService.saveUser(user); | |
HttpHeaders headers = new HttpHeaders(); | |
headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.getId()).toUri()); | |
return new ResponseEntity<Void>(headers, HttpStatus.CREATED); | |
} | |
//------------------- Update a User -------------------------------------------------------- | |
@RequestMapping(value = "/user/{id}", method = RequestMethod.PUT) | |
public ResponseEntity<User> updateUser(@PathVariable("id") long id, @RequestBody User user) { | |
System.out.println("Updating User " + id); | |
User currentUser = userService.findById(id); | |
if (currentUser==null) { | |
System.out.println("User with id " + id + " not found"); | |
return new ResponseEntity<User>(HttpStatus.NOT_FOUND); | |
} | |
currentUser.setName(user.getName()); | |
currentUser.setAge(user.getAge()); | |
currentUser.setSalary(user.getSalary()); | |
userService.updateUser(currentUser); | |
return new ResponseEntity<User>(currentUser, HttpStatus.OK); | |
} | |
//------------------- Delete a User -------------------------------------------------------- | |
@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE) | |
public ResponseEntity<User> deleteUser(@PathVariable("id") long id) { | |
System.out.println("Fetching & Deleting User with id " + id); | |
User user = userService.findById(id); | |
if (user == null) { | |
System.out.println("Unable to delete. User with id " + id + " not found"); | |
return new ResponseEntity<User>(HttpStatus.NOT_FOUND); | |
} | |
userService.deleteUserById(id); | |
return new ResponseEntity<User>(HttpStatus.NO_CONTENT); | |
} | |
//------------------- Delete All Users -------------------------------------------------------- | |
@RequestMapping(value = "/user/", method = RequestMethod.DELETE) | |
public ResponseEntity<User> deleteAllUsers() { | |
System.out.println("Deleting All Users"); | |
userService.deleteAllUsers(); | |
return new ResponseEntity<User>(HttpStatus.NO_CONTENT); | |
} | |
} |
Sending Request to /oauth/token with grant_password and resource owners credentials will generate the access token and refresh tokens
http://localhost:8080/Securing_RESTful_API_with_OAuth/oauth/token?grant_type=password&username=User1&password=abc123
Use the token you received to access the resources
GET http://localhost:8080/Securing_RESTful_API_with_OAuth/user/?access_token=3525d0e4-d881-49e7-9f91-bcfd18259109