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

Issue/18 #19

Open
wants to merge 7 commits into
base: experimental
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions auth/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.gewia.common</groupId>
<artifactId>scope</artifactId>
<version>${project.parent.version}</version>
</dependency>

<dependency>
<groupId>com.auth0</groupId>
Expand Down
14 changes: 14 additions & 0 deletions auth/src/main/java/com/gewia/common/auth/jwt/Jwt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.gewia.common.auth.jwt;

import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.UUID;

@Getter
@AllArgsConstructor
public class Jwt {

private final UUID userId;
private final JwtScopes userScopes;

}
43 changes: 43 additions & 0 deletions auth/src/main/java/com/gewia/common/auth/jwt/JwtScopes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.gewia.common.auth.jwt;

import com.gewia.common.util.Executor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class JwtScopes {

@Getter private List<String> scopes = new ArrayList<>();
private boolean containing = false;

public JwtScopes(List<String> scopes) {
this.scopes = Collections.unmodifiableList(scopes);
}

public JwtScopes includes(String scope, Executor executor) {
if (this.scopes.contains(scope)) {
containing = true;
if (executor != null) executor.action();
} else containing = false;

return this;
}

public void orElse(Executor executor) {
if (!containing && executor != null) executor.action();
containing = false;
}

public boolean getResult() {
return containing;
}

public boolean hasScope(String scope) {
return this.scopes.contains(scope);
}

}
60 changes: 60 additions & 0 deletions auth/src/test/java/com/gewia/common/auth/jwt/JwtScopesTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.gewia.common.auth.jwt;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Assert;
import org.junit.Test;

public class JwtScopesTest {

@Test
public void testScopesUnmodifiable() {
JwtScopes jwtScopes = this.getExampleJwtScopes();

Assert.assertThrows(UnsupportedOperationException.class, () -> jwtScopes.getScopes().add("another.example.scope"));
}

@Test
public void testResultOperation() {
JwtScopes jwtScopes = this.getExampleJwtScopes();

Assert.assertTrue(jwtScopes.includes("microservice.topic.mode.limitation.extra", null).getResult());
Assert.assertFalse(jwtScopes.includes("another.exmaple.scope", null).getResult());
}

@Test
public void testOrElseOperation() {
JwtScopes jwtScopes = this.getExampleJwtScopes();

AtomicInteger i = new AtomicInteger();
jwtScopes.includes("another.example.scope", i::getAndIncrement).orElse(i::getAndDecrement);
Assert.assertEquals(-1, i.get());
}

@Test
public void testIncludeOperation() {
JwtScopes jwtScopes = this.getExampleJwtScopes();

AtomicInteger i = new AtomicInteger();
jwtScopes.includes("microservice.topic.mode.limitation.extra", i::getAndIncrement).orElse(i::getAndDecrement);
Assert.assertEquals(1, i.get());
}

@Test
public void testInitializing() {
List<String> exampleScopes = new ArrayList<>();
exampleScopes.add("microservice.topic.mode.limitation.extra");
JwtScopes jwtScopes = new JwtScopes(exampleScopes);

Assert.assertEquals(exampleScopes, jwtScopes.getScopes());
}

private JwtScopes getExampleJwtScopes() {
List<String> exampleScopes = new ArrayList<>();
exampleScopes.add("microservice.topic.mode.limitation.extra");

return new JwtScopes(exampleScopes);
}

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

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

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

}
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() {
this.addAuthenticationInterceptors(interceptors);
}

abstract public void addAuthenticationInterceptors(List<HandlerInterceptorAdapter> authenticationInterceptors);

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

import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.gewia.common.auth.jwt.Jwt;
import com.gewia.common.auth.jwt.JwtScopes;
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 {
DecodedJWT decodedJWT = (DecodedJWT) ((HttpServletRequest) webRequest.getNativeRequest()).getAttribute("accessToken");

return new Jwt(UUID.fromString(decodedJWT.getClaim("userId").asString()),
new JwtScopes(decodedJWT.getClaim("scopes").asList(String.class)));
}

@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(Jwt.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("/**/*");
}

}
Loading