Skip to content

Commit

Permalink
Merge pull request #15 from protegeproject/WHO-setup
Browse files Browse the repository at this point in the history
Who setup
  • Loading branch information
matthewhorridge authored Jun 28, 2024
2 parents 93502cf + f1b5732 commit 29e01b7
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 27 deletions.
43 changes: 40 additions & 3 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- main-who

jobs:
build:
Expand Down Expand Up @@ -32,19 +33,55 @@ jobs:
server-id: docker.io
server-username: DOCKER_USERNAME
server-password: DOCKER_PASSWORD
- name: Get current version
id: get-version
run: |
current_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
echo "Current version: $current_version"
echo "::set-output name=current_version::$current_version"
- name: Bump version
id: bump
uses: mickem/gh-action-bump-maven-version@v1
run: |
current_version=${{ steps.get-version.outputs.current_version }}
branch=${GITHUB_REF##*/}
echo "Current branch: $branch"
# Extract the base version without suffix
base_version=$(echo $current_version | sed -E 's/(-.*)?$//')
# Increment the base version (assuming semantic versioning)
IFS='.' read -r -a version_parts <<< "$base_version"
version_parts[2]=$((version_parts[2] + 1))
new_base_version="${version_parts[0]}.${version_parts[1]}.${version_parts[2]}"
if [[ "$branch" == "main-who" ]]; then
new_version="${new_base_version}-WHO"
else
new_version="$new_base_version"
fi
echo "New version: $new_version"
mvn versions:set -DnewVersion=$new_version -DgenerateBackupPoms=false
echo ":: set-output name=new_version::$new_version"
- name: Commit new version
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git add pom.xml
git commit -m "Bump version to ${{ steps.bump.outputs.new_version }}"
git tag ${{ steps.bump.outputs.new_version }}
git push origin HEAD:${GITHUB_REF##*/}
git push origin ${{ steps.bump.outputs.new_version }}
- name: Build and Publish package
run: mvn --batch-mode -Prelease package dockerfile:push
- name: Release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.bump.outputs.tag }}
tag_name: ${{ steps.bump.outputs.new_version }}
generate_release_notes: true

env:
DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}}
DOCKER_TOKEN: ${{secrets.DOCKER_PASSWORD}}
DOCKER_TOKEN: ${{secrets.DOCKER_PASSWORD}}
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>
<groupId>edu.stanford.protege</groupId>
<artifactId>webprotege-gwt-api-gateway</artifactId>
<version>1.0.11</version>
<version>1.0.12-WHO</version>
<name>webprotege-gwt-api-gateway</name>
<description>The API Gateway for the WebProtégé GWT User Interface</description>
<properties>
Expand Down Expand Up @@ -77,7 +77,7 @@
<dependency>
<groupId>edu.stanford.protege</groupId>
<artifactId>webprotege-ipc</artifactId>
<version>1.0.4</version>
<version>1.0.5</version>
</dependency>

