I generated simple microservices application with Jhipster I wrote simple controller like hello world,
When I am trying to test through test method it is always giving Unauthorized error and the test fails.
Controller:
#RestController
#RequestMapping("/api")
public class TestController{
#GetMapping("/test/{Id}")
public String TestGetData(#PathVariable int Id) {
return "Here is your data!";
}
}
Testclass:
#SpringBootTest(classes = HerstellerController.class)
#AutoConfigureMockMvc
public class TestIT {
#Autowired
private MockMvc mockMvc;
private static final long ONE_MINUTE = 60000;
private String token;
private Key key;
private TokenProvider tokenProvider;
#BeforeEach
public void setup() {
tokenProvider = new TokenProvider( new JHipsterProperties());
key = Keys.hmacShaKeyFor(Decoders.BASE64
.decode("xxxx"));
ReflectionTestUtils.setField(tokenProvider, "key", key);
ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", ONE_MINUTE);
}
#Test
public void TestData() throws Exception {
token=tokenProvider.createToken(createAuthentication(),false);
String id="1";
String expData = "Here is your data!";
String result = mockMvc.perform(get("/api/test/"+ id)
.header("Authorization","Bearer " + token))
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();
System.out.println("\nResult:\n"+result);
}
private Authentication createAuthentication() {
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.ADMIN));
return new UsernamePasswordAuthenticationToken("admin", "admin", authorities);
}
Changed the securityconfig also like this
.antMatchers("/api/**").permitAll()
.antMatchers("/api/**").anonymous()
I added authentication to securityContext in setup of Testclass!, It works!
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(createAuthentication());
SecurityContextHolder.setContext(securityContext);
Related
I am new to unit testing REST API in Spring Boot.
I am expecting response status as CREATED but instead I am getting a PAGE NOT FOUND error.
Below is the code for:-
UserControllerUnitTests
#SpringBootTest
#ContextConfiguration(classes = { CommonConfig.class, SecurityConfig.class})
#RunWith(SpringRunner.class)
class UserControllerUnitTests {
private static ObjectMapper mapper;
private static final String URI = "/users";
MockMvc mvc;
#Autowired
WebApplicationContext webAppContext;
#Mock
UserService userService;
MvcResult mvcResult;
#BeforeAll
static void setUp() {
mapper = new ObjectMapper();
}
#BeforeEach
void initialize() throws Exception {
mvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();
....
....
....
void shouldReturnStatusCreatedIfValidUserPassedForPostUser(long index) throws Exception {
int expectedStatus = HttpStatus.CREATED.value();
UserDAO returnUser;
UserDAO user = userList.get(index);
userList.remove(index);
String jsonContent = mapper.writeValueAsString(user);
user.setId(index);
user.setEncryptedPassword(null);
Mockito.when(userService.addUser(Mockito.any())).thenReturn(user);
mvcResult = mvc.perform(MockMvcRequestBuilders.post(URI)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonContent)).andReturn();
//Mockito.verify(userService, Mockito.times(1)).addUser(Mockito.any());
int actualStatus = mvcResult.getResponse().getStatus();
Assert.assertEquals("Response status should be CREATED", expectedStatus, actualStatus);
jsonContent = mvcResult.getResponse().getContentAsString();
returnUser = mapper.readValue(jsonContent, UserDAO.class);
Assert.assertEquals("EncryptedPassword should not be returned", null,
returnUser.getEncryptedPassword());
}
User Controller.class
#RestController
#RequestMapping("users/")
public class UserController {
UserService userService;
#Autowired
public UserController(UserService userService) {
this.userService = userService;
}
....
....
....
#PostMapping(path = "",
consumes = { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON },
produces = { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public ResponseEntity<UserDAO> createUser(#Valid #RequestBody UserDAO user) {
String password = user.getEncryptedPassword();
user.setEncryptedPassword(null);
UserDAO retreivedUser;
if(user.getId() != 0)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
user.setEncryptedPassword(password);
retreivedUser = userService.addUser(user);
if(retreivedUser != null)
return new ResponseEntity<>(retreivedUser, HttpStatus.CREATED);
return new ResponseEntity<>(HttpStatus.CONFLICT);
}
}
The full code can be found at https://github.com/vineethmaller/springboot-userservice
I spotted a few errors:
Get rid of ContextConfiguration
#SpringBootTest
// #ContextConfiguration(classes = { CommonConfig.class, SecurityConfig.class})
#RunWith(SpringRunner.class)
class UserControllerUnitTests {
Specify correct mapping on the controller (no slash)
#RestController
#RequestMapping("users")
public class UserController {
You setup your UserService mock which is not used in the test. Did you mean #MockBean?
#MockBean
UserService userService;
I get An Authentication object was not found in the SecurityContext error when I call a #Service after calling a #RestController through MockMvc in a test method annotated with #WithMockUser.
Calling in the opposite order works fine as does calling the service and controller individually. The #Service is clearing the SecurityContextHolder. The only workaround I can think of is to set the context manually. Am I missing something?
I need to call the service to mutate state and then test that the controller returns the correct state.
#Service
public class SimpleService {
#Secured("ROLE_SIMPLE_USER")
public void doThis(Long id) {
System.out.println("dothis : " + id);
}
#Secured("ROLE_SIMPLE_USER")
public void doThat(Long id) {
System.out.println("dothat : " + id);
}
}
#RestController
#RequestMapping("/api")
#Secured("ROLE_SIMPLE_USER")
public class SimpleController {
#Autowired
private SimpleService simpleService;
#PostMapping(value = "{id}/dothis")
public ResponseEntity dothis(#PathVariable("id") Long id) {
simpleService.doThis(id);
return ResponseEntity.status(HttpStatus.OK).build();
}
#PostMapping(value = "{id}/dothat")
public ResponseEntity dothat(#PathVariable("id") Long id) {
simpleService.doThat(id);
return ResponseEntity.status(HttpStatus.OK).build();
}
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureMockMvc
#ActiveProfiles({"devh2"})
public class SimpleControllerTest {
#Autowired
private SimpleService simpleService;
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#Before
public void setUpLiabilities() {
this.mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
}
#Test
#WithMockUser(username="simple.user", password = "******", roles = {"SIMPLE_USER"})
public void callViaControllers() throws Exception {
mockMvc.perform(post("/api/1/dothis").with(csrf())).andExpect(status().isOk());
mockMvc.perform(post("/api/1/dothat").with(csrf())).andExpect(status().isOk());
}
#Test
#WithMockUser(username="simple.user", password = "******", roles = {"SIMPLE_USER"})
public void callViaService() throws Exception {
simpleService.doThis(1L);
simpleService.doThat(1L);
}
#Test
#WithMockUser(username="simple.user", password = "******", roles = {"SIMPLE_USER"})
public void callViaServiceThenControllers() throws Exception {
simpleService.doThis(1L);
mockMvc.perform(post("/api/1/dothat").with(csrf())).andExpect(status().isOk());
}
#Test
#WithMockUser(username="simple.user", password = "******", roles = {"SIMPLE_USER"})
public void callViaControllerThenService() throws Exception {
mockMvc.perform(post("/api/1/dothis").with(csrf())).andExpect(status().isOk());
// ***FAILS*** because SecurityContextPersistenceFilter clears the SecurityContext ???
simpleService.doThat(1L);
}
#Test
#WithMockUser(username="simple.user", password = "******", roles = {"SIMPLE_USER"})
public void callViaControllerThenServiceWithWorkaround() throws Exception {
mockMvc.perform(post("/api/1/dothis").with(csrf())).andExpect(status().isOk());
setSecurityContextAndThenCallDoThat(1L, "simple.user", "******", "ROLE_SIMPLE_USER");
}
// Workaround - set context manually
private void setSecurityContextAndThenCallDoThat(long id, String username, String password, String... roles) {
try {
final SecurityContextImpl holder = new SecurityContextImpl();
holder.setAuthentication(new TestingAuthenticationToken(username, password, roles));
SecurityContextHolder.setContext(holder);
this.simpleService.doThat(id);
} finally {
SecurityContextHolder.clearContext();
}
}
}
I have a small issue with mocking methods . Where mock should return an predefined object, it returns null. here is test set up:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerTest {
#Autowired
WebApplicationContext webContext;
#MockBean
UserTransferService userTransferService;
#MockBean
UserService userService;
MockMvc mockMvc;
private User user = DummyObjects.getDummyUser();
private User modifiedUser = DummyObjects.getModifiedUser();
private UserTO userTO = DummyObjects.getDummyUserTO();
private UserTO modifiedUserTO = DummyObjects.getModifiedUserTO();
#Before
public void setUp() throws Exception {
List<User> users = new ArrayList<>();
users.add(modifiedUser);
users.add(user);
given(this.userTransferService.getTO(user)).willReturn(userTO);
given(this.userTransferService.getObject(userTO)).willReturn(user);
given(this.userTransferService.getTO(modifiedUser)).willReturn(modifiedUserTO);
given(this.userTransferService.getObject(modifiedUserTO)).willReturn(modifiedUser);
given(this.userService.findAll()).willReturn(users);
given(this.userService.save(user)).willReturn(user);
given(this.userService.removeById(1)).willReturn(true);
given(this.userService.getById(1)).willReturn(user);
given(this.userService.getById(2)).willReturn(null);
given(this.userService.modify(modifiedUser)).willReturn(modifiedUser);
given(this.userService.findByLogin(user.getLogin())).willReturn(user);
given(this.userService.findByLogin("AAA")).willReturn(null);
mockMvc = MockMvcBuilders
.webAppContextSetup(webContext)
.apply(springSecurity())
.build();
}
test itself:
#Test
public void shouldAddUser() throws Exception {
mockMvc.perform(post("/api/user")
.content(TestingUtility.asJsonString(userTO))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.with(csrf().asHeader()))
.andExpect(status().is(200))
.andExpect(content().json(TestingUtility.asJsonString(userTO)));
}
and Controller method:
#RequestMapping(method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
public UserTO modifyUser(#RequestBody UserTO userTO, UsernamePasswordAuthenticationToken principal) throws IllegalAccessException{
User user = userTransferService.getObject(userTO);
if (principal.getName().equals(userTO.getLogin()) || permissionService.hasPermission(principal,Permission.SU)) {
return userTransferService.getTO(userService.modify(user));
} else {
throw new IllegalAccessException("You are not allowed to modify user");
}
}
User is null, but UserTO is filled. So mocked method UserTransferService.getObject(userTO) is not working properly.
I am using Jhipster with Oauth2 implementation and mongodb as a database.
I am trying to test a resource with OAuth2. But I got always an error message "Access Denied" and status code 401. I am looking for an JUnit example with OAuth2. Thank you!
Manuel
/**
* Test class for the InvoiceResource REST controller.
*
* #see InvoiceResource
*/
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#IntegrationTest
public class InvoiceResourceIntTest {
...
private MockMvc restInvoiceMockMvcWebApp;
#PostConstruct
public void setup() {
MockitoAnnotations.initMocks(this);
this.restInvoiceMockMvcWebApp = MockMvcBuilders.webAppContextSetup(context).alwaysDo(MockMvcResultHandlers.print())
.apply(SecurityMockMvcConfigurers.springSecurity()).build();
}
#Before
public void initTest() {
// Create currentuser
currentUser = new User();
currentUser.setActivated(CURRENTUSER_ACTIVATED);
currentUser.setFirstName(CURRENTUSER_FIRSTNAME);
currentUser.setLastName(CURRENTUSER_LASTNAME);
currentUser.setEmail(CURRENTUSER_EMAIL);
Set<Authority> authorities = new HashSet<>();
Authority authority = new Authority();
authority.setName(AuthoritiesConstants.ADMIN);
currentUser.setAuthorities(authorities);
currentUser.setPassword(passwordEncoder.encode(CURRENTUSER_PASSWORD));
userRepository.save(currentUser);
}
#Test
// #WithMockUser(username = CURRENTUSER_EMAIL, password = CURRENTUSER_PASSWORD, roles = { "ADMIN" })
public void getAllInvoices() throws Exception {
// Initialize the database
invoice.setDeletedAt(LocalDate.now());
invoiceRepository.save(invoice);
invoice.setId(null);
invoice.setDeletedAt(null);
invoiceRepository.save(invoice);
// Get all the invoices
restInvoiceMockMvcWebApp.perform(get("/api/invoicessort=id,desc")
.with(user(CURRENTUSER_EMAIL).password(CURRENTUSER_PASSWORD.roles("ADMIN")))
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON)).andExpect(jsonPath("$", hasSize(1)))
}
You can get a token from the token resource, and use that token in your tests, here a complete example.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
public class PermissionTest {
#Autowired
WebApplicationContext context;
#Autowired
FilterChainProxy springSecurityFilterChain;
MockMvc mvc;
#Before
public void setUp() {
mvc = MockMvcBuilders.webAppContextSetup(context)
.addFilter(springSecurityFilterChain).build();
}
#Test
public void shouldHavePermission() throws Exception {
mvc.perform(get("/api/resource")
.header("Authorization", "Bearer " + getAccessToken("user", "123"))
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}
private String getAccessToken(String username, String password) {
MockHttpServletResponse response = mvc
.perform(post("/oauth/token")
.header("Authorization", "Basic "
+ new String(Base64Utils.encode(("appclient:password")
.getBytes())))
.param("username", username)
.param("password", password)
.param("grant_type", "password"))
.andReturn().getResponse();
return new ObjectMapper()
.readValue(response.getContentAsByteArray(), OAuthToken.class)
.accessToken;
}
#JsonIgnoreProperties(ignoreUnknown = true)
private static class OAuthToken {
#JsonProperty("access_token")
public String accessToken;
}
}
I'm trying to understand how to use a OAuth2RestTemplate object to consume my OAuth2 secured REST service (which is running under a different project and let's assume also on a different server etc...)
An example of my REST service is:
http://localhost:8082/app/helloworld
-> Accessing this URL generates an error as I am not authenticated
To request a token I would go to:
http://localhost:8082/app/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=**USERNAME**&password=**PASSWORD**
After I receive the token I can then connect to the REST API by using the following URL (example token inserted)
http://localhost:8082/app/helloworld/?access_token=**4855f557-c6ee-43b7-8617-c24591965206**
Now my question is how do I implement a second application which can consume this OAuth2 secured REST API? I really haven't found any working examples where you provide the user name and password (e.g. coming from a login form) and then a token is generated which can be re-used to get data from the REST API.
I currently tried something with the following objects:
BaseOAuth2ProtectedResourceDetails baseOAuth2ProtectedResourceDetails = new BaseOAuth2ProtectedResourceDetails();
baseOAuth2ProtectedResourceDetails.setClientId("restapp");
baseOAuth2ProtectedResourceDetails.setClientSecret("restapp");
baseOAuth2ProtectedResourceDetails.setGrantType("password");
// how to set user name and password ???
DefaultAccessTokenRequest accessTokenRequest = new DefaultAccessTokenRequest();
OAuth2ClientContext oAuth2ClientContext = new DefaultOAuth2ClientContext(accessTokenRequest());
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(baseOAuth2ProtectedResourceDetails,oAuth2ClientContext);
But this just isn't working :(
Any ideas, links to working examples or tutorials are greatly appreciated.
You can find examples for writing OAuth clients here:
https://github.com/spring-projects/spring-security-oauth
In your case you can't just use default or base classes for everything, you have a multiple classes Implementing OAuth2ProtectedResourceDetails. The configuration depends of how you configured your OAuth service but assuming from your curl connections I would recommend:
#EnableOAuth2Client
#Configuration
class MyConfig{
#Value("${oauth.resource:http://localhost:8082}")
private String baseUrl;
#Value("${oauth.authorize:http://localhost:8082/oauth/authorize}")
private String authorizeUrl;
#Value("${oauth.token:http://localhost:8082/oauth/token}")
private String tokenUrl;
#Bean
protected OAuth2ProtectedResourceDetails resource() {
ResourceOwnerPasswordResourceDetails resource;
resource = new ResourceOwnerPasswordResourceDetails();
List scopes = new ArrayList<String>(2);
scopes.add("write");
scopes.add("read");
resource.setAccessTokenUri(tokenUrl);
resource.setClientId("restapp");
resource.setClientSecret("restapp");
resource.setGrantType("password");
resource.setScope(scopes);
resource.setUsername("**USERNAME**");
resource.setPassword("**PASSWORD**");
return resource;
}
#Bean
public OAuth2RestOperations restTemplate() {
AccessTokenRequest atr = new DefaultAccessTokenRequest();
return new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(atr));
}
}
#Service
#SuppressWarnings("unchecked")
class MyService {
#Autowired
private OAuth2RestOperations restTemplate;
public MyService() {
restTemplate.getAccessToken();
}
}
Do not forget about #EnableOAuth2Client on your config class, also I would suggest to try that the urls you are using are working with curl first, also try to trace it with the debugger because lot of exceptions are just consumed and never printed out due security reasons, so it gets little hard to find where the issue is. You should use logger with debug enabled set.
Good luck
I uploaded sample springboot app on github https://github.com/mariubog/oauth-client-sample
to depict your situation because I could not find any samples for your scenario .
In the answer from #mariubog (https://stackoverflow.com/a/27882337/1279002) I was using password grant types too as in the example but needed to set the client authentication scheme to form. Scopes were not supported by the endpoint for password and there was no need to set the grant type as the ResourceOwnerPasswordResourceDetails object sets this itself in the constructor.
...
public ResourceOwnerPasswordResourceDetails() {
setGrantType("password");
}
...
The key thing for me was the client_id and client_secret were not being added to the form object to post in the body if resource.setClientAuthenticationScheme(AuthenticationScheme.form); was not set.
See the switch in:
org.springframework.security.oauth2.client.token.auth.DefaultClientAuthenticationHandler.authenticateTokenRequest()
Finally, when connecting to Salesforce endpoint the password token needed to be appended to the password.
#EnableOAuth2Client
#Configuration
class MyConfig {
#Value("${security.oauth2.client.access-token-uri}")
private String tokenUrl;
#Value("${security.oauth2.client.client-id}")
private String clientId;
#Value("${security.oauth2.client.client-secret}")
private String clientSecret;
#Value("${security.oauth2.client.password-token}")
private String passwordToken;
#Value("${security.user.name}")
private String username;
#Value("${security.user.password}")
private String password;
#Bean
protected OAuth2ProtectedResourceDetails resource() {
ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
resource.setAccessTokenUri(tokenUrl);
resource.setClientId(clientId);
resource.setClientSecret(clientSecret);
resource.setClientAuthenticationScheme(AuthenticationScheme.form);
resource.setUsername(username);
resource.setPassword(password + passwordToken);
return resource;
}
#Bean
public OAuth2RestOperations restTemplate() {
return new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));
}
}
#Service
#SuppressWarnings("unchecked")
class MyService {
#Autowired
private OAuth2RestOperations restTemplate;
public MyService() {
restTemplate.getAccessToken();
}
}
I have different approach if you want access token and make call to other resource system with access token in header
Spring Security comes with automatic security: oauth2 properties access from application.yml file for every request and every request has SESSIONID which it reads and pull user info via Principal, so you need to make sure inject Principal in OAuthUser and get accessToken and make call to resource server
This is your application.yml, change according to your auth server:
security:
oauth2:
client:
clientId: 233668646673605
clientSecret: 33b17e044ee6a4fa383f46ec6e28ea1d
accessTokenUri: https://graph.facebook.com/oauth/access_token
userAuthorizationUri: https://www.facebook.com/dialog/oauth
tokenName: oauth_token
authenticationScheme: query
clientAuthenticationScheme: form
resource:
userInfoUri: https://graph.facebook.com/me
#Component
public class OAuthUser implements Serializable {
private static final long serialVersionUID = 1L;
private String authority;
#JsonIgnore
private String clientId;
#JsonIgnore
private String grantType;
private boolean isAuthenticated;
private Map<String, Object> userDetail = new LinkedHashMap<String, Object>();
#JsonIgnore
private String sessionId;
#JsonIgnore
private String tokenType;
#JsonIgnore
private String accessToken;
#JsonIgnore
private Principal principal;
public void setOAuthUser(Principal principal) {
this.principal = principal;
init();
}
public Principal getPrincipal() {
return principal;
}
private void init() {
if (principal != null) {
OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) principal;
if (oAuth2Authentication != null) {
for (GrantedAuthority ga : oAuth2Authentication.getAuthorities()) {
setAuthority(ga.getAuthority());
}
setClientId(oAuth2Authentication.getOAuth2Request().getClientId());
setGrantType(oAuth2Authentication.getOAuth2Request().getGrantType());
setAuthenticated(oAuth2Authentication.getUserAuthentication().isAuthenticated());
OAuth2AuthenticationDetails oAuth2AuthenticationDetails = (OAuth2AuthenticationDetails) oAuth2Authentication
.getDetails();
if (oAuth2AuthenticationDetails != null) {
setSessionId(oAuth2AuthenticationDetails.getSessionId());
setTokenType(oAuth2AuthenticationDetails.getTokenType());
// This is what you will be looking for
setAccessToken(oAuth2AuthenticationDetails.getTokenValue());
}
// This detail is more related to Logged-in User
UsernamePasswordAuthenticationToken userAuthenticationToken = (UsernamePasswordAuthenticationToken) oAuth2Authentication.getUserAuthentication();
if (userAuthenticationToken != null) {
LinkedHashMap<String, Object> detailMap = (LinkedHashMap<String, Object>) userAuthenticationToken.getDetails();
if (detailMap != null) {
for (Map.Entry<String, Object> mapEntry : detailMap.entrySet()) {
//System.out.println("#### detail Key = " + mapEntry.getKey());
//System.out.println("#### detail Value = " + mapEntry.getValue());
getUserDetail().put(mapEntry.getKey(), mapEntry.getValue());
}
}
}
}
}
}
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getGrantType() {
return grantType;
}
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public boolean isAuthenticated() {
return isAuthenticated;
}
public void setAuthenticated(boolean isAuthenticated) {
this.isAuthenticated = isAuthenticated;
}
public Map<String, Object> getUserDetail() {
return userDetail;
}
public void setUserDetail(Map<String, Object> userDetail) {
this.userDetail = userDetail;
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public String getTokenType() {
return tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
#Override
public String toString() {
return "OAuthUser [clientId=" + clientId + ", grantType=" + grantType + ", isAuthenticated=" + isAuthenticated
+ ", userDetail=" + userDetail + ", sessionId=" + sessionId + ", tokenType="
+ tokenType + ", accessToken= " + accessToken + " ]";
}
#RestController
public class YourController {
#Autowired
OAuthUser oAuthUser;
// In case if you want to see Profile of user then you this
#RequestMapping(value = "/profile", produces = MediaType.APPLICATION_JSON_VALUE)
public OAuthUser user(Principal principal) {
oAuthUser.setOAuthUser(principal);
// System.out.println("#### Inside user() - oAuthUser.toString() = " + oAuthUser.toString());
return oAuthUser;
}
#RequestMapping(value = "/createOrder",
method = RequestMethod.POST,
headers = {"Content-type=application/json"},
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public FinalOrderDetail createOrder(#RequestBody CreateOrder createOrder) {
return postCreateOrder_restTemplate(createOrder, oAuthUser).getBody();
}
private ResponseEntity<String> postCreateOrder_restTemplate(CreateOrder createOrder, OAuthUser oAuthUser) {
String url_POST = "your post url goes here";
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("Authorization", String.format("%s %s", oAuthUser.getTokenType(), oAuthUser.getAccessToken()));
headers.add("Content-Type", "application/json");
RestTemplate restTemplate = new RestTemplate();
//restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
HttpEntity<String> request = new HttpEntity<String>(createOrder, headers);
ResponseEntity<String> result = restTemplate.exchange(url_POST, HttpMethod.POST, request, String.class);
System.out.println("#### post response = " + result);
return result;
}
}
My simple solution. IMHO it's the cleanest.
First create a application.yml
spring.main.allow-bean-definition-overriding: true
security:
oauth2:
client:
clientId: XXX
clientSecret: XXX
accessTokenUri: XXX
tokenName: access_token
grant-type: client_credentials
Create the main class: Main
#SpringBootApplication
#EnableOAuth2Client
public class Main extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll();
}
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
#Bean
public OAuth2RestTemplate oauth2RestTemplate(ClientCredentialsResourceDetails details) {
return new OAuth2RestTemplate(details);
}
}
Then Create the controller class: Controller
#RestController
class OfferController {
#Autowired
private OAuth2RestOperations restOperations;
#RequestMapping(value = "/<your url>"
, method = RequestMethod.GET
, produces = "application/json")
public String foo() {
ResponseEntity<String> responseEntity = restOperations.getForEntity(<the url you want to call on the server>, String.class);
return responseEntity.getBody();
}
}
Maven dependencies
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
</dependencies>