forked from hapifhir/hapi-fhir-jpaserver-starter
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add integration of security service (#1)
- Loading branch information
Showing
9 changed files
with
338 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
src/main/java/earth/angelson/security/AuthenticationInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package earth.angelson.security; | ||
|
||
import ca.uhn.fhir.i18n.Msg; | ||
import ca.uhn.fhir.interceptor.api.Hook; | ||
import ca.uhn.fhir.interceptor.api.Interceptor; | ||
import ca.uhn.fhir.interceptor.api.Pointcut; | ||
import ca.uhn.fhir.rest.api.server.RequestDetails; | ||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
|
||
|
||
@Interceptor | ||
public class AuthenticationInterceptor { | ||
/** | ||
* This interceptor implements HTTP Basic Auth, which specifies that | ||
* a username and password are provided in a header called Authorization. | ||
*/ | ||
@Hook(Pointcut.SERVER_INCOMING_REQUEST_POST_PROCESSED) | ||
public boolean incomingRequestPostProcessed( | ||
RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) | ||
throws AuthenticationException { | ||
|
||
|
||
String authHeader = theRequest.getHeader("Authorization"); | ||
|
||
// The format of the header must be: | ||
if (authHeader == null) { | ||
throw new AuthenticationException(Msg.code(642) + "Missing or invalid Authorization header"); | ||
} else if ("Bearer dfw98h38r".equals(authHeader)) { | ||
//todo validate token | ||
// This user has access only to Practitioner/1 resources | ||
return true; | ||
} else if ("Bearer 39ff939jgg".equals(authHeader)) { | ||
// This user has access to everything | ||
return true; | ||
} else { | ||
// Throw an HTTP 401 | ||
return true; | ||
// throw new AuthenticationException(Msg.code(644) + "Missing or invalid Authorization header value"); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/earth/angelson/security/AuthorizationInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package earth.angelson.security; | ||
|
||
import earth.angelson.security.cache.TokenCacheService; | ||
import ca.uhn.fhir.rest.api.server.RequestDetails; | ||
import ca.uhn.fhir.rest.server.interceptor.auth.IAuthRule; | ||
|
||
import java.util.List; | ||
|
||
@SuppressWarnings("ConstantConditions") | ||
public class AuthorizationInterceptor extends ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor { | ||
|
||
private final TokenCacheService tokenCacheService; | ||
|
||
public AuthorizationInterceptor(TokenCacheService tokenCacheService) { | ||
this.tokenCacheService = tokenCacheService; | ||
} | ||
|
||
@Override | ||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) { | ||
String authHeader = theRequestDetails.getHeader("Authorization"); | ||
|
||
//todo if service return empty unauthorized request 403 | ||
return tokenCacheService.getData(authHeader); | ||
} | ||
} |
77 changes: 77 additions & 0 deletions
77
src/main/java/earth/angelson/security/cache/TokenCacheService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package earth.angelson.security.cache; | ||
|
||
|
||
import earth.angelson.security.dto.RoleAttachmentsDTO; | ||
import ca.uhn.fhir.rest.server.interceptor.auth.IAuthRule; | ||
import ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder; | ||
import org.springframework.cache.annotation.Cacheable; | ||
import org.springframework.http.HttpEntity; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpMethod; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
import java.util.List; | ||
|
||
public class TokenCacheService { | ||
|
||
private final RestTemplate restTemplate; | ||
private final String url; | ||
|
||
public TokenCacheService(String url) { | ||
this.restTemplate = new RestTemplate(); | ||
this.url = url; | ||
} | ||
|
||
@Cacheable(value = "jwtTokenCache", cacheManager = "caffeineCacheManager") | ||
public List<IAuthRule> getData(String token) { | ||
HttpHeaders headers = new HttpHeaders(); | ||
headers.set("Authorization", token); | ||
|
||
// Create HttpEntity with headers | ||
HttpEntity<RoleAttachmentsDTO> entity = new HttpEntity<>(headers); | ||
|
||
ResponseEntity<RoleAttachmentsDTO> response = | ||
restTemplate.exchange(url, HttpMethod.GET, entity, RoleAttachmentsDTO.class); | ||
|
||
|
||
if (response.getBody() != null) { | ||
var builder = new RuleBuilder().build(); | ||
var role = response.getBody(); | ||
role.getRoles().stream().forEach(roleWithRuleDTO -> { | ||
roleWithRuleDTO.getRules().forEach(rule -> { | ||
switch (rule.getOperation()) { | ||
case "READ": { | ||
builder.addAll(new RuleBuilder() | ||
.allow() | ||
.read() | ||
.allResources() | ||
.withAnyId() | ||
.build()); | ||
break; | ||
} | ||
case "WRITE": { | ||
builder.addAll(new RuleBuilder() | ||
.allow() | ||
.write() | ||
.allResources() | ||
.withAnyId() | ||
.build()); | ||
break; | ||
} | ||
case "ALL": { | ||
builder.addAll(new RuleBuilder().allowAll().build()); | ||
break; | ||
} | ||
} | ||
|
||
}); | ||
}); | ||
return builder; | ||
} | ||
|
||
// By default, deny everything. This should never get hit, but it's | ||
// good to be defensive | ||
return new RuleBuilder().denyAll().build(); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
src/main/java/earth/angelson/security/config/SecurityConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package earth.angelson.security.config; | ||
|
||
import earth.angelson.security.AuthorizationInterceptor; | ||
import earth.angelson.security.cache.TokenCacheService; | ||
import com.github.benmanes.caffeine.cache.Caffeine; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.cache.CacheManager; | ||
import org.springframework.cache.annotation.EnableCaching; | ||
import org.springframework.cache.caffeine.CaffeineCacheManager; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
import java.util.concurrent.TimeUnit; | ||
|
||
@EnableCaching | ||
@Configuration | ||
public class SecurityConfiguration { | ||
|
||
|
||
@Value("${security.service.url:http:https://localhost:8081/account/info}") | ||
private String securityServiceUrl; | ||
|
||
@Bean | ||
public TokenCacheService tokenCacheService() { | ||
return new TokenCacheService(securityServiceUrl); | ||
} | ||
|
||
@Bean | ||
public AuthorizationInterceptor authorizationInterceptor(TokenCacheService tokenCacheService) { | ||
return new AuthorizationInterceptor(tokenCacheService); | ||
} | ||
|
||
@Bean | ||
public CacheManager caffeineCacheManager() { | ||
CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager(); | ||
caffeineCacheManager | ||
.setCaffeine(Caffeine.newBuilder() | ||
.expireAfterWrite(15, TimeUnit.MINUTES)); | ||
return caffeineCacheManager; | ||
} | ||
|
||
} |
33 changes: 33 additions & 0 deletions
33
src/main/java/earth/angelson/security/dto/RoleAttachmentsDTO.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package earth.angelson.security.dto; | ||
|
||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
public class RoleAttachmentsDTO { | ||
private Set<RoleWithRuleDTO> roles; | ||
private Set<Map<String, String>> attachments; | ||
|
||
public RoleAttachmentsDTO() { | ||
} | ||
|
||
public RoleAttachmentsDTO(Set<RoleWithRuleDTO> roles, Set<Map<String, String>> attachments) { | ||
this.roles = roles; | ||
this.attachments = attachments; | ||
} | ||
|
||
public Set<RoleWithRuleDTO> getRoles() { | ||
return roles; | ||
} | ||
|
||
public void setRoles(Set<RoleWithRuleDTO> roles) { | ||
this.roles = roles; | ||
} | ||
|
||
public Set<Map<String, String>> getAttachments() { | ||
return attachments; | ||
} | ||
|
||
public void setAttachments(Set<Map<String, String>> attachments) { | ||
this.attachments = attachments; | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
src/main/java/earth/angelson/security/dto/RoleWithRuleDTO.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package earth.angelson.security.dto; | ||
|
||
import java.util.Set; | ||
import java.util.UUID; | ||
|
||
public class RoleWithRuleDTO { | ||
private UUID id; | ||
private String roleName; | ||
private Set<RuleDTO> rules; | ||
|
||
public RoleWithRuleDTO() { | ||
} | ||
|
||
public RoleWithRuleDTO(UUID id, String roleName, Set<RuleDTO> rules) { | ||
this.id = id; | ||
this.roleName = roleName; | ||
this.rules = rules; | ||
} | ||
|
||
public UUID getId() { | ||
return id; | ||
} | ||
|
||
public void setId(UUID id) { | ||
this.id = id; | ||
} | ||
|
||
public String getRoleName() { | ||
return roleName; | ||
} | ||
|
||
public void setRoleName(String roleName) { | ||
this.roleName = roleName; | ||
} | ||
|
||
public Set<RuleDTO> getRules() { | ||
return rules; | ||
} | ||
|
||
public void setRules(Set<RuleDTO> rules) { | ||
this.rules = rules; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package earth.angelson.security.dto; | ||
|
||
|
||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
|
||
public class RuleDTO { | ||
|
||
private UUID id; | ||
private String name; | ||
private String operation; | ||
private List<String> resource; | ||
private String filter; | ||
|
||
public RuleDTO() { | ||
} | ||
|
||
public RuleDTO(UUID id, String name, String operation, List<String> resource, String filter) { | ||
this.id = id; | ||
this.name = name; | ||
this.operation = operation; | ||
this.resource = resource; | ||
this.filter = filter; | ||
} | ||
|
||
public UUID getId() { | ||
return id; | ||
} | ||
|
||
public void setId(UUID id) { | ||
this.id = id; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
|
||
public String getOperation() { | ||
return operation; | ||
} | ||
|
||
public void setOperation(String operation) { | ||
this.operation = operation; | ||
} | ||
|
||
public List<String> getResource() { | ||
return resource; | ||
} | ||
|
||
public void setResource(List<String> resource) { | ||
this.resource = resource; | ||
} | ||
|
||
public String getFilter() { | ||
return filter; | ||
} | ||
|
||
public void setFilter(String filter) { | ||
this.filter = filter; | ||
} | ||
} |