Skip to content
This repository has been archived by the owner on May 22, 2021. It is now read-only.

Commit

Permalink
Added spring-auth module
Browse files Browse the repository at this point in the history
  • Loading branch information
PAException committed May 10, 2020
1 parent c899ff6 commit d75b4a9
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 0 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<module>scope</module>
<module>auth</module>
<module>util</module>
<module>spring-auth</module>
</modules>

<properties>
Expand Down
77 changes: 77 additions & 0 deletions spring-auth/pom.xml
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>
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 {

String scope() default "";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.gewia.common.spring.auth;

import com.gewia.common.spring.auth.interceptor.AuthenticationInterceptor;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import lombok.Getter;

public abstract class SpringAuthentication {

@Getter private static List<AuthenticationInterceptor> authenticationInterceptors = new ArrayList<>();

@PostConstruct
public void registerInterceptor() {
authenticationInterceptors = this.addAuthenticationInterceptors(authenticationInterceptors);
}

abstract public List<AuthenticationInterceptor> addAuthenticationInterceptors(List<AuthenticationInterceptor> authenticationInterceptors);

}
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 com.gewia.common.spring.auth.interceptor.AuthenticationInterceptor;
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;

@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 (AuthenticationInterceptor authenticationInterceptor : SpringAuthentication.getAuthenticationInterceptors())
registry.addInterceptor(authenticationInterceptor).addPathPatterns("/**/*");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.gewia.common.spring.auth.interceptor;

import com.gewia.common.spring.auth.Authentication;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;

public class AuthenticationInterceptor extends HandlerInterceptorAdapter {

public List<Authentication> getAuthenticationAnnotations(Object handler) {
HandlerMethod method = (HandlerMethod) handler;

List<Authentication> authentications = new ArrayList<>();
for (Annotation annotation : method.getMethod().getAnnotations())
if (annotation.annotationType().equals(Authentication.class))
authentications.add((Authentication) annotation);

return authentications;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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.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;

@AllArgsConstructor
public class AuthenticationScopeInterceptor extends AuthenticationInterceptor {

private JwtUtil jwtUtil;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setStatus(HttpStatus.FORBIDDEN.value());

List<Authentication> authentications = this.getAuthenticationAnnotations(handler);

if (authentications.isEmpty()) {
response.setStatus(HttpStatus.OK.value());
return true;
}

String jwt = request.getHeader("Authorization");

Pair<DecodedJWT, JwtUtil.VerificationResult> result = this.jwtUtil.verify(jwt);

if (result.getRight() != JwtUtil.VerificationResult.SUCCESS) return false;

Claim claim = result.getLeft().getClaim("scopes");
List<String> userScopes = claim.asList(String.class);
for (Authentication authentication : authentications) {
if (!authentication.scope().isBlank()) {
boolean isPresent = false;
for (String userScope : userScopes)
if (userScope.equalsIgnoreCase(authentication.scope())) {
isPresent = true;
break;
}
if (!isPresent) return false;
}
}

response.setStatus(HttpStatus.OK.value());
request.setAttribute("accessToken", result.getLeft());

return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.gewia.common.spring.auth.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;

@AllArgsConstructor
public class AuthenticationServiceTokenInterceptor extends AuthenticationInterceptor {

private String serviceToken;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setStatus(HttpStatus.FORBIDDEN.value());

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;
}

}

0 comments on commit d75b4a9

Please sign in to comment.