This is an automated email from the ASF dual-hosted git repository. ofuks pushed a commit to branch DLAB-1156 in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git
commit 5b1f7f9474054a769679a99642dec3b84e93f122 Author: ofuks <olegfuk...@gmail.com> AuthorDate: Wed Oct 2 14:01:32 2019 +0300 [DLAB-1156]: Created endpoint to get new access and refresh token in case when access token is expired --- .../src/main/java/com/epam/dlab/auth/UserInfo.java | 13 +++++++++-- .../backendapi/resources/KeycloakResource.java | 27 +++++++++++++++++++++- .../backendapi/service/SecurityServiceImpl.java | 26 ++++++--------------- .../epam/dlab/backendapi/util/KeycloakUtil.java | 22 ++++++++++++++++++ 4 files changed, 66 insertions(+), 22 deletions(-) diff --git a/services/dlab-webapp-common/src/main/java/com/epam/dlab/auth/UserInfo.java b/services/dlab-webapp-common/src/main/java/com/epam/dlab/auth/UserInfo.java index b0c05bf..5c6a74f 100644 --- a/services/dlab-webapp-common/src/main/java/com/epam/dlab/auth/UserInfo.java +++ b/services/dlab-webapp-common/src/main/java/com/epam/dlab/auth/UserInfo.java @@ -32,6 +32,7 @@ public class UserInfo implements Principal { private final String username; private final String accessToken; + private String refreshToken; private final Set<String> roles = new HashSet<>(); private final Map<String,String> keys = new HashMap<>(); @@ -66,6 +67,15 @@ public class UserInfo implements Principal { return accessToken; } + @JsonProperty("refresh_token") + public String getRefreshToken() { + return refreshToken; + } + + public void setRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + } + @JsonProperty("roles") public Set<String> getRoles() { return roles; @@ -121,8 +131,6 @@ public class UserInfo implements Principal { return newInfo; } - - public boolean isAwsUser() { return awsUser; } @@ -182,6 +190,7 @@ public class UserInfo implements Principal { return "UserInfo{" + "username='" + username + '\'' + ", accessToken='" + accessToken + '\'' + + ", refreshToken='" + refreshToken + '\'' + ", roles=" + roles + ", keys=" + keys.keySet() + ", firstName='" + firstName + '\'' + diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/KeycloakResource.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/KeycloakResource.java index e719215..0a6e6d2 100644 --- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/KeycloakResource.java +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/KeycloakResource.java @@ -5,9 +5,12 @@ import com.epam.dlab.backendapi.conf.KeycloakConfiguration; import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration; import com.epam.dlab.backendapi.dao.SecurityDAO; import com.epam.dlab.backendapi.roles.UserRoles; +import com.epam.dlab.backendapi.service.KeycloakService; import com.epam.dlab.backendapi.service.SecurityService; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.inject.Inject; import io.dropwizard.auth.Auth; +import org.keycloak.representations.AccessTokenResponse; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; @@ -24,6 +27,7 @@ public class KeycloakResource { private static final String KEYCLOAK_LOGOUT_URI_FORMAT = "%s/realms/%s/protocol/openid-connect/logout" + "?redirect_uri="; private final SecurityService securityService; + private final KeycloakService keycloakService; private final SecurityDAO securityDAO; private final String loginUri; private final String logoutUri; @@ -32,12 +36,13 @@ public class KeycloakResource { @Inject public KeycloakResource(SecurityService securityService, SelfServiceApplicationConfiguration configuration, - SecurityDAO securityDAO) { + SecurityDAO securityDAO, KeycloakService keycloakService) { this.securityDAO = securityDAO; this.defaultAccess = configuration.getRoleDefaultAccess(); final KeycloakConfiguration keycloakConfiguration = configuration.getKeycloakConfiguration(); this.redirectUri = keycloakConfiguration.getRedirectUri(); this.securityService = securityService; + this.keycloakService = keycloakService; loginUri = format(LOGIN_URI_FORMAT, @@ -78,4 +83,24 @@ public class KeycloakResource { .location(new URI(logoutUri + redirectUri)) .build(); } + + @POST + @Path("/refresh/{refresh_token}") + @Produces(MediaType.APPLICATION_JSON) + public Response refreshAccessToken(@PathParam("refresh_token") String refreshToken) { + AccessTokenResponse tokenResponse = keycloakService.refreshToken(refreshToken); + return Response.ok(new TokenInfo(tokenResponse.getToken(), tokenResponse.getRefreshToken())).build(); + } + + class TokenInfo { + @JsonProperty("access_token") + private final String accessToken; + @JsonProperty("refresh_token") + private final String refreshToken; + + TokenInfo(String accessToken, String refreshToken) { + this.accessToken = accessToken; + this.refreshToken = refreshToken; + } + } } diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/SecurityServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/SecurityServiceImpl.java index f2930cd..9b17d91 100644 --- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/SecurityServiceImpl.java +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/SecurityServiceImpl.java @@ -2,12 +2,10 @@ package com.epam.dlab.backendapi.service; import com.epam.dlab.auth.UserInfo; import com.epam.dlab.backendapi.dao.SecurityDAO; +import com.epam.dlab.backendapi.util.KeycloakUtil; import com.epam.dlab.exceptions.DlabException; import com.google.inject.Inject; -import org.keycloak.common.util.Base64Url; import org.keycloak.representations.AccessTokenResponse; -import org.keycloak.representations.IDToken; -import org.keycloak.util.JsonSerialization; public class SecurityServiceImpl implements SecurityService { private final KeycloakService keycloakService; @@ -22,9 +20,11 @@ public class SecurityServiceImpl implements SecurityService { @Override public UserInfo getUserInfo(String code) { final AccessTokenResponse token = keycloakService.getToken(code); - final String username = parseToken(token.getToken()).getPreferredUsername(); + final String username = KeycloakUtil.parseToken(token.getToken()).getPreferredUsername(); securityDAO.saveUser(username, token); - return new UserInfo(username, token.getToken()); + UserInfo userInfo = new UserInfo(username, token.getToken()); + userInfo.setRefreshToken(token.getRefreshToken()); + return userInfo; } @Override @@ -32,20 +32,8 @@ public class SecurityServiceImpl implements SecurityService { return securityDAO.getTokenResponse(username) .map(AccessTokenResponse::getRefreshToken) .map(keycloakService::refreshToken) - .map(accessTokenResponse -> new UserInfo(parseToken(accessTokenResponse.getToken()).getPreferredUsername(), accessTokenResponse.getToken())) + .map(accessTokenResponse -> new UserInfo(KeycloakUtil.parseToken(accessTokenResponse.getToken()).getPreferredUsername(), + accessTokenResponse.getToken())) .orElseThrow(() -> new DlabException("Can not find token for user " + username)); } - - private IDToken parseToken(String encoded) { - try { - String[] parts = encoded.split("\\."); - if (parts.length < 2 || parts.length > 3) { - throw new IllegalArgumentException("Parsing error"); - } - byte[] bytes = Base64Url.decode(parts[1]); - return JsonSerialization.readValue(bytes, IDToken.class); - } catch (Exception e) { - throw new DlabException("Can not parse token due to: " + e.getMessage()); - } - } } diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/util/KeycloakUtil.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/util/KeycloakUtil.java new file mode 100644 index 0000000..63fc62c --- /dev/null +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/util/KeycloakUtil.java @@ -0,0 +1,22 @@ +package com.epam.dlab.backendapi.util; + +import com.epam.dlab.exceptions.DlabException; +import org.keycloak.common.util.Base64Url; +import org.keycloak.representations.IDToken; +import org.keycloak.util.JsonSerialization; + +public class KeycloakUtil { + + public static IDToken parseToken(String encoded) { + try { + String[] parts = encoded.split("\\."); + if (parts.length < 2 || parts.length > 3) { + throw new IllegalArgumentException("Parsing error"); + } + byte[] bytes = Base64Url.decode(parts[1]); + return JsonSerialization.readValue(bytes, IDToken.class); + } catch (Exception e) { + throw new DlabException("Can not parse token due to: " + e.getMessage()); + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@dlab.apache.org For additional commands, e-mail: commits-h...@dlab.apache.org