From 577ea32b0f6b6b8705ca344dffc4907e48a0d01a Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Tue, 21 Jul 2020 21:17:29 +0530 Subject: [PATCH 1/8] [Add] Lombok dependency to avoid boilerplate code --- auto-configure/pom.xml | 6 ++++++ core/pom.xml | 6 ++++++ pom.xml | 9 +++++++++ 3 files changed, 21 insertions(+) diff --git a/auto-configure/pom.xml b/auto-configure/pom.xml index d1cfc5a..96ba54d 100644 --- a/auto-configure/pom.xml +++ b/auto-configure/pom.xml @@ -40,6 +40,12 @@ spring-boot-starter-test test + + + org.projectlombok + lombok + true + \ No newline at end of file diff --git a/core/pom.xml b/core/pom.xml index b5d34c9..552d5e5 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -29,6 +29,12 @@ spring-boot-starter-test test + + + org.projectlombok + lombok + true + \ No newline at end of file diff --git a/pom.xml b/pom.xml index ba4273b..0a1d06b 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ 2.1.6.RELEASE 0.8.4 8.14.1 + 1.16.16 @@ -43,6 +44,14 @@ + + + org.projectlombok + lombok + ${lombok.version} + + + From 208d5f1c7c486c732dcf4d6d87fd684be29cb96f Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Tue, 21 Jul 2020 21:18:59 +0530 Subject: [PATCH 2/8] Move lombok dependency to dependency management tree in root pom --- pom.xml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 0a1d06b..692be7b 100644 --- a/pom.xml +++ b/pom.xml @@ -41,17 +41,15 @@ nimbus-jose-jwt ${nimbus-jose-jwt.version} + + + org.projectlombok + lombok + ${lombok.version} + - - - org.projectlombok - lombok - ${lombok.version} - - - From be90f111d556b934c98c4257685df96b30eb399c Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Tue, 21 Jul 2020 22:28:55 +0530 Subject: [PATCH 3/8] [Add] Junit5 dependencies for automating test cases --- core/pom.xml | 33 +++++++++++++++++++++++++++++++++ pom.xml | 1 + 2 files changed, 34 insertions(+) diff --git a/core/pom.xml b/core/pom.xml index 552d5e5..be441ce 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -35,6 +35,39 @@ lombok true + + + org.junit.jupiter + junit-jupiter + ${junit.jupiter.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.platform + junit-platform-suite-api + test + + + org.junit.platform + junit-platform-runner + test + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 692be7b..3167195 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,7 @@ 0.8.4 8.14.1 1.16.16 + 5.5.1 From f2fe3c5412d9c7920d44488cae391a3d876e88e8 Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Fri, 24 Jul 2020 17:56:42 +0530 Subject: [PATCH 4/8] Add domain, request and response for interaction with oauth2 token server --- auto-configure/pom.xml | 6 ++ core/pom.xml | 6 ++ .../rest/secured/core/domain/GrantType.java | 14 +++ .../core/domain/IssueTokenRequest.java | 49 +++++++++++ .../core/domain/IssueTokenResponse.java | 35 ++++++++ .../rest/secured/core/domain/Token.java | 34 ++++++++ .../core/domain/ValidateTokenRequest.java | 14 +++ .../core/domain/ValidateTokenResponse.java | 85 +++++++++++++++++++ .../core/properties/SecurityProperties.java | 6 +- pom.xml | 8 ++ 10 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/com/codeyapa/rest/secured/core/domain/GrantType.java create mode 100644 core/src/main/java/com/codeyapa/rest/secured/core/domain/IssueTokenRequest.java create mode 100644 core/src/main/java/com/codeyapa/rest/secured/core/domain/IssueTokenResponse.java create mode 100644 core/src/main/java/com/codeyapa/rest/secured/core/domain/Token.java create mode 100644 core/src/main/java/com/codeyapa/rest/secured/core/domain/ValidateTokenRequest.java create mode 100644 core/src/main/java/com/codeyapa/rest/secured/core/domain/ValidateTokenResponse.java diff --git a/auto-configure/pom.xml b/auto-configure/pom.xml index d1cfc5a..780bb7e 100644 --- a/auto-configure/pom.xml +++ b/auto-configure/pom.xml @@ -29,6 +29,12 @@ true + + org.projectlombok + lombok + true + + com.codeyapa core diff --git a/core/pom.xml b/core/pom.xml index b5d34c9..16ba9df 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -24,6 +24,12 @@ provided + + org.projectlombok + lombok + true + + org.springframework.boot spring-boot-starter-test diff --git a/core/src/main/java/com/codeyapa/rest/secured/core/domain/GrantType.java b/core/src/main/java/com/codeyapa/rest/secured/core/domain/GrantType.java new file mode 100644 index 0000000..0720248 --- /dev/null +++ b/core/src/main/java/com/codeyapa/rest/secured/core/domain/GrantType.java @@ -0,0 +1,14 @@ +package com.codeyapa.rest.secured.core.domain; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public enum GrantType { + @JsonProperty("password") + PASSWORD, + + @JsonProperty("refresh_token") + REFRESH_TOKEN, + + @JsonProperty("client_credentials") + CLIENT_CREDENTIALS +} diff --git a/core/src/main/java/com/codeyapa/rest/secured/core/domain/IssueTokenRequest.java b/core/src/main/java/com/codeyapa/rest/secured/core/domain/IssueTokenRequest.java new file mode 100644 index 0000000..1a9fae0 --- /dev/null +++ b/core/src/main/java/com/codeyapa/rest/secured/core/domain/IssueTokenRequest.java @@ -0,0 +1,49 @@ +package com.codeyapa.rest.secured.core.domain; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@AllArgsConstructor +@Getter +@EqualsAndHashCode +public class IssueTokenRequest { + @JsonProperty("client_id") + private String clientId; + + @JsonProperty("grant_type") + private GrantType grantType; + + private String scope; + private String username; + private String password; + private int confidenceLevel; + + @JsonProperty("refresh_token") + private String refreshToken; + + public IssueTokenRequest(String clientId, String username, String password, String scope) { + this.clientId = clientId; + this.grantType = GrantType.PASSWORD; + + this.username = username; + this.password = password; + this.scope = scope; + } + + public IssueTokenRequest(String clientId, String refreshToken) { + this.clientId = clientId; + this.grantType = GrantType.REFRESH_TOKEN; + this.refreshToken = refreshToken; + } + + public IssueTokenRequest(String clientId, String scope, int confidenceLevel) { + this.clientId = clientId; + this.scope = scope; + this.confidenceLevel = confidenceLevel; + this.grantType = GrantType.CLIENT_CREDENTIALS; + } +} diff --git a/core/src/main/java/com/codeyapa/rest/secured/core/domain/IssueTokenResponse.java b/core/src/main/java/com/codeyapa/rest/secured/core/domain/IssueTokenResponse.java new file mode 100644 index 0000000..7c1f03a --- /dev/null +++ b/core/src/main/java/com/codeyapa/rest/secured/core/domain/IssueTokenResponse.java @@ -0,0 +1,35 @@ +package com.codeyapa.rest.secured.core.domain; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +public class IssueTokenResponse { + @JsonProperty("access_token") + String accessToken; + + @JsonProperty("refresh_token") + String refreshToken; + + @JsonProperty("expires_in") + Integer expiresIn; + + @JsonProperty("token_type") + String tokenType; + + @JsonProperty("scope") + String scope; + + @JsonProperty("confidence_level") + Integer confidenceLevel; +} diff --git a/core/src/main/java/com/codeyapa/rest/secured/core/domain/Token.java b/core/src/main/java/com/codeyapa/rest/secured/core/domain/Token.java new file mode 100644 index 0000000..7412739 --- /dev/null +++ b/core/src/main/java/com/codeyapa/rest/secured/core/domain/Token.java @@ -0,0 +1,34 @@ +package com.codeyapa.rest.secured.core.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Value; + +import java.time.Instant; +import java.util.Set; + +@Builder +@Value +@AllArgsConstructor +@EqualsAndHashCode +public class Token { + String tokenId; + String userId; + String clientId; + Instant validFrom; + Instant expiresAt; + Instant issuedAt; + String issuer; + String scope; + Integer confidenceLevel; + Set audience; + + public boolean isFutureToken() { + return !validFrom.isBefore(Instant.now()); + } + + public boolean isExpired() { + return expiresAt.isBefore(Instant.now()); + } +} diff --git a/core/src/main/java/com/codeyapa/rest/secured/core/domain/ValidateTokenRequest.java b/core/src/main/java/com/codeyapa/rest/secured/core/domain/ValidateTokenRequest.java new file mode 100644 index 0000000..d0862a2 --- /dev/null +++ b/core/src/main/java/com/codeyapa/rest/secured/core/domain/ValidateTokenRequest.java @@ -0,0 +1,14 @@ +package com.codeyapa.rest.secured.core.domain; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@Getter +@AllArgsConstructor +public class ValidateTokenRequest { + @JsonProperty("access_token") + private String accessToken; +} diff --git a/core/src/main/java/com/codeyapa/rest/secured/core/domain/ValidateTokenResponse.java b/core/src/main/java/com/codeyapa/rest/secured/core/domain/ValidateTokenResponse.java new file mode 100644 index 0000000..bb8a28e --- /dev/null +++ b/core/src/main/java/com/codeyapa/rest/secured/core/domain/ValidateTokenResponse.java @@ -0,0 +1,85 @@ +package com.codeyapa.rest.secured.core.domain; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Optional; + +import static java.time.Instant.ofEpochSecond; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@Slf4j +public class ValidateTokenResponse { + @JsonProperty("active") + private boolean active; + + @JsonProperty("jti") + private String tokenId; + + @JsonProperty("iss") + private String issuer; + + @JsonProperty("sub") + private String subject; + + @JsonProperty("aud") + private Collection audience; + + @JsonProperty("iat") + private Long issuedAt; + + @JsonProperty("nbf") + private Long notBefore; + + @JsonProperty("exp") + private Long expirationTime; + + @JsonProperty("scope") + private String scope; + + @JsonProperty("confidence_level") + private Integer confidenceLevel; + + @JsonProperty("client_id") + private String clientId; + + @JsonProperty("token_type") + private String tokenType; + + public Optional toToken() { + if (!active || subject == null) { + return Optional.empty(); + } + try { + return Optional.of( + Token.builder() + .userId(subject) + .clientId(clientId) + .issuedAt(ofEpochSecond(issuedAt)) + .expiresAt(ofEpochSecond(expirationTime)) + .validFrom(ofEpochSecond(notBefore)) + .confidenceLevel(confidenceLevel) + .audience(audience == null ? Collections.emptySet() : new HashSet<>(audience)) + .scope(scope) + .tokenId(tokenId) + .build()); + } catch (IllegalArgumentException | NullPointerException e) { + log.error("The token could not be parsed as a valid JWT.", e); + return Optional.empty(); + } + } +} diff --git a/core/src/main/java/com/codeyapa/rest/secured/core/properties/SecurityProperties.java b/core/src/main/java/com/codeyapa/rest/secured/core/properties/SecurityProperties.java index bed9e45..ff1a6b1 100644 --- a/core/src/main/java/com/codeyapa/rest/secured/core/properties/SecurityProperties.java +++ b/core/src/main/java/com/codeyapa/rest/secured/core/properties/SecurityProperties.java @@ -1,8 +1,12 @@ package com.codeyapa.rest.secured.core.properties; +import lombok.Getter; +import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; -@ConfigurationProperties(prefix = "rest.security") +@ConfigurationProperties(prefix = "ofs.security") +@Getter +@Setter public class SecurityProperties { private boolean enabled = true; } diff --git a/pom.xml b/pom.xml index ba4273b..1037637 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ 2.1.6.RELEASE 0.8.4 8.14.1 + 1.16.16 @@ -40,7 +41,14 @@ nimbus-jose-jwt ${nimbus-jose-jwt.version} + + + org.projectlombok + lombok + ${lombok.version} + + From 313c515fc448768440a0921c14726dbbef5659cc Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Fri, 24 Jul 2020 18:00:28 +0530 Subject: [PATCH 5/8] Add sonar exclusions for domain classed --- core/pom.xml | 10 ++++++++++ pom.xml | 3 +++ 2 files changed, 13 insertions(+) diff --git a/core/pom.xml b/core/pom.xml index 16ba9df..9566aea 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -11,6 +11,16 @@ core + + ${project.build.directory}/jacoco.exec + + src/main/java/com/codeyapa/rest/secured/core/domain/* + + + src/main/java/com/codeyapa/rest/secured/core/domain/* + + + org.springframework.boot diff --git a/pom.xml b/pom.xml index 1037637..1b0902d 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,9 @@ 0.8.4 8.14.1 1.16.16 + jacoco + reuseReports + ${project.build.directory}/jacoco.exec From a2a2eb144009c13ea8d5243d6e1309b6a046bbd3 Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Fri, 24 Jul 2020 18:04:01 +0530 Subject: [PATCH 6/8] [Add] Tests for autoconfiguration class --- .../SecurityAutoConfigurationTest.java | 21 +++++++++++++++++-- .../secured/core/service/SecurityService.java | 4 ++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/com/codeyapa/rest/secured/core/service/SecurityService.java diff --git a/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java b/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java index ab3a2a2..acc1c2c 100644 --- a/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java +++ b/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java @@ -3,6 +3,7 @@ import org.junit.Test; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; +import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.boot.autoconfigure.AutoConfigurations.of; public class SecurityAutoConfigurationTest { @@ -15,12 +16,28 @@ public void shouldCreateAutoConfiguredBeanIfStarterIsEnabled() { .withPropertyValues(properties(true)) .withConfiguration(of(SecurityAutoConfiguration.class)); - this.applicationContextRunner.run(context -> {}); + this.applicationContextRunner.run( + context -> { + assertThat(context).hasBean("securityService"); + }); + } + + @Test + public void shouldNotCreateAutoConfiguredBeanIfStarterIsNotEnabled() { + applicationContextRunner = + new WebApplicationContextRunner() + .withPropertyValues(properties(false)) + .withConfiguration(of(SecurityAutoConfiguration.class)); + + this.applicationContextRunner.run( + context -> { + assertThat(context).doesNotHaveBean("securityService"); + }); } private String[] properties(boolean enabled) { return new String[] { - String.format("rest.security.enabled=%b", enabled), + String.format("rest.secured.enabled=%b", enabled), }; } } diff --git a/core/src/main/java/com/codeyapa/rest/secured/core/service/SecurityService.java b/core/src/main/java/com/codeyapa/rest/secured/core/service/SecurityService.java new file mode 100644 index 0000000..fc91aa8 --- /dev/null +++ b/core/src/main/java/com/codeyapa/rest/secured/core/service/SecurityService.java @@ -0,0 +1,4 @@ +package com.codeyapa.rest.secured.core.service; + +public class SecurityService { +} From 252fb7926c3d9ed8803d262fecf9c2eb5c9c86ab Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Fri, 24 Jul 2020 18:06:48 +0530 Subject: [PATCH 7/8] Syntax correcction --- .../autoconfiguration/SecurityAutoConfigurationTest.java | 2 +- .../rest/secured/core/properties/SecurityProperties.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java b/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java index acc1c2c..ba46727 100644 --- a/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java +++ b/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java @@ -37,7 +37,7 @@ public void shouldNotCreateAutoConfiguredBeanIfStarterIsNotEnabled() { private String[] properties(boolean enabled) { return new String[] { - String.format("rest.secured.enabled=%b", enabled), + String.format("rest.security.enabled=%b", enabled), }; } } diff --git a/core/src/main/java/com/codeyapa/rest/secured/core/properties/SecurityProperties.java b/core/src/main/java/com/codeyapa/rest/secured/core/properties/SecurityProperties.java index ff1a6b1..e73ab0e 100644 --- a/core/src/main/java/com/codeyapa/rest/secured/core/properties/SecurityProperties.java +++ b/core/src/main/java/com/codeyapa/rest/secured/core/properties/SecurityProperties.java @@ -4,7 +4,7 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; -@ConfigurationProperties(prefix = "ofs.security") +@ConfigurationProperties(prefix = "rest.security") @Getter @Setter public class SecurityProperties { From 0601bc298c5f07e419b05e5a4bbfe057dba977b9 Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Fri, 24 Jul 2020 18:09:04 +0530 Subject: [PATCH 8/8] Syntax correcction --- .../autoconfiguration/SecurityAutoConfigurationTest.java | 2 -- .../codeyapa/rest/secured/core/service/SecurityService.java | 4 ---- 2 files changed, 6 deletions(-) delete mode 100644 core/src/main/java/com/codeyapa/rest/secured/core/service/SecurityService.java diff --git a/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java b/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java index ba46727..eaac56a 100644 --- a/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java +++ b/auto-configure/src/test/java/com/codeyapa/rest/secured/autoconfiguration/SecurityAutoConfigurationTest.java @@ -18,7 +18,6 @@ public void shouldCreateAutoConfiguredBeanIfStarterIsEnabled() { this.applicationContextRunner.run( context -> { - assertThat(context).hasBean("securityService"); }); } @@ -31,7 +30,6 @@ public void shouldNotCreateAutoConfiguredBeanIfStarterIsNotEnabled() { this.applicationContextRunner.run( context -> { - assertThat(context).doesNotHaveBean("securityService"); }); } diff --git a/core/src/main/java/com/codeyapa/rest/secured/core/service/SecurityService.java b/core/src/main/java/com/codeyapa/rest/secured/core/service/SecurityService.java deleted file mode 100644 index fc91aa8..0000000 --- a/core/src/main/java/com/codeyapa/rest/secured/core/service/SecurityService.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.codeyapa.rest.secured.core.service; - -public class SecurityService { -}