This is the codeAbility Sharing Platform! Learn more about the codeAbility Sharing Platform.

Skip to content
Snippets Groups Projects
Commit dd3aafb7 authored by Michael Breu's avatar Michael Breu :speech_balloon:
Browse files

Resolving #196: SessionManagement in Application disabled Spring OAuth

Authorization Management replaced by a solution without sessions
parent bbb33c2c
2 merge requests!188Merging Peer Reviewing et. al to Master,!164211 peer reviewing functionality
......@@ -44,8 +44,10 @@ import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.core.endpoint.PkceParameterNames;
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
......@@ -73,6 +75,7 @@ import at.ac.uibk.gitsearch.domain.User;
import at.ac.uibk.gitsearch.security.AuthoritiesConstants;
import at.ac.uibk.gitsearch.security.jwt.JWTConfigurer;
import at.ac.uibk.gitsearch.security.jwt.TokenProvider;
import at.ac.uibk.gitsearch.security.oauth2.GitSearchOAuth2AuthorizationRequestRepository;
import at.ac.uibk.gitsearch.security.oauth2.SavedRequestAwareAuthenticationSuccessHandlerWithJWTSupport;
import at.ac.uibk.gitsearch.security.oauth2.UserDetailsFetcher;
import at.ac.uibk.gitsearch.service.UserService;
......@@ -149,7 +152,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
.deny()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/statistics/**").permitAll()
......@@ -185,7 +188,10 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
.and()
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.oidcUserService(this.oidcUserService())))
.oidcUserService(this.oidcUserService()))
.authorizationEndpoint(
authorizationEndpointConfig -> authorizationEndpointConfig.authorizationRequestRepository(getOAuth2AuthorizatinRequestRepository()))
)
.oauth2Login().successHandler(getAuthenticationSuccessHandler())
.and()
.oauth2ResourceServer() // .bearerTokenResolver(bearerTokenResolver)
......@@ -203,7 +209,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
// .apply(securityConfigurerAdapter())
// @formatter:on
}
Converter<Jwt, AbstractAuthenticationToken> authenticationConverter() {
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(new at.ac.uibk.gitsearch.security.oauth2.JwtGrantedAuthorityConverter());
......@@ -356,6 +362,11 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
return new SavedRequestAwareAuthenticationSuccessHandlerWithJWTSupport(tokenProvider);
}
@Bean
public AuthorizationRequestRepository<OAuth2AuthorizationRequest> getOAuth2AuthorizatinRequestRepository() {
return new GitSearchOAuth2AuthorizationRequestRepository();
}
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
final OidcUserService delegate = new OidcUserService();
......
package at.ac.uibk.gitsearch.security.oauth2;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.util.Assert;
/**
* a specialized version of OAuth2 2AuthorizationRequestRepository that does not uses sessions to store requests.
* @author Michael Breu
*
*/
public class GitSearchOAuth2AuthorizationRequestRepository implements AuthorizationRequestRepository<OAuth2AuthorizationRequest>{
/**
* TODO this should be persisted in the database!
*/
private Map<String, OAuth2AuthorizationRequest> authorizationRequests = new HashMap<>();
@Override
public OAuth2AuthorizationRequest loadAuthorizationRequest(HttpServletRequest request) {
Assert.notNull(request, "request cannot be null");
String stateParameter = this.getStateParameter(request);
if (stateParameter == null) {
return null;
}
// Map<String, OAuth2AuthorizationRequest> authorizationRequests = this.getAuthorizationRequests(request);
return authorizationRequests.get(stateParameter);
}
@Override
public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, HttpServletRequest request,
HttpServletResponse response) {
Assert.notNull(request, "request cannot be null");
Assert.notNull(response, "response cannot be null");
if (authorizationRequest == null) {
this.removeAuthorizationRequest(request, response);
return;
}
String state = authorizationRequest.getState();
Assert.hasText(state, "authorizationRequest.state cannot be empty");
// Map<String, OAuth2AuthorizationRequest> authorizationRequests = this.getAuthorizationRequests(request);
authorizationRequests.put(state, authorizationRequest);
// request.getSession().setAttribute(this.sessionAttributeName, authorizationRequests);
}
@Override
public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request) {
Assert.notNull(request, "request cannot be null");
String stateParameter = this.getStateParameter(request);
if (stateParameter == null) {
return null;
}
// Map<String, OAuth2AuthorizationRequest> authorizationRequests = this.getAuthorizationRequests(request);
OAuth2AuthorizationRequest originalRequest = authorizationRequests.remove(stateParameter);
// if (!authorizationRequests.isEmpty()) {
// request.getSession().setAttribute(this.sessionAttributeName, authorizationRequests);
// } else {
// request.getSession().removeAttribute(this.sessionAttributeName);
// }
return originalRequest;
}
@Override
public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request, HttpServletResponse response) {
Assert.notNull(response, "response cannot be null");
return this.removeAuthorizationRequest(request);
}
/**
* Gets the state parameter from the {@link HttpServletRequest}
* @param request the request to use
* @return the state parameter or null if not found
*/
private String getStateParameter(HttpServletRequest request) {
return request.getParameter(OAuth2ParameterNames.STATE);
}
// /**
// * Gets a non-null and mutable map of {@link OAuth2AuthorizationRequest#getState()} to an {@link OAuth2AuthorizationRequest}
// * @param request
// * @return a non-null and mutable map of {@link OAuth2AuthorizationRequest#getState()} to an {@link OAuth2AuthorizationRequest}.
// */
// private Map<String, OAuth2AuthorizationRequest> getAuthorizationRequests(HttpServletRequest request) {
// HttpSession session = request.getSession(false);
// Map<String, OAuth2AuthorizationRequest> authorizationRequests = session == null ? null :
// (Map<String, OAuth2AuthorizationRequest>) session.getAttribute(this.sessionAttributeName);
// if (authorizationRequests == null) {
// return new HashMap<>();
// }
// return authorizationRequests;
// }
}
package at.ac.uibk.gitsearch.security.oauth2;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import at.ac.uibk.gitsearch.GitsearchApp;
@SpringBootTest(classes = GitsearchApp.class)
public class GitSearchOAuth2AuthorizationRequestRepositoryTest {
private static final String TEST_STATE = "JustATestState";
@Autowired
private GitSearchOAuth2AuthorizationRequestRepository requestRepository;
@Test
public void testRepositorySimple() {
MockHttpServletRequest mockedRequest = new MockHttpServletRequest();
mockedRequest.addParameter(OAuth2ParameterNames.STATE, TEST_STATE);
MockHttpServletResponse mockedResponse = new MockHttpServletResponse();
OAuth2AuthorizationRequest oauthRequest =
OAuth2AuthorizationRequest.authorizationCode().state(TEST_STATE)
.authorizationUri("http://unusedHere")
.clientId("someClientId")
.build();
requestRepository.saveAuthorizationRequest(oauthRequest, mockedRequest, mockedResponse);
OAuth2AuthorizationRequest retrievedRequest = requestRepository.loadAuthorizationRequest(mockedRequest);
Assert.assertEquals(oauthRequest, retrievedRequest);
OAuth2AuthorizationRequest deletedRequest = requestRepository.removeAuthorizationRequest(mockedRequest);
Assert.assertEquals(oauthRequest, deletedRequest);
Assert.assertNull("it should be removed", requestRepository.removeAuthorizationRequest(mockedRequest));
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment