Skip to content
Snippets Groups Projects
Commit fa4bf6f1 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Added refresh token support

parent 98edfafe
No related branches found
No related tags found
No related merge requests found
......@@ -61,7 +61,7 @@ export default {
}
#loading {
position: absolute;
position: fixed;
top: 0;
bottom: 0;
right: 0;
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>it.inaf.ia2</groupId>
......@@ -23,15 +23,15 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
......@@ -52,11 +52,6 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Embedded PostgreSQL: -->
<dependency>
<groupId>com.opentable.components</groupId>
......
......@@ -5,17 +5,16 @@ import java.util.Map;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
public class CustomAuthenticationData extends UsernamePasswordAuthenticationToken {
private final Map<String, Object> attributes;
private final OAuth2AccessToken accessToken;
private final OAuth2RefreshToken refreshToken;
private final String refreshToken;
public CustomAuthenticationData(String username, Map<String, Object> attributes,
Collection<? extends GrantedAuthority> authorities,
OAuth2AccessToken accessToken, OAuth2RefreshToken refreshToken) {
OAuth2AccessToken accessToken, String refreshToken) {
super(username, "N/A", authorities);
this.attributes = attributes;
this.accessToken = accessToken;
......@@ -30,7 +29,7 @@ public class CustomAuthenticationData extends UsernamePasswordAuthenticationToke
return accessToken;
}
public OAuth2RefreshToken getRefreshToken() {
public String getRefreshToken() {
return refreshToken;
}
}
......@@ -6,7 +6,6 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.security.oauth2.provider.token.store.jwk.JwkTokenStore;
......@@ -25,8 +24,9 @@ public class CustomIdTokenConverter extends DefaultUserAuthenticationConverter {
OAuth2AccessToken token = jwkTokenStore.readAccessToken(idToken);
String refreshToken = (String) map.get("refresh_token");
Map<String, Object> claims = token.getAdditionalInformation();
OAuth2RefreshToken refreshToken = token.getRefreshToken();
String principal = (String) claims.get("sub");
......
......@@ -16,12 +16,14 @@ public class SessionData {
private String userId;
private String accessToken;
private String refreshToken;
@PostConstruct
public void init() {
CustomAuthenticationData authn = (CustomAuthenticationData) ((OAuth2Authentication) request.getUserPrincipal()).getUserAuthentication();
userId = (String) authn.getPrincipal();
accessToken = (String) authn.getAccessToken().getValue();
refreshToken = authn.getRefreshToken();
}
public String getUserId() {
......@@ -31,4 +33,16 @@ public class SessionData {
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
}
......@@ -5,7 +5,9 @@ import it.inaf.ia2.gms.model.RapUser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
......@@ -13,7 +15,11 @@ import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
@Component
......@@ -22,11 +28,30 @@ public class RapClient {
@Value("${rap.ws-url}")
private String rapBaseUrl;
@Autowired
private SessionData sessionData;
@Value("${security.oauth2.client.access-token-uri}")
private String accessTokenUri;
@Value("${security.oauth2.client.client-id}")
private String clientId;
@Value("${security.oauth2.client.client-secret}")
private String clientSecret;
@Value("${security.oauth2.client.scope}")
private String scope;
private final SessionData sessionData;
private final RestTemplate rapRestTemplate;
private final RestTemplate refreshTokenRestTemplate;
@Autowired
private RestTemplate rapRestTemplate;
public RapClient(SessionData sessionData, RestTemplate rapRestTemplate) {
this.sessionData = sessionData;
this.rapRestTemplate = rapRestTemplate;
this.refreshTokenRestTemplate = new RestTemplate();
}
public List<RapUser> getUsers(Set<String> identifiers) {
......@@ -35,8 +60,11 @@ public class RapClient {
}
String url = rapBaseUrl + "/user?identifiers=" + String.join(",", identifiers);
return rapRestTemplate.exchange(url, HttpMethod.GET, getEntity(), new ParameterizedTypeReference<List<RapUser>>() {
return httpCall(entity -> {
return rapRestTemplate.exchange(url, HttpMethod.GET, entity, new ParameterizedTypeReference<List<RapUser>>() {
}).getBody();
});
}
public List<RapUser> searchUsers(String searchText) {
......@@ -46,12 +74,24 @@ public class RapClient {
}
String url = rapBaseUrl + "/user?search=" + searchText;
return rapRestTemplate.exchange(url, HttpMethod.GET, getEntity(), new ParameterizedTypeReference<List<RapUser>>() {
return httpCall(entity -> {
return rapRestTemplate.exchange(url, HttpMethod.GET, entity, new ParameterizedTypeReference<List<RapUser>>() {
}).getBody();
});
}
private <R> R httpCall(Function<HttpEntity<?>, R> function) {
return httpCall(function, null);
}
private HttpEntity<?> getEntity() {
return getEntity(null);
private <R, T> R httpCall(Function<HttpEntity<?>, R> function, T body) {
try {
return function.apply(getEntity(body));
} catch (HttpClientErrorException.Unauthorized ex) {
refreshToken();
return function.apply(getEntity(body));
}
}
private <T> HttpEntity<T> getEntity(T body) {
......@@ -63,4 +103,27 @@ public class RapClient {
return new HttpEntity<>(body, headers);
}
private void refreshToken() {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setBasicAuth(clientId, clientSecret);
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("grant_type", "refresh_token");
map.add("refresh_token", sessionData.getRefreshToken());
map.add("scope", scope.replace(",", " "));
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
ResponseEntity<Map> response = refreshTokenRestTemplate.postForEntity(accessTokenUri, request, Map.class);
Map<String, String> values = response.getBody();
sessionData.setAccessToken(values.get("access_token"));
sessionData.setRefreshToken(values.get("refresh_token"));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment