This repository has been archived by the owner on May 22, 2021. It is now read-only.
-
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.
- Loading branch information
1 parent
c899ff6
commit ed95d43
Showing
9 changed files
with
301 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<parent> | ||
<artifactId>gewia-common</artifactId> | ||
<groupId>com.gewia.common</groupId> | ||
<version>1.0</version> | ||
</parent> | ||
<modelVersion>4.0.0</modelVersion> | ||
<artifactId>spring-auth</artifactId> | ||
|
||
<dependencyManagement> | ||
<dependencies> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-dependencies</artifactId> | ||
<version>2.1.10.RELEASE</version> | ||
<type>pom</type> | ||
<scope>import</scope> | ||
</dependency> | ||
</dependencies> | ||
</dependencyManagement> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.gewia.common</groupId> | ||
<artifactId>auth</artifactId> | ||
<version>${project.parent.version}</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.gewia.common</groupId> | ||
<artifactId>scope</artifactId> | ||
<version>${project.parent.version}</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>com.auth0</groupId> | ||
<artifactId>java-jwt</artifactId> | ||
<version>3.10.3</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>javax.validation</groupId> | ||
<artifactId>validation-api</artifactId> | ||
<version>2.0.1.Final</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
|
||
<!-- Spring --> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-web</artifactId> | ||
<exclusions> | ||
<exclusion> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-logging</artifactId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-test</artifactId> | ||
<scope>test</scope> | ||
<exclusions> | ||
<exclusion> | ||
<groupId>org.junit.vintage</groupId> | ||
<artifactId>junit-vintage-engine</artifactId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
18 changes: 18 additions & 0 deletions
18
spring-auth/src/main/java/com/gewia/common/spring/auth/AuthScope.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,18 @@ | ||
package com.gewia.common.spring.auth; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Repeatable; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.METHOD) | ||
@Repeatable(Authentication.class) | ||
public @interface AuthScope { | ||
|
||
String value() default ""; | ||
|
||
String scope() default ""; | ||
|
||
} |
14 changes: 14 additions & 0 deletions
14
spring-auth/src/main/java/com/gewia/common/spring/auth/Authentication.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,14 @@ | ||
package com.gewia.common.spring.auth; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.METHOD) | ||
public @interface Authentication { | ||
|
||
AuthScope[] value(); | ||
|
||
} |
12 changes: 12 additions & 0 deletions
12
spring-auth/src/main/java/com/gewia/common/spring/auth/IgnoreServiceToken.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,12 @@ | ||
package com.gewia.common.spring.auth; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target({ElementType.METHOD, ElementType.TYPE}) | ||
public @interface IgnoreServiceToken { | ||
|
||
} |
23 changes: 23 additions & 0 deletions
23
spring-auth/src/main/java/com/gewia/common/spring/auth/SpringAuthentication.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,23 @@ | ||
package com.gewia.common.spring.auth; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import lombok.AccessLevel; | ||
import lombok.Getter; | ||
import org.springframework.beans.factory.InitializingBean; | ||
import org.springframework.context.annotation.ComponentScan; | ||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; | ||
|
||
@ComponentScan("com.gewia.common.spring.auth") | ||
public abstract class SpringAuthentication implements InitializingBean { | ||
|
||
@Getter(AccessLevel.PACKAGE) private static List<HandlerInterceptorAdapter> interceptors = new ArrayList<>(); | ||
|
||
@Override | ||
public void afterPropertiesSet() { | ||
interceptors = this.addAuthenticationInterceptors(interceptors); | ||
} | ||
|
||
abstract public List<HandlerInterceptorAdapter> addAuthenticationInterceptors(List<HandlerInterceptorAdapter> authenticationInterceptors); | ||
|
||
} |
42 changes: 42 additions & 0 deletions
42
spring-auth/src/main/java/com/gewia/common/spring/auth/SpringAuthenticationWebConfig.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 com.gewia.common.spring.auth; | ||
|
||
import com.auth0.jwt.interfaces.DecodedJWT; | ||
import java.util.List; | ||
import javax.servlet.http.HttpServletRequest; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.core.MethodParameter; | ||
import org.springframework.web.bind.support.WebDataBinderFactory; | ||
import org.springframework.web.context.request.NativeWebRequest; | ||
import org.springframework.web.method.support.HandlerMethodArgumentResolver; | ||
import org.springframework.web.method.support.ModelAndViewContainer; | ||
import org.springframework.web.servlet.config.annotation.EnableWebMvc; | ||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | ||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; | ||
|
||
@Configuration | ||
@EnableWebMvc | ||
public class SpringAuthenticationWebConfig implements WebMvcConfigurer, HandlerMethodArgumentResolver { | ||
|
||
@Override | ||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { | ||
return ((HttpServletRequest) webRequest.getNativeRequest()).getAttribute("accessToken"); | ||
} | ||
|
||
@Override | ||
public boolean supportsParameter(MethodParameter parameter) { | ||
return parameter.getParameterType().equals(DecodedJWT.class); | ||
} | ||
|
||
@Override | ||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { | ||
resolvers.add(this); | ||
} | ||
|
||
@Override | ||
public void addInterceptors(InterceptorRegistry registry) { | ||
for (HandlerInterceptorAdapter interceptors : SpringAuthentication.getInterceptors()) | ||
registry.addInterceptor(interceptors).addPathPatterns("/**/*"); | ||
} | ||
|
||
} |
78 changes: 78 additions & 0 deletions
78
spring-auth/src/main/java/com/gewia/common/spring/auth/interceptor/ScopeInterceptor.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,78 @@ | ||
package com.gewia.common.spring.auth.interceptor; | ||
|
||
import com.auth0.jwt.interfaces.Claim; | ||
import com.auth0.jwt.interfaces.DecodedJWT; | ||
import com.gewia.common.auth.jwt.JwtUtil; | ||
import com.gewia.common.spring.auth.AuthScope; | ||
import com.gewia.common.spring.auth.Authentication; | ||
import com.gewia.common.util.Pair; | ||
import java.util.List; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import lombok.AllArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.web.method.HandlerMethod; | ||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; | ||
|
||
@AllArgsConstructor | ||
public class ScopeInterceptor extends HandlerInterceptorAdapter { | ||
|
||
private final JwtUtil jwtUtil; | ||
|
||
@Override | ||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { | ||
HandlerMethod method = (HandlerMethod) handler; | ||
|
||
AuthScope[] authScopes; | ||
Authentication auth = method.getMethodAnnotation(Authentication.class); | ||
AuthScope methodAuthScope = method.getMethodAnnotation(AuthScope.class); | ||
if (auth != null) authScopes = auth.value(); | ||
else { | ||
if (methodAuthScope == null) return true; | ||
authScopes = new AuthScope[]{methodAuthScope}; | ||
} | ||
|
||
|
||
String jwt = request.getHeader("Authorization"); | ||
if (jwt == null || jwt.isBlank()) return false; | ||
|
||
Pair<DecodedJWT, JwtUtil.VerificationResult> result = this.jwtUtil.verify(jwt); | ||
switch (result.getRight()) { | ||
case EXPIRED: | ||
response.setStatus(HttpStatus.UNAUTHORIZED.value()); | ||
return false; | ||
case INVALID: | ||
response.setStatus(HttpStatus.NOT_ACCEPTABLE.value()); | ||
return false; | ||
case FAILED: | ||
response.setStatus(HttpStatus.EXPECTATION_FAILED.value()); | ||
return false; | ||
case UNKNOWN: | ||
response.setStatus(HttpStatus.FORBIDDEN.value()); | ||
return false; | ||
default: | ||
response.setStatus(HttpStatus.OK.value()); | ||
} | ||
|
||
Claim claim = result.getLeft().getClaim("scopes"); | ||
List<String> userScopes = claim.asList(String.class); | ||
for (AuthScope authScope : authScopes) { | ||
String scope = authScope.scope(); | ||
if (scope.isBlank()) scope = authScope.value(); | ||
if (!scope.isBlank()) { | ||
boolean isPresent = false; | ||
for (String userScope : userScopes) | ||
if (userScope.equalsIgnoreCase(scope)) { | ||
isPresent = true; | ||
break; | ||
} | ||
if (!isPresent) return false; | ||
} | ||
} | ||
|
||
request.setAttribute("accessToken", result.getLeft()); | ||
|
||
return true; | ||
} | ||
|
||
} |
36 changes: 36 additions & 0 deletions
36
...-auth/src/main/java/com/gewia/common/spring/auth/interceptor/ServiceTokenInterceptor.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,36 @@ | ||
package com.gewia.common.spring.auth.interceptor; | ||
|
||
import com.gewia.common.spring.auth.IgnoreServiceToken; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import lombok.AllArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.web.method.HandlerMethod; | ||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; | ||
|
||
@AllArgsConstructor | ||
public class ServiceTokenInterceptor extends HandlerInterceptorAdapter { | ||
|
||
private final String serviceToken; | ||
|
||
@Override | ||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { | ||
response.setStatus(HttpStatus.FORBIDDEN.value()); | ||
|
||
HandlerMethod method = (HandlerMethod) handler; | ||
if (method.hasMethodAnnotation(IgnoreServiceToken.class) || | ||
method.getMethod().getDeclaringClass().getAnnotation(IgnoreServiceToken.class) != null) { | ||
response.setStatus(HttpStatus.OK.value()); | ||
return true; | ||
} | ||
|
||
String serviceToken = request.getHeader("X-ServiceToken"); | ||
|
||
if (serviceToken == null) return false; | ||
if (!this.serviceToken.equals(serviceToken)) return false; | ||
|
||
response.setStatus(HttpStatus.OK.value()); | ||
return true; | ||
} | ||
|
||
} |