<dependency>
Expand Down Expand Up @@ -153,7 +153,7 @@
<dependency>
<groupId>edu.stanford.protege</groupId>
<artifactId>webprotege-backend-api</artifactId>
<version>1.0.23</version>
<version>1.0.24-WHO</version>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public FileSubmissionId storeFile(Path tempFile) {
logger.info("Storing file ({}) in {} bucket with an object id of {}", getFileSizeInMB(tempFile), minioProperties.getBucketName(), fileIdentifier);
createBucketIfNecessary();
uploadObject(tempFile, fileIdentifier);
logger.info("File {} uploaded successfully !", fileIdentifier);
return new FileSubmissionId(fileIdentifier);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package edu.stanford.protege.webprotege.gateway;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.stanford.protege.webprotege.common.UserId;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -34,8 +38,12 @@ public class GatewayController {

private final RpcRequestProcessor rpcRequestProcessor;

public GatewayController(RpcRequestProcessor rpcRequestProcessor) {
private final LogoutHandler logoutHandler;


public GatewayController(RpcRequestProcessor rpcRequestProcessor, LogoutHandler logoutHandler) {
this.rpcRequestProcessor = rpcRequestProcessor;
this.logoutHandler = logoutHandler;
}

@PostMapping(path = "/api/execute", consumes = "application/json")
Expand Down Expand Up @@ -64,4 +72,10 @@ public RpcResponse execute(@RequestBody RpcRequest request,
return RpcResponse.forError(request.methodName(), HttpStatus.GATEWAY_TIMEOUT);
}
}

@GetMapping(path = "/logout")
public HttpServletResponse logout(HttpServletRequest request, HttpServletResponse response) {
logoutHandler.logout(request, response, SecurityContextHolder.getContext().getAuthentication());
return response;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;

@Component
public class KeycloakLogoutHandler implements LogoutHandler {
public class KeycloakLogoutHandler extends SecurityContextLogoutHandler {

private static final Logger logger = LoggerFactory.getLogger(KeycloakLogoutHandler.class);
private final RestTemplate restTemplate;
Expand All @@ -26,21 +31,25 @@ public KeycloakLogoutHandler() {
@Override
public void logout(HttpServletRequest request, HttpServletResponse response,
Authentication auth) {
logoutFromKeycloak((OidcUser) auth.getPrincipal());
logoutFromKeycloak((Jwt) auth.getPrincipal());
super.logout(request, response,auth);
}

private void logoutFromKeycloak(OidcUser user) {
String endSessionEndpoint = user.getIssuer() + "/protocol/openid-connect/logout";
UriComponentsBuilder builder = UriComponentsBuilder
.fromUriString(endSessionEndpoint)
.queryParam("id_token_hint", user.getIdToken().getTokenValue());

ResponseEntity<String> logoutResponse = restTemplate.getForEntity(
builder.toUriString(), String.class);
if (logoutResponse.getStatusCode().is2xxSuccessful()) {
logger.info("Successfulley logged out from Keycloak");
} else {
logger.error("Could not propagate logout to Keycloak");
private void logoutFromKeycloak(Jwt token) {
String issuer = token.getClaimAsString("iss");
String endSessionEndpoint = issuer + "/protocol/openid-connect/logout";

String accessToken = token.getTokenValue();
try {
URI logoutUri = new URI(endSessionEndpoint + "?token=" + accessToken);
ResponseEntity<String> logoutResponse = restTemplate.getForEntity(logoutUri, String.class);
if (logoutResponse.getStatusCode().is2xxSuccessful()) {
logger.info("Successfulley logged out from Keycloak");
} else {
logger.error("Could not propagate logout to Keycloak");
}
} catch (Exception e) {
e.printStackTrace();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package edu.stanford.protege.webprotege.gateway;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
Expand All @@ -10,9 +11,14 @@
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.AuthorizationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

Expand All @@ -39,16 +45,19 @@ public class SecurityConfig {
SecurityConfig(KeycloakLogoutHandler keycloakLogoutHandler) {
this.keycloakLogoutHandler = keycloakLogoutHandler;
}

@Bean
public LogoutFilter customLogoutFilter() {
return new LogoutFilter("/login?logout", keycloakLogoutHandler);
}

@Bean
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
/* @Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.debug(true);
}
}*/
@Bean
public SecurityFilterChain resourceServerFilterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
Expand All @@ -57,10 +66,12 @@ public SecurityFilterChain resourceServerFilterChain(HttpSecurity http) throws E
.anyRequest()
.authenticated()
);
http.addFilterAfter(customLogoutFilter(), AuthorizationFilter.class);
http.oauth2ResourceServer((oauth2) -> oauth2
.jwt(Customizer.withDefaults()));
http.oauth2Login(Customizer.withDefaults())
.logout(logout -> logout.addLogoutHandler(keycloakLogoutHandler).logoutSuccessUrl("/"));
.logout(AbstractHttpConfigurer::disable);

return http.build();
}

Expand Down
18 changes: 17 additions & 1 deletion src/main/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
server:
port: 7777

logging:
level:
org:
springframework:
amqp: ERROR
spring:
application:
name: webprotege-gwt-api-gateway
Expand All @@ -11,15 +16,26 @@ spring:
password: guest
publisher-confirm-type: correlated
publisher-returns: true
servlet:
multipart:
max-file-size: 200MB
max-request-size: 200MB


webprotege:
rabbitmq:
requestqueue: webprotege-gwt-api-gateway-queue
responsequeue: webprotege-gwt-api-gateway-response-queue
eventsqueue: webprotege-gwt-api-gateway-event-queue
timeout: 60000
timeout: 120000
event-subscribe: true
allowedOrigin: webprotege-local.edu
minio:
accessKey: webprotege
endPoint: http://webprotege-local.edu:9000
secretKey: webprotege
bucketName: webprotege-uploads


spring.security.oauth2:
client:
Expand Down

0 comments on commit 29e01b7

Please sign in to comment.