From 9491d3215bac9c755b69bb1084575df46987eaea Mon Sep 17 00:00:00 2001 From: Sam Glendenning Date: Mon, 22 Nov 2021 15:27:58 +0000 Subject: [PATCH] Merging changes for updating Spring boot and Java version. Squashed commit of the following: commit dccc0b6f8476492289479c2b0eb31b7f22288771 Merge: 0c674fb cc3b4d5 Author: Sam Glendenning Date: Mon Nov 22 14:55:04 2021 +0000 Merge branch 'iam-spring-update-oct-2021' of git://github.com/indigo-iam/iam into iam-spring-update-oct-2021 commit cc3b4d51af3cc1e5db71d8009642eb08eda11a82 Author: Andrea Ceccanti Date: Mon Nov 15 08:33:55 2021 +0100 More fixes for SonarCloud warnings commit 5ff5e3be7018f8d5b43265c7503d6a6080700e67 Author: Andrea Ceccanti Date: Sun Nov 14 16:38:07 2021 +0100 Fixes for Sonar warnings/errors and other minor improvements commit 91d05339bd2b4239981506ddd35aa5fc5592d0cd Author: Andrea Ceccanti Date: Sat Nov 13 16:02:51 2021 +0100 Tests green (locally) commit d575a479448fca88ee3d6e9a8cbf4c6a812ac2bc Author: Andrea Ceccanti Date: Sat Nov 13 08:59:09 2021 +0100 More warning and test fixes commit 0b629633411e0b034e360726a8d68968ce864593 Author: Andrea Ceccanti Date: Fri Nov 12 18:38:35 2021 +0100 More test fixes commit 922b46452882cebca3984df8303cab136afe7b64 Author: Andrea Ceccanti Date: Tue Nov 9 11:00:34 2021 +0100 Test errors -> 0, Test failures -> ~12% commit f7f851348bdebb905eae653f72fd754357e1b88e Author: Andrea Ceccanti Date: Sat Nov 6 09:50:08 2021 +0100 Silence deprecation warnings Only if coming from the latest spring-security-oauth2 (for which we do not and won't have a replacement for some time). commit 8f27bd2b28763d2a0557aa86f84a9939e7f959dc Author: Andrea Ceccanti Date: Sat Nov 6 08:44:07 2021 +0100 Use H2 datasource for the tests This prevents issues with the hikari connection pool being closed. commit 45c7b4e627c13d08b350b022eaa25a9045ecc9b0 Author: Andrea Ceccanti Date: Fri Nov 5 19:44:15 2021 +0100 Service starts up! commit 4f984ee000e54e006cd88c7f411c1e5cb5e5e54f Author: Andrea Ceccanti Date: Fri Nov 5 19:27:01 2021 +0100 Use a keystore with key size 2048 commit 3efc9f9f46f6921fdef85b271cb9386b90ab8248 Author: Andrea Ceccanti Date: Fri Nov 5 18:37:34 2021 +0100 Flyway migration refactoring to avoid naming errors commit 3f5e74182d94c765b1451f32f429f876e3228f40 Author: Andrea Ceccanti Date: Fri Nov 5 18:22:42 2021 +0100 Moved source/target compatibility to Java 11 commit 7e1f1d6f7077663a70a3ea9e4ed630571b89c23c Author: Andrea Ceccanti Date: Fri Nov 5 18:14:18 2021 +0100 License updates commit b63ce93be8f5770ec7fb69232a6208b9dff5ec6c Author: Andrea Ceccanti Date: Fri Nov 5 18:13:32 2021 +0100 Config files changes commit 66d28d271365bb7f9bf0b973018296b80b971141 Author: Andrea Ceccanti Date: Fri Nov 5 17:59:07 2021 +0100 Builds against spring boot 2.5.6 commit 0d9167ab4a3b07b5c495eb8396342e36c1e3e3eb Author: Andrea Ceccanti Date: Fri Nov 5 10:26:35 2021 +0100 Fixed flyway migrations compilation problems commit 1ca9d730a94bf29a52730b75f38a8844aead0d6d Author: Andrea Ceccanti Date: Fri Nov 5 10:09:10 2021 +0100 wip commit acd7e4f814f2abfb3446ac2be7d4d85c5033eafe Author: Andrea Ceccanti Date: Fri Nov 5 08:07:33 2021 +0100 WIP: maven clean succeeds commit 2b9835edec7a221fc789efcfce13b56c5bed3cb5 Author: Andrea Ceccanti Date: Thu Nov 4 18:18:33 2021 +0100 wip commit 8dbf1cf034676afe1a547b70acdac1dec3c5857d Author: Andrea Ceccanti Date: Wed Nov 3 19:35:18 2021 +0100 Fixed code smells reported by Sonar commit 56b570ed719ec52c166d7a22113c6a548cfa278f Author: Andrea Ceccanti Date: Wed Nov 3 19:16:59 2021 +0100 Just build on Java 11 Still not there for Java 17... commit 15290496bf97125e78d50f7820d8b05c7eaee317 Author: Andrea Ceccanti Date: Wed Nov 3 18:41:18 2021 +0100 Restore sonar analysis commit ed5220796f89c014cf3b3a4c5d5552d0644492c6 Author: Andrea Ceccanti Date: Wed Nov 3 18:40:23 2021 +0100 Use openjdk:11 docker images commit cc382c21f93da9204630cd69f48baf1d689159bf Author: Andrea Ceccanti Date: Wed Nov 3 18:26:14 2021 +0100 Drop java 8 commit 9dc729ca3239e4cd7e568ca0edced9aa4265f8bc Author: Andrea Ceccanti Date: Wed Nov 3 17:59:29 2021 +0100 Build on Jenkins with Java 11 commit 7c090dd05da59c7b3a5b9f822f7c775efcae47ce Author: Andrea Ceccanti Date: Wed Nov 3 17:52:18 2021 +0100 First attempt at java version matrix build commit d77d86058fe48be7cd67c53355a8c21423a22a5b Author: Andrea Ceccanti Date: Wed Nov 3 17:43:21 2021 +0100 Dropped validator-collections dependency commit 47cf69b385df4f278d4f050b4f6cc8a0fc23bdfa Author: Andrea Ceccanti Date: Mon Nov 1 16:46:22 2021 +0100 Fix test fixture initialization commit 59406e0d0101c79ce4a5163a0c3fefdd10b9415b Author: Andrea Ceccanti Date: Mon Nov 1 16:45:23 2021 +0100 Drop DevToolsDataSourceAutoConfiguration Which breaks h2 tests. commit 6c18f352f74acbd0b91a7660406dda3d9ca19337 Author: Andrea Ceccanti Date: Mon Nov 1 16:44:52 2021 +0100 Add flyway debug log handle commit 2f433adfd63f635fb2762e01ca0c84211d2f66af Author: Andrea Ceccanti Date: Mon Nov 1 16:44:28 2021 +0100 Streamlined h2 db test configuration commit c9eaa1687ddc2db0fc1877ba10ce9796a6997e18 Author: Andrea Ceccanti Date: Mon Nov 1 16:41:39 2021 +0100 Upgrade surefire plugin to the latest version commit 3ae9b7fccc904be5f3a405f84ac1c568b80c8b18 Author: Andrea Ceccanti Date: Fri Oct 29 08:18:12 2021 +0200 Archive JUnit reports commit 96269821519dda2a46a02f2c8733bb6c4957292d Author: Andrea Ceccanti Date: Fri Oct 29 07:45:04 2021 +0200 Removed ununsed dependency commit de574c8f60b6767fac2b312b4d83688bf1107556 Author: Andrea Ceccanti Date: Fri Oct 29 07:44:30 2021 +0200 More test fixes commit b3620ac6fb84403ec9137745821a718c8ce1b540 Author: Andrea Ceccanti Date: Fri Oct 29 07:43:58 2021 +0200 Control how many test contexts are cached during builds commit a853f9425f61d886176b436f69d9246630d9fcaf Author: Andrea Ceccanti Date: Thu Oct 28 12:32:08 2021 +0200 More test fixes commit 481a45697675ced9a14992e8c2819bc67f418e23 Author: Andrea Ceccanti Date: Thu Oct 28 11:13:39 2021 +0200 More test fixes commit 003a4864b2e3fe66172ce4d619175b84164979bd Author: Andrea Ceccanti Date: Thu Oct 28 08:49:19 2021 +0200 More test fixes commit 0417ad15b54c3a2d70e2f66da8eab799762cbef7 Author: Andrea Ceccanti Date: Wed Oct 27 19:25:19 2021 +0200 More test porting commit ed3032209b6684f0048b35538825ef60d9651719 Author: Andrea Ceccanti Date: Wed Oct 27 18:29:58 2021 +0200 Fixed Velocity initialization And moved email templates from the /templates folder to the /email-templates folder in the classpath. commit b35bf83575c3aa0203ac146dd3406ac3bc07e01a Author: Andrea Ceccanti Date: Wed Oct 27 08:52:18 2021 +0200 More test fixing work commit c2b205b81acc68f8d80e9b51eec6cbad90512363 Author: Andrea Ceccanti Date: Tue Oct 26 17:48:16 2021 +0200 More test fixes commit b310d4c3cbcb4cc8de5e10c60ba210979659f0ae Author: Andrea Ceccanti Date: Tue Oct 26 17:23:47 2021 +0200 All api tests green commit 4a7098254dd2bf6eee7b57c260caa51485e9c28a Author: Andrea Ceccanti Date: Tue Oct 26 12:17:49 2021 +0200 Cors configuration & actuator test fixes commit 4ed75ff33dde919194dd28a4252586ecb847dc7c Author: Andrea Ceccanti Date: Tue Oct 26 00:38:23 2021 +0200 Remove cors filter configuration commit a9487412794c9c1346eee9aff3a336e1bcd96667 Author: Andrea Ceccanti Date: Mon Oct 25 19:37:51 2021 +0200 Added license commit e025b7d0509a8a4b520053226f9278fc36219c0a Author: Andrea Ceccanti Date: Mon Oct 25 19:37:25 2021 +0200 Started migration of integration tests commit ee7fc54c3d2ae67b3c8d1f7cd5f33d192b0769c3 Author: Andrea Ceccanti Date: Mon Oct 25 19:36:54 2021 +0200 New unified test annotation commit 149d9d12c7e7278e3d55b59e9054b1dc308fc44b Author: Andrea Ceccanti Date: Mon Oct 25 19:14:54 2021 +0200 Project compiles commit 84ed532014bc57f0d68430d5ec332ce290f58a9a Author: Andrea Ceccanti Date: Mon Oct 25 19:12:59 2021 +0200 Run update-tests script commit ce93f59a9718ed8f59b44a372aba14aeaaf893c0 Author: Andrea Ceccanti Date: Mon Oct 25 19:07:21 2021 +0200 Fix compilation problems on main code Fix renamed classes and changed JPAConfig commit 93b80c6c6d0b8d3bc2229302d6a41fd4fac3ca42 Author: Andrea Ceccanti Date: Mon Oct 25 19:06:47 2021 +0200 First migrate to spring boot 1.5.22 commit de5f1b1d65775bd8c87c5c287e0548d8151679fe Author: Andrea Ceccanti Date: Mon Oct 25 18:30:00 2021 +0200 Updated Spring and mitreid deps commit e9e54086b75fd9d532c3982f44a0b0a38184fee6 Merge: 8c9b8bc 4bfc271 Author: Andrea Ceccanti Date: Sun Oct 24 17:47:19 2021 +0200 Merge pull request #433 from indigo-iam/issue-432-include-groups-in-userinfo-response-wlcg Include wlcg.groups in userinfo response commit 8c9b8bc4e158eb64e60542b52d3b5165cab56e8d Merge: ec31232 8ffed21 Author: Andrea Ceccanti Date: Sun Oct 24 17:47:05 2021 +0200 Merge pull request #431 from indigo-iam/issue-430-improved-jwk-configuration Improved support for JWK configuration commit ec31232b711b3e757e7429c75a1a68aa87b8bc0e Merge: 767e86e 88bb278 Author: Andrea Ceccanti Date: Sun Oct 24 17:46:45 2021 +0200 Merge pull request #427 from indigo-iam/issue-426-jwt-based-client-auth First attempt at JWT-based client-auth commit 4bfc2719c32f2063027ad232042098b081e64f8c Author: Andrea Ceccanti Date: Sun Oct 24 17:23:36 2021 +0200 Include wlcg.groups information in userinfo response Even though the IAM access token is a JWT and even though groups are included in the access token when requested, as mandated by the WLCG JWT profile, there are still apps treating the access token as an opaque string. To support those apps, and be more consistent with the traditional IAM profile behaviour, IAM should include group information in the userinfo endpoint response also for the WLCG profile. Issue: #432 commit 195c2d76ace2b6bdeb540812e3c38ea470b9df74 Merge: 7f90144 5b8d9d8 Author: Andrea Ceccanti Date: Thu Sep 23 15:23:34 2021 +0200 Merge pull request #425 from indigo-iam/issue-424-IAM-does-not-encode-group-names-correctly-aarc-g002 Fix for issue-422: iam does not encode group names correctly according to AARC G002 commit 8ffed21bbffaa19113f34eb14c0f4b17d43fa5f1 Author: Andrea Ceccanti Date: Sun Oct 24 09:25:36 2021 +0200 Improved support for JWT configuration It's now possible to specify the default key id and algorithm used for signing tokens. Issue: #430 commit 88bb2784d9580655eaa936df4255f069bfa81a96 Author: Andrea Ceccanti Date: Sat Oct 23 09:56:08 2021 +0200 More integration tests commit cd8ef617a61adc4c2f654869949f8d6791b9bebe Author: Andrea Ceccanti Date: Sat Oct 23 08:39:43 2021 +0200 More tests for JWTAuthenticationProvider commit fc7148d42358ffbbf080d4e8675d22dacf5e4e05 Author: Andrea Ceccanti Date: Sun Oct 17 23:03:37 2021 +0200 First attempt at JWT-based client-auth commit 767e86e0eed8cd386a678cbab84b8221be56fc48 Merge: 7f90144 5b8d9d8 Author: Andrea Ceccanti Date: Thu Sep 23 15:23:34 2021 +0200 Merge pull request #425 from indigo-iam/issue-424-IAM-does-not-encode-group-names-correctly-aarc-g002 Fix for issue-422: iam does not encode group names correctly according to AARC G002 commit 5b8d9d8d27c7b006eb2e4989cc918345043233c9 Author: Andrea Ceccanti Date: Thu Sep 23 14:50:32 2021 +0200 Fix wrong AARC G002 group name encoding commit 7f901442a97ceca8d98aac5bfe573c09b219a484 Author: Andrea Ceccanti Date: Tue Sep 14 07:56:12 2021 +0200 Version bumped back to 1.8.0-SNAPSHOT commit 1828bf04df08587981053c70567f44c0b0aa0729 Author: Andrea Ceccanti Date: Tue Sep 14 07:55:41 2021 +0200 Test custom logging conf --- .github/workflows/sonar.yaml | 1 + Jenkinsfile | 2 +- docker-compose.yml | 5 + iam-common/pom.xml | 4 - iam-login-service/docker/Dockerfile.prod | 1 + iam-login-service/pom.xml | 70 ++- .../mw/iam/api/scim/model/ScimAttribute.java | 74 ---- .../it/infn/mw/iam/config/IamProperties.java | 5 + .../config/security/MitreSecurityConfig.java | 1 - .../profile/aarc/AarcClaimValueHelper.java | 3 - .../profile/common/BaseIdTokenCustomizer.java | 1 + .../wlcg/WLCGProfileAccessTokenBuilder.java | 5 + .../mw/iam/core/web/IamDiscoveryEndpoint.java | 401 ++++++++++++++++++ .../web/jwk/IamJWKSetPublishingEndpoint.java | 1 + .../src/main/resources/application-h2.yml | 2 +- .../src/main/resources/application-prod.yml | 2 +- .../src/main/resources/application.properties | 1 - .../src/main/resources/application.yml | 1 + .../AupSignatureCheckIntegrationTests.java | 4 + .../GroupRequestsGetDetailsTests.java | 2 +- .../X509AuthenticationIntegrationTests.java | 1 - ...LifecycleNoSuspensionGracePeriodTests.java | 3 +- .../test/lifecycle/AccountLifecycleTests.java | 1 - .../AuthorizationCodeIntegrationTests.java | 197 +++++++++ .../oauth/ClientRegistrationAuthzTests.java | 69 +++ .../test/oauth/DiscoveryEndpointTests.java | 98 +++++ .../oauth/devicecode/DeviceCodeTests.java | 1 - .../iam/test/oauth/jwk/JWKEndpointTests.java | 1 + .../profile/AarcClaimValueHelperTests.java | 1 - .../RegistrationUsernameTests.java | 37 ++ .../repository/IamTokenRepositoryTests.java | 1 + .../mw/iam/test/scim/ScimRestUtilsMvc.java | 2 + .../user/ScimUserServiceTests.java | 8 +- .../me/patch/ScimMeEndpointPatchAddTests.java | 2 + .../test/scim/user/ScimUserCreationTests.java | 6 + .../scim/user/ScimUserProvisioningTests.java | 1 - .../annotation/IamMockMvcIntegrationTest.java | 1 + iam-persistence/pom.xml | 5 + .../CreateGroupManagerAuthorities.java | 43 -- .../repository/IamTotpMfaRepositoryImpl.java | 1 - .../db/migration/test/V100000___test_data.sql | 9 + iam-test-protected-resource/pom.xml | 100 ----- 42 files changed, 928 insertions(+), 246 deletions(-) delete mode 100644 iam-login-service/src/main/java/it/infn/mw/iam/api/scim/model/ScimAttribute.java create mode 100644 iam-login-service/src/main/java/it/infn/mw/iam/core/web/IamDiscoveryEndpoint.java create mode 100644 iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/AuthorizationCodeIntegrationTests.java create mode 100644 iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/ClientRegistrationAuthzTests.java create mode 100644 iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/DiscoveryEndpointTests.java delete mode 100644 iam-persistence/src/main/java/it/infn/mw/iam/persistence/migrations/CreateGroupManagerAuthorities.java delete mode 100644 iam-test-protected-resource/pom.xml diff --git a/.github/workflows/sonar.yaml b/.github/workflows/sonar.yaml index a8136225f..db2809c28 100644 --- a/.github/workflows/sonar.yaml +++ b/.github/workflows/sonar.yaml @@ -4,6 +4,7 @@ on: push: branches: - develop + pull_request: types: [opened, edited, reopened, synchronize] diff --git a/Jenkinsfile b/Jenkinsfile index 185e85069..2ad6da820 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -90,7 +90,7 @@ pipeline { post { always { script { - maybeArchiveJUnitReports() + maybeArchiveJUnitReportsWithJacoco() } } } diff --git a/docker-compose.yml b/docker-compose.yml index c1dd09cf8..c4062c012 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -85,7 +85,12 @@ services: - logs:/var/log/iam - .:/code:ro - /dev/urandom:/dev/random +<<<<<<< HEAD # - ./compose/custom-logging/logback-spring.xml:/indigo-iam/logback-spring.xml:ro +======= + - ./compose/custom-logging/logback-spring.xml:/indigo-iam/logback-spring.xml:ro + +>>>>>>> af13c9c9 (Merging changes for updating Spring boot and Java version. Squashed commit of the following:) # - ./compose/metadata/iam.local.io.metadata.xml:/indigo-iam/iam.local.io.metadata.xml:ro # - ./compose/metadata/spid-idp.example.metadata.xml:/indigo-iam/spid-idp.example.metadata.xml:ro # - ./compose/custom-saml/application-saml.yml:/indigo-iam/config/application-saml.yml:ro diff --git a/iam-common/pom.xml b/iam-common/pom.xml index 86dd3beca..673dbffb8 100644 --- a/iam-common/pom.xml +++ b/iam-common/pom.xml @@ -5,11 +5,7 @@ it.infn.mw.iam-parent iam-parent -<<<<<<< HEAD 1.11.0 -======= - 1.7.1 ->>>>>>> a2dcabba (Bumped version to v1.7.1) it.infn.mw.iam-common diff --git a/iam-login-service/docker/Dockerfile.prod b/iam-login-service/docker/Dockerfile.prod index baa7a1293..91d592071 100644 --- a/iam-login-service/docker/Dockerfile.prod +++ b/iam-login-service/docker/Dockerfile.prod @@ -1,4 +1,5 @@ FROM eclipse-temurin:17 as builder + RUN mkdir /indigo-iam WORKDIR /indigo-iam COPY iam-login-service.war /indigo-iam/ diff --git a/iam-login-service/pom.xml b/iam-login-service/pom.xml index 31cd91555..7fc45484e 100644 --- a/iam-login-service/pom.xml +++ b/iam-login-service/pom.xml @@ -92,7 +92,6 @@ org.springframework.boot spring-boot-starter-data-redis - @@ -270,8 +269,13 @@ +<<<<<<< HEAD com.mysql mysql-connector-j +======= + mysql + mysql-connector-java +>>>>>>> af13c9c9 (Merging changes for updating Spring boot and Java version. Squashed commit of the following:) runtime @@ -422,6 +426,70 @@ src/main/webapp +<<<<<<< HEAD +======= + + + org.apache.maven.plugins + maven-surefire-plugin + + + + + ${argLine} ${jvm.test.args} + alphabetical + false + + + + org.jacoco + jacoco-maven-plugin + + + it/infn/mw/iam/api/registration/cern/mock/*.class + it/infn/mw/iam/api/registration/cern/dto/*.class + + + + + agent + + prepare-agent + + + + Project Base Path (WEB):: ${project.basedir} + Jacoco exec target path (WEB):: + ${sonar.jacoco.reportPath} + + + + + + report-aggregate + + report-aggregate + + + + + + org.springframework.boot + spring-boot-maven-plugin + + it.infn.mw.iam.IamLoginService + + + + + build-info + + + + + + +>>>>>>> af13c9c9 (Merging changes for updating Spring boot and Java version. Squashed commit of the following:) diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/scim/model/ScimAttribute.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/scim/model/ScimAttribute.java deleted file mode 100644 index cdb64ebed..000000000 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/scim/model/ScimAttribute.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package it.infn.mw.iam.api.scim.model; - -import javax.validation.constraints.NotBlank; - -import org.hibernate.validator.constraints.Length; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class ScimAttribute { - - @NotBlank - @Length(max = 64) - private final String name; - - @Length(max = 256) - private final String value; - - @JsonCreator - private ScimAttribute(@JsonProperty("name") String name, @JsonProperty("value") String value) { - this.name = name; - this.value = value; - } - - public String getName() { - return name; - } - - public String getValue() { - return value; - } - - private ScimAttribute(Builder builder) { - this(builder.name, builder.value); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private String name; - private String value; - - public Builder withName(String name) { - this.name = name; - return this; - } - - public Builder withVaule(String value) { - this.value = value; - return this; - } - - public ScimAttribute build() { - return new ScimAttribute(this); - } - } -} diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/config/IamProperties.java b/iam-login-service/src/main/java/it/infn/mw/iam/config/IamProperties.java index c6dd8f671..c078dab82 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/config/IamProperties.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/config/IamProperties.java @@ -646,6 +646,11 @@ public void setEnrollment(String enrollment) { private ClientProperties client = new ClientProperties(); + private ExternalConnectivityProbeProperties externalConnectivityProbe = + new ExternalConnectivityProbeProperties(); + + private AccountLinkingProperties accountLinking = new AccountLinkingProperties(); + public String getBaseUrl() { return baseUrl; } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/config/security/MitreSecurityConfig.java b/iam-login-service/src/main/java/it/infn/mw/iam/config/security/MitreSecurityConfig.java index 62abcacbe..d84606927 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/config/security/MitreSecurityConfig.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/config/security/MitreSecurityConfig.java @@ -119,7 +119,6 @@ public static class RegisterEndpointAuthorizationConfig extends WebSecurityConfi @Autowired private OAuth2AuthenticationEntryPoint authenticationEntryPoint; - @Override public void configure(final HttpSecurity http) throws Exception { diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/aarc/AarcClaimValueHelper.java b/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/aarc/AarcClaimValueHelper.java index 187589f77..314816fa9 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/aarc/AarcClaimValueHelper.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/aarc/AarcClaimValueHelper.java @@ -21,9 +21,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import com.google.common.base.Strings; -import com.google.common.collect.Sets; - import it.infn.mw.iam.persistence.model.IamGroup; import it.infn.mw.iam.persistence.model.IamUserInfo; diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/common/BaseIdTokenCustomizer.java b/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/common/BaseIdTokenCustomizer.java index 3544079e0..734fb2e85 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/common/BaseIdTokenCustomizer.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/common/BaseIdTokenCustomizer.java @@ -29,6 +29,7 @@ import it.infn.mw.iam.persistence.model.IamLabel; import it.infn.mw.iam.persistence.repository.IamAccountRepository; +@SuppressWarnings("deprecation") public abstract class BaseIdTokenCustomizer implements IDTokenCustomizer { private final IamAccountRepository accountRepo; diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/wlcg/WLCGProfileAccessTokenBuilder.java b/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/wlcg/WLCGProfileAccessTokenBuilder.java index f1a064ea7..4509a44d4 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/wlcg/WLCGProfileAccessTokenBuilder.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/core/oauth/profile/wlcg/WLCGProfileAccessTokenBuilder.java @@ -75,6 +75,11 @@ public JWTClaimsSet buildAccessToken(OAuth2AccessTokenEntity token, if (properties.getAccessToken().isIncludeAuthnInfo()) { addAuthnInfoClaims(builder, token.getScope(), userInfo); } + + if (token.getScope().contains(ATTR_SCOPE)) { + builder.claim(ATTR_SCOPE, attributeHelper + .getAttributeMapFromUserInfo(((UserInfoAdapter) userInfo).getUserinfo())); + } } addAudience(builder, authentication); diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/core/web/IamDiscoveryEndpoint.java b/iam-login-service/src/main/java/it/infn/mw/iam/core/web/IamDiscoveryEndpoint.java new file mode 100644 index 000000000..5e766f856 --- /dev/null +++ b/iam-login-service/src/main/java/it/infn/mw/iam/core/web/IamDiscoveryEndpoint.java @@ -0,0 +1,401 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.core.web; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import org.mitre.discovery.util.WebfingerURLNormalizer; +import org.mitre.jwt.encryption.service.JWTEncryptionAndDecryptionService; +import org.mitre.oauth2.model.PKCEAlgorithm; +import org.mitre.oauth2.service.SystemScopeService; +import org.mitre.oauth2.web.DeviceEndpoint; +import org.mitre.oauth2.web.IntrospectionEndpoint; +import org.mitre.oauth2.web.RevocationEndpoint; +import org.mitre.openid.connect.config.ConfigurationPropertiesBean; +import org.mitre.openid.connect.model.UserInfo; +import org.mitre.openid.connect.service.UserInfoService; +import org.mitre.openid.connect.view.HttpCodeView; +import org.mitre.openid.connect.view.JsonEntityView; +import org.mitre.openid.connect.web.DynamicClientRegistrationEndpoint; +import org.mitre.openid.connect.web.JWKSetPublishingEndpoint; +import org.mitre.openid.connect.web.UserInfoEndpoint; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; + +import com.google.common.base.Function; +import com.google.common.base.Strings; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import com.nimbusds.jose.Algorithm; +import com.nimbusds.jose.JWSAlgorithm; + +@Controller +public class IamDiscoveryEndpoint { + + public static final String WELL_KNOWN_URL = ".well-known"; + public static final String OPENID_CONFIGURATION_URL = WELL_KNOWN_URL + "/openid-configuration"; + public static final String WEBFINGER_URL = WELL_KNOWN_URL + "/webfinger"; + public static final String ABOUT_URL = "about"; + + /** + * Logger for this class + */ + private static final Logger logger = LoggerFactory.getLogger(IamDiscoveryEndpoint.class); + + @Autowired + private ConfigurationPropertiesBean config; + + @Autowired + private SystemScopeService scopeService; + + @Autowired + private JWTEncryptionAndDecryptionService encService; + + @Autowired + private UserInfoService userService; + + // used to map JWA algorithms objects to strings + private Function toAlgorithmName = new Function() { + @Override + public String apply(Algorithm alg) { + + if (Objects.isNull(alg)) { + return null; + } else { + return alg.getName(); + } + } + }; + + @RequestMapping(value = {"/" + WEBFINGER_URL}, produces = MediaType.APPLICATION_JSON_VALUE) + public String webfinger(@RequestParam("resource") String resource, + @RequestParam(value = "rel", required = false) String rel, Model model) { + + if (!Strings.isNullOrEmpty(rel) && !"http://openid.net/specs/connect/1.0/issuer".equals(rel)) { + logger.warn("Responding to webfinger request for non-OIDC relation: {}", rel); + } + + if (!resource.equals(config.getIssuer())) { + // it's not the issuer directly, need to check other methods + + UriComponents resourceUri = WebfingerURLNormalizer.normalizeResource(resource); + if (resourceUri != null && resourceUri.getScheme() != null + && "acct".equals(resourceUri.getScheme())) { + // acct: URI (email address format) + + // check on email addresses first + UserInfo user = + userService.getByEmailAddress(resourceUri.getUserInfo() + "@" + resourceUri.getHost()); + + if (user == null) { + // user wasn't found, see if the local part of the username matches, plus our issuer iamHost + + user = userService.getByUsername(resourceUri.getUserInfo()); // first part is the username + + if (user != null) { + // username matched, check the iamHost component + UriComponents issuerComponents = + UriComponentsBuilder.fromHttpUrl(config.getIssuer()).build(); + if (!Strings.nullToEmpty(issuerComponents.getHost()) + .equals(Strings.nullToEmpty(resourceUri.getHost()))) { + logger.info("Host mismatch, expected " + issuerComponents.getHost() + " got " + + resourceUri.getHost()); + model.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return HttpCodeView.VIEWNAME; + } + + } else { + + // if the user's still null, punt and say we didn't find them + + logger.info("User not found: {}", resource); + model.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return HttpCodeView.VIEWNAME; + } + + } + + } else { + logger.info("Unknown URI format: {}", resource); + model.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return HttpCodeView.VIEWNAME; + } + } + + // if we got here, then we're good, return ourselves + model.addAttribute("resource", resource); + model.addAttribute("issuer", config.getIssuer()); + + return "webfingerView"; + } + + @RequestMapping("/" + OPENID_CONFIGURATION_URL) + public String providerConfiguration(Model model) { + // @formatter:off + /* + issuer + REQUIRED. URL using the https scheme with no query or fragment component that the OP asserts as its Issuer Identifier. + authorization_endpoint + OPTIONAL. URL of the OP's Authentication and Authorization Endpoint [OpenID.Messages]. + token_endpoint + OPTIONAL. URL of the OP's OAuth 2.0 Token Endpoint [OpenID.Messages]. + userinfo_endpoint + RECOMMENDED. URL of the OP's UserInfo Endpoint [OpenID.Messages]. This URL MUST use the https scheme + and MAY contain port, path, and query parameter components. + check_session_iframe + OPTIONAL. URL of an OP endpoint that provides a page to support cross-origin communications for session state information with + the RP Client, using the HTML5 postMessage API. The page is loaded from an invisible iframe embedded in an RP page so that + it can run in the OP's security context. See [OpenID.Session]. + end_session_endpoint + OPTIONAL. URL of the OP's endpoint that initiates logging out the End-User. See [OpenID.Session]. + jwks_uri + REQUIRED. URL of the OP's JSON Web Key Set [JWKProperties] document. This contains the signing key(s) the Client uses to + validate signatures from the OP. The JWKProperties Set MAY also contain the Server's encryption key(s), + which are used by Clients to encrypt requests to the Server. When both signing and encryption keys are made available, + a use (Key Use) parameter value is REQUIRED for all keys in the document to indicate each key's intended usage. + registration_endpoint + RECOMMENDED. URL of the OP's Dynamic Client Registration Endpoint [OpenID.Registration]. + scopes_supported + RECOMMENDED. JSON array containing a list of the OAuth 2.0 [RFC6749] scope values that this server supports. + The server MUST support the openid scope value. + response_types_supported + REQUIRED. JSON array containing a list of the OAuth 2.0 response_type values that this server supports. + The server MUST support the code, id_token, and the token id_token response type values. + grant_types_supported + OPTIONAL. JSON array containing a list of the OAuth 2.0 grant type values that this server supports. + The server MUST support the authorization_code and implicit grant type values + and MAY support the urn:ietf:params:oauth:grant-type:jwt-bearer grant type defined in OAuth JWT Bearer Token Profiles [OAuth.JWT]. + If omitted, the default value is ["authorization_code", "implicit"]. + acr_values_supported + OPTIONAL. JSON array containing a list of the Authentication Context Class References that this server supports. + subject_types_supported + REQUIRED. JSON array containing a list of the subject identifier types that this server supports. Valid types include pairwise and public. + userinfo_signing_alg_values_supported + OPTIONAL. JSON array containing a list of the JWS [JWS] signing algorithms (alg values) [JWA] supported by the UserInfo Endpoint to + encode the Claims in a JWT [JWT]. + userinfo_encryption_alg_values_supported + OPTIONAL. JSON array containing a list of the JWE [JWE] encryption algorithms (alg values) [JWA] supported by the UserInfo Endpoint to + encode the Claims in a JWT [JWT]. + userinfo_encryption_enc_values_supported + OPTIONAL. JSON array containing a list of the JWE encryption algorithms (enc values) [JWA] supported by the UserInfo Endpoint to + encode the Claims in a JWT [JWT]. + id_token_signing_alg_values_supported + REQUIRED. JSON array containing a list of the JWS signing algorithms (alg values) supported by the Authorization Server for the + ID Token to encode the Claims in a JWT [JWT]. + id_token_encryption_alg_values_supported + OPTIONAL. JSON array containing a list of the JWE encryption algorithms (alg values) supported by the Authorization Server for the + ID Token to encode the Claims in a JWT [JWT]. + id_token_encryption_enc_values_supported + OPTIONAL. JSON array containing a list of the JWE encryption algorithms (enc values) supported by the Authorization Server for the + ID Token to encode the Claims in a JWT [JWT]. + request_object_signing_alg_values_supported + OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values) supported by the Authorization Server for + the Request Object described in Section 2.9 of OpenID Connect Messages 1.0 [OpenID.Messages]. These algorithms are used both when + the Request Object is passed by value (using the request parameter) and when it is passed by reference (using the request_uri parameter). + Servers SHOULD support none and RS256. + request_object_encryption_alg_values_supported + OPTIONAL. JSON array containing a list of the JWE encryption algorithms (alg values) supported by the Authorization Server for + the Request Object described in Section 2.9 of OpenID Connect Messages 1.0 [OpenID.Messages]. These algorithms are used both when + the Request Object is passed by value and when it is passed by reference. + request_object_encryption_enc_values_supported + OPTIONAL. JSON array containing a list of the JWE encryption algorithms (enc values) supported by the Authorization Server for + the Request Object described in Section 2.9 of OpenID Connect Messages 1.0 [OpenID.Messages]. These algorithms are used both when + the Request Object is passed by value and when it is passed by reference. + token_endpoint_auth_methods_supported + OPTIONAL. JSON array containing a list of authentication methods supported by this Token Endpoint. + The options are client_secret_post, client_secret_basic, client_secret_jwt, and private_key_jwt, + as described in Section 2.2.1 of OpenID Connect Messages 1.0 [OpenID.Messages]. + Other authentication methods MAY be defined by extensions. + If omitted, the default is client_secret_basic -- the HTTP Basic Authentication Scheme as specified in + Section 2.3.1 of OAuth 2.0 [RFC6749]. + token_endpoint_auth_signing_alg_values_supported + OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values) supported by the Token Endpoint for + the private_key_jwt and client_secret_jwt methods to encode the JWT [JWT]. Servers SHOULD support RS256. + display_values_supported + OPTIONAL. JSON array containing a list of the display parameter values that the OpenID Provider supports. + These values are described in Section 2.1.1 of OpenID Connect Messages 1.0 [OpenID.Messages]. + claim_types_supported + OPTIONAL. JSON array containing a list of the Claim Types that the OpenID Provider supports. + These Claim Types are described in Section 2.6 of OpenID Connect Messages 1.0 [OpenID.Messages]. + Values defined by this specification are normal, aggregated, and distributed. + If not specified, the implementation supports only normal Claims. + claims_supported + RECOMMENDED. JSON array containing a list of the Claim Names of the Claims that the OpenID Provider MAY be able to supply values for. + Note that for privacy or other reasons, this might not be an exhaustive list. + service_documentation + OPTIONAL. URL of a page containing human-readable information that developers might want or need to know when using the OpenID Provider. + In particular, if the OpenID Provider does not support Dynamic Client Registration, then information on how to register Clients needs + to be provided in this documentation. + claims_locales_supported + OPTIONAL. Languages and scripts supported for values in Claims being returned, represented as a JSON array of + BCP47 [RFC5646] language tag values. Not all languages and scripts are necessarily supported for all Claim values. + ui_locales_supported + OPTIONAL. Languages and scripts supported for the user interface, represented as a JSON array of BCP47 [RFC5646] language tag values. + claims_parameter_supported + OPTIONAL. Boolean value specifying whether the OP supports use of the claims parameter, with true indicating support. + If omitted, the default value is false. + request_parameter_supported + OPTIONAL. Boolean value specifying whether the OP supports use of the request parameter, with true indicating support. + If omitted, the default value is false. + request_uri_parameter_supported + OPTIONAL. Boolean value specifying whether the OP supports use of the request_uri parameter, with true indicating support. + If omitted, the default value is true. + require_request_uri_registration + OPTIONAL. Boolean value specifying whether the OP requires any request_uri values used to be pre-registered using + the request_uris registration parameter. Pre-registration is REQUIRED when the value is true. If omitted, the default value is false. + op_policy_uri + OPTIONAL. URL that the OpenID Provider provides to the person registering the Client to read about the OP's requirements on + how the Relying Party can use the data provided by the OP. The registration process SHOULD display this URL to the person registering + the Client if it is given. + op_tos_uri + OPTIONAL. URL that the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service. + The registration process SHOULD display this URL to the person registering the Client if it is given. + */ + // @formatter: on + String baseUrl = config.getIssuer(); + + Collection clientSymmetricAndAsymmetricSigningAlgs = Lists.newArrayList( + JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512, JWSAlgorithm.RS256, + JWSAlgorithm.RS384, JWSAlgorithm.RS512, JWSAlgorithm.ES256, JWSAlgorithm.ES384, + JWSAlgorithm.ES512, JWSAlgorithm.PS256, JWSAlgorithm.PS384, JWSAlgorithm.PS512); + Collection clientSymmetricAndAsymmetricSigningAlgsWithNone = + Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512, + JWSAlgorithm.RS256, JWSAlgorithm.RS384, JWSAlgorithm.RS512, JWSAlgorithm.ES256, + JWSAlgorithm.ES384, JWSAlgorithm.ES512, JWSAlgorithm.PS256, JWSAlgorithm.PS384, + JWSAlgorithm.PS512, Algorithm.NONE); + + // @formatter:off + ArrayList grantTypes = Lists.newArrayList( + "authorization_code", + "implicit", + "refresh_token", + "client_credentials", + "password", + "urn:ietf:params:oauth:grant-type:jwt-bearer", + "urn:ietf:params:oauth:grant_type:redelegate", + "urn:ietf:params:oauth:grant-type:token-exchange", + "urn:ietf:params:oauth:grant-type:device_code"); + // @formatter:on + + Map m = new HashMap<>(); + m.put("issuer", config.getIssuer()); + m.put("authorization_endpoint", baseUrl + "authorize"); + m.put("token_endpoint", baseUrl + "token"); + m.put("userinfo_endpoint", baseUrl + UserInfoEndpoint.URL); + // check_session_iframe + + // end_session_endpoint + m.put("jwks_uri", baseUrl + JWKSetPublishingEndpoint.URL); + m.put("registration_endpoint", baseUrl + DynamicClientRegistrationEndpoint.URL); + m.put("scopes_supported", scopeService.toStrings(scopeService.getUnrestricted())); + m.put("response_types_supported", Lists.newArrayList("code", "token")); + m.put("grant_types_supported", grantTypes); + + // acr_values_supported + m.put("subject_types_supported", Lists.newArrayList("public", "pairwise")); + m.put("userinfo_signing_alg_values_supported", + Collections2.transform(clientSymmetricAndAsymmetricSigningAlgs, toAlgorithmName)); + m.put("userinfo_encryption_alg_values_supported", + Collections2.transform(encService.getAllEncryptionAlgsSupported(), toAlgorithmName)); + m.put("userinfo_encryption_enc_values_supported", + Collections2.transform(encService.getAllEncryptionEncsSupported(), toAlgorithmName)); + m.put("id_token_signing_alg_values_supported", + Collections2.transform(clientSymmetricAndAsymmetricSigningAlgsWithNone, toAlgorithmName)); + m.put("id_token_encryption_alg_values_supported", + Collections2.transform(encService.getAllEncryptionAlgsSupported(), toAlgorithmName)); + m.put("id_token_encryption_enc_values_supported", + Collections2.transform(encService.getAllEncryptionEncsSupported(), toAlgorithmName)); + m.put("request_object_signing_alg_values_supported", + Collections2.transform(clientSymmetricAndAsymmetricSigningAlgs, toAlgorithmName)); + m.put("request_object_encryption_alg_values_supported", + Collections2.transform(encService.getAllEncryptionAlgsSupported(), toAlgorithmName)); + m.put("request_object_encryption_enc_values_supported", + Collections2.transform(encService.getAllEncryptionEncsSupported(), toAlgorithmName)); + + // @formatter:off + m.put("token_endpoint_auth_methods_supported", Lists.newArrayList( + "client_secret_post", + "client_secret_basic", + "none")); + // @formatter:on + + m.put("token_endpoint_auth_signing_alg_values_supported", + Collections2.transform(clientSymmetricAndAsymmetricSigningAlgs, toAlgorithmName)); + + // display_types_supported + m.put("claim_types_supported", Lists.newArrayList("normal")); + // @formatter:off + m.put("claims_supported", Lists.newArrayList( + "sub", + "name", + "preferred_username", + "given_name", + "family_name", + "middle_name", + "nickname", + "profile", + "picture", + "website", + "gender", + "zoneinfo", + "locale", + "updated_at", + "birthdate", + "email", + "email_verified", + "phone_number", + "phone_number_verified", + "address", + "organisation_name", + "groups", + "external_authn")); + // @formatter:on + + m.put("service_documentation", baseUrl + ABOUT_URL); + // claims_locales_supported + // ui_locales_supported + m.put("claims_parameter_supported", false); + m.put("request_parameter_supported", true); + m.put("request_uri_parameter_supported", false); + m.put("require_request_uri_registration", false); + m.put("op_policy_uri", baseUrl + ABOUT_URL); + m.put("op_tos_uri", baseUrl + ABOUT_URL); + + m.put("introspection_endpoint", baseUrl + IntrospectionEndpoint.URL); + m.put("revocation_endpoint", baseUrl + RevocationEndpoint.URL); + + m.put("code_challenge_methods_supported", + Lists.newArrayList(PKCEAlgorithm.plain.getName(), PKCEAlgorithm.S256.getName())); + + m.put("device_authorization_endpoint", baseUrl + DeviceEndpoint.URL); + model.addAttribute(JsonEntityView.ENTITY, m); + + return JsonEntityView.VIEWNAME; + } +} diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/core/web/jwk/IamJWKSetPublishingEndpoint.java b/iam-login-service/src/main/java/it/infn/mw/iam/core/web/jwk/IamJWKSetPublishingEndpoint.java index 6b9399298..6cf194a3a 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/core/web/jwk/IamJWKSetPublishingEndpoint.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/core/web/jwk/IamJWKSetPublishingEndpoint.java @@ -28,6 +28,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; + import org.springframework.web.bind.annotation.RestController; import com.nimbusds.jose.jwk.JWK; diff --git a/iam-login-service/src/main/resources/application-h2.yml b/iam-login-service/src/main/resources/application-h2.yml index f3128b92c..99fcfa7c4 100644 --- a/iam-login-service/src/main/resources/application-h2.yml +++ b/iam-login-service/src/main/resources/application-h2.yml @@ -27,7 +27,7 @@ spring: locations: - classpath:db/migration/h2 - classpath:db/migration/test - + datasource: type: org.h2.jdbcx.JdbcDataSource url: jdbc:h2:mem:iam;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1 diff --git a/iam-login-service/src/main/resources/application-prod.yml b/iam-login-service/src/main/resources/application-prod.yml index f1e9582b7..845329669 100644 --- a/iam-login-service/src/main/resources/application-prod.yml +++ b/iam-login-service/src/main/resources/application-prod.yml @@ -36,4 +36,4 @@ spring: hikari: maximum-pool-size: ${IAM_DB_MAX_ACTIVE:50} minimum-idle: ${IAM_DB_MIN_IDLE:8} - connection-test-query: ${IAM_DB_VALIDATION_QUERY:SELECT 1} \ No newline at end of file + connection-test-query: ${IAM_DB_VALIDATION_QUERY:SELECT 1} diff --git a/iam-login-service/src/main/resources/application.properties b/iam-login-service/src/main/resources/application.properties index 696ab3e43..3face04bf 100644 --- a/iam-login-service/src/main/resources/application.properties +++ b/iam-login-service/src/main/resources/application.properties @@ -39,7 +39,6 @@ logging.level.org.apache.tomcat.util.scan.StandardJarScanner=ERROR # Persistence engine logging logging.level.org.eclipse.persistence=DEBUG - # Notification service logging #logging.level.it.infn.mw.iam.notification=DEBUG diff --git a/iam-login-service/src/main/resources/application.yml b/iam-login-service/src/main/resources/application.yml index 76083b81d..433d5a5cb 100644 --- a/iam-login-service/src/main/resources/application.yml +++ b/iam-login-service/src/main/resources/application.yml @@ -25,6 +25,7 @@ server: port: ${IAM_PORT:8080} tomcat: + accesslog: enabled: ${IAM_TOMCAT_ACCESS_LOG_ENABLED:false} directory: ${IAM_TOMCAT_ACCESS_LOG_DIRECTORY:/tmp} diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureCheckIntegrationTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureCheckIntegrationTests.java index 192827547..c0749bf76 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureCheckIntegrationTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureCheckIntegrationTests.java @@ -17,6 +17,10 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +<<<<<<< HEAD +======= +import static org.hamcrest.MatcherAssert.assertThat; +>>>>>>> af13c9c9 (Merging changes for updating Spring boot and Java version. Squashed commit of the following:) import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/requests/GroupRequestsGetDetailsTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/requests/GroupRequestsGetDetailsTests.java index 14ee9764d..c95bdcbec 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/requests/GroupRequestsGetDetailsTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/requests/GroupRequestsGetDetailsTests.java @@ -53,7 +53,7 @@ public class GroupRequestsGetDetailsTests extends GroupRequestsTestUtils { public void getGroupRequestDetailsAsAdmin() throws Exception { GroupRequestDto request = savePendingGroupRequest(TEST_100_USERNAME, TEST_001_GROUPNAME); - + // @formatter:off mvc.perform(get(GET_DETAILS_URL, request.getUuid())) .andExpect(status().isOk()) diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/ext_authn/x509/X509AuthenticationIntegrationTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/ext_authn/x509/X509AuthenticationIntegrationTests.java index 973ab3dda..44265653e 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/ext_authn/x509/X509AuthenticationIntegrationTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/ext_authn/x509/X509AuthenticationIntegrationTests.java @@ -58,7 +58,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import it.infn.mw.iam.IamLoginService; import it.infn.mw.iam.authn.x509.IamX509AuthenticationCredential; import it.infn.mw.iam.persistence.model.IamAccount; import it.infn.mw.iam.persistence.model.IamX509Certificate; diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/lifecycle/AccountLifecycleNoSuspensionGracePeriodTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/lifecycle/AccountLifecycleNoSuspensionGracePeriodTests.java index cb97f60e9..9d6588164 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/lifecycle/AccountLifecycleNoSuspensionGracePeriodTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/lifecycle/AccountLifecycleNoSuspensionGracePeriodTests.java @@ -51,8 +51,7 @@ @IamMockMvcIntegrationTest @SpringBootTest( classes = {IamLoginService.class, CoreControllerTestSupport.class, - AccountLifecycleNoSuspensionGracePeriodTests.TestConfig.class}, - webEnvironment = WebEnvironment.MOCK) + AccountLifecycleNoSuspensionGracePeriodTests.TestConfig.class}, webEnvironment = WebEnvironment.MOCK) @TestPropertySource( properties = {"lifecycle.account.expiredAccountPolicy.suspensionGracePeriodDays=0", "lifecycle.account.expiredAccountPolicy.removalGracePeriodDays=30"}) diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/lifecycle/AccountLifecycleTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/lifecycle/AccountLifecycleTests.java index bd00353a1..489537e99 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/lifecycle/AccountLifecycleTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/lifecycle/AccountLifecycleTests.java @@ -203,5 +203,4 @@ public void testNoAccountsRemoved() { assertThat(accountBefore, is(accountAfter)); } - } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/AuthorizationCodeIntegrationTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/AuthorizationCodeIntegrationTests.java new file mode 100644 index 000000000..721591605 --- /dev/null +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/AuthorizationCodeIntegrationTests.java @@ -0,0 +1,197 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.test.oauth; + +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; + +import java.io.IOException; +import java.text.ParseException; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.util.UriComponentsBuilder; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jayway.restassured.RestAssured; +import com.jayway.restassured.response.ValidatableResponse; +import com.nimbusds.jwt.JWT; +import com.nimbusds.jwt.JWTParser; + +import it.infn.mw.iam.test.TestUtils; +import it.infn.mw.iam.test.util.annotation.IamRandomPortIntegrationTest; + +@RunWith(SpringRunner.class) +@IamRandomPortIntegrationTest +public class AuthorizationCodeIntegrationTests { + + @Value("${local.server.port}") + private Integer iamPort; + + @Autowired + ObjectMapper mapper; + + public static final String TEST_CLIENT_ID = "client"; + public static final String TEST_CLIENT_SECRET = "secret"; + public static final String TEST_CLIENT_REDIRECT_URI = + "https://iam.local.io/iam-test-client/openid_connect_login"; + + public static final String LOCALHOST_URL_TEMPLATE = "http://localhost:%d"; + + public static final String RESPONSE_TYPE_CODE = "code"; + + public static final String SCOPE = "openid profile"; + + public static final String TEST_USER_ID = "test"; + public static final String TEST_USER_PASSWORD = "password"; + + private String loginUrl; + private String authorizeUrl; + private String tokenUrl; + + @BeforeClass + public static void init() { + TestUtils.initRestAssured(); + + } + + @Before + public void setup() { + RestAssured.port = iamPort; + loginUrl = String.format(LOCALHOST_URL_TEMPLATE + "/login", iamPort); + authorizeUrl = String.format(LOCALHOST_URL_TEMPLATE + "/authorize", iamPort); + tokenUrl = String.format(LOCALHOST_URL_TEMPLATE + "/token", iamPort); + } + + @Test + public void testAuthzCodeAudienceSupport() + throws JsonProcessingException, IOException, ParseException { + + String[] audienceKeys = {"aud", "audience"}; + + for (String audKey : audienceKeys) { + + // @formatter:off + ValidatableResponse resp1 = RestAssured.given() + .queryParam("response_type", RESPONSE_TYPE_CODE) + .queryParam("client_id", TEST_CLIENT_ID) + .queryParam("redirect_uri", TEST_CLIENT_REDIRECT_URI) + .queryParam("scope", SCOPE) + .queryParam(audKey, "example-audience") + .queryParam("nonce", "1") + .queryParam("state", "1") + .redirects().follow(false) + .when() + .get(authorizeUrl) + .then() + .statusCode(HttpStatus.FOUND.value()) + .header("Location", is(loginUrl)); + // @formatter:on + + // @formatter:off + ValidatableResponse resp2 = RestAssured.given() + .formParam("username", "test") + .formParam("password", "password") + .formParam("submit", "Login") + .cookie(resp1.extract().detailedCookie("JSESSIONID")) + .redirects().follow(false) + .when() + .post(loginUrl) + .then() + .statusCode(HttpStatus.FOUND.value()); + // @formatter:on + + // @formatter:off + RestAssured.given() + .cookie(resp2.extract().detailedCookie("JSESSIONID")) + .queryParam("response_type", RESPONSE_TYPE_CODE) + .queryParam("client_id", TEST_CLIENT_ID) + .queryParam("redirect_uri", TEST_CLIENT_REDIRECT_URI) + .queryParam("scope", SCOPE) + .queryParam(audKey, "example-audience") + .queryParam("nonce", "1") + .queryParam("state", "1") + .redirects().follow(false) + .when() + .get(authorizeUrl) + .then() + .log().all() + .statusCode(HttpStatus.OK.value()); + // @formatter:on + + // @formatter:off + ValidatableResponse resp4 = RestAssured.given() + .cookie(resp2.extract().detailedCookie("JSESSIONID")) + .formParam("user_oauth_approval", "true") + .formParam("authorize", "Authorize") + .formParam("scope_openid", "openid") + .formParam("scope_profile", "profile") + .formParam("remember", "none") + .redirects().follow(false) + .when() + .post(authorizeUrl) + .then() + .statusCode(HttpStatus.SEE_OTHER.value()); + // @formatter:on + + String authzCode = UriComponentsBuilder.fromHttpUrl(resp4.extract().header("Location")) + .build() + .getQueryParams() + .get("code") + .get(0); + + // @formatter:off + ValidatableResponse resp5= RestAssured.given() + .formParam("grant_type", "authorization_code") + .formParam("redirect_uri", TEST_CLIENT_REDIRECT_URI) + .formParam("code", authzCode) + .formParam("state", "1") + .authentication() + .preemptive() + .basic(TEST_CLIENT_ID, TEST_CLIENT_SECRET) + .when() + .post(tokenUrl) + .then() + .statusCode(HttpStatus.OK.value()); + // @formatter:on + + String accessToken = + mapper.readTree(resp5.extract().body().asString()).get("access_token").asText(); + + String idToken = mapper.readTree(resp5.extract().body().asString()).get("id_token").asText(); + + JWT atJwt = JWTParser.parse(accessToken); + JWT itJwt = JWTParser.parse(idToken); + + assertThat(atJwt.getJWTClaimsSet().getAudience(), hasSize(1)); + assertThat(atJwt.getJWTClaimsSet().getAudience(), hasItem("example-audience")); + + assertThat(itJwt.getJWTClaimsSet().getAudience(), hasSize(1)); + assertThat(itJwt.getJWTClaimsSet().getAudience(), hasItem(TEST_CLIENT_ID)); + } + + } + +} diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/ClientRegistrationAuthzTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/ClientRegistrationAuthzTests.java new file mode 100644 index 000000000..a19cde9ff --- /dev/null +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/ClientRegistrationAuthzTests.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.test.oauth; + +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; + + +@RunWith(SpringRunner.class) +@IamMockMvcIntegrationTest +@TestPropertySource(properties = {"client-registration.allow-for=REGISTERED_USERS"}) +public class ClientRegistrationAuthzTests extends ClientRegistrationTestSupport { + + @Autowired + private MockMvc mvc; + + + @Test + public void testClientRegistrationRequiresAuthenticatedUser() throws Exception { + + String jsonInString = ClientJsonStringBuilder.builder().scopes("test").build(); + + mvc.perform(post(REGISTER_ENDPOINT).contentType(APPLICATION_JSON).content(jsonInString)) + .andExpect(status().isUnauthorized()); + } + + @WithMockUser(username="test", roles="USER") + public void testClientRegistrationWorksForAuthenticatedUser() throws Exception { + + String jsonInString = ClientJsonStringBuilder.builder().scopes("test").build(); + + mvc.perform(post(REGISTER_ENDPOINT).contentType(APPLICATION_JSON).content(jsonInString)) + .andExpect(status().isCreated()); + } + + @WithMockUser(username="admin", roles="ADMIN") + public void testClientRegistrationWorksForAdminUser() throws Exception { + + String jsonInString = ClientJsonStringBuilder.builder().scopes("test").build(); + + mvc.perform(post(REGISTER_ENDPOINT).contentType(APPLICATION_JSON).content(jsonInString)) + .andExpect(status().isCreated()); + } + +} diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/DiscoveryEndpointTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/DiscoveryEndpointTests.java new file mode 100644 index 000000000..2f165a7a7 --- /dev/null +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/DiscoveryEndpointTests.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.test.oauth; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasItem; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.Arrays; +import java.util.Set; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import com.google.common.collect.Sets; + +import it.infn.mw.iam.IamLoginService; +import it.infn.mw.iam.core.web.IamDiscoveryEndpoint; +import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; + + +@RunWith(SpringRunner.class) +@IamMockMvcIntegrationTest +@SpringBootTest(classes = {IamLoginService.class}, webEnvironment = WebEnvironment.MOCK) +public class DiscoveryEndpointTests { + + private String endpoint = "/" + IamDiscoveryEndpoint.OPENID_CONFIGURATION_URL; + + private Set iamSupportedGrants = Sets.newLinkedHashSet(Arrays.asList("authorization_code", + "implicit", "refresh_token", "client_credentials", "password", + "urn:ietf:params:oauth:grant-type:jwt-bearer", "urn:ietf:params:oauth:grant_type:redelegate", + "urn:ietf:params:oauth:grant-type:token-exchange", + "urn:ietf:params:oauth:grant-type:device_code")); + + private static final String IAM_ORGANISATION_NAME_CLAIM = "organisation_name"; + private static final String IAM_GROUPS_CLAIM = "groups"; + private static final String IAM_EXTERNAL_AUTHN_CLAIM = "external_authn"; + + @Autowired + private MockMvc mvc; + + @Test + public void testGrantTypesSupported() throws Exception { + + // @formatter:off + mvc.perform(post(endpoint)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.grant_types_supported").isNotEmpty()) + .andExpect(jsonPath("$.grant_types_supported").isArray()) + .andExpect(jsonPath("$.grant_types_supported").value(containsInAnyOrder(iamSupportedGrants.toArray()))); + // @formatter:on + } + + @Test + public void testSupportedClaims() throws Exception { + + // @formatter:off + mvc.perform(post(endpoint)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.claims_supported").isNotEmpty()) + .andExpect(jsonPath("$.claims_supported").isArray()) + .andExpect(jsonPath("$.claims_supported", hasItem(IAM_ORGANISATION_NAME_CLAIM))) + .andExpect(jsonPath("$.claims_supported", hasItem(IAM_GROUPS_CLAIM))) + .andExpect(jsonPath("$.claims_supported", hasItem(IAM_EXTERNAL_AUTHN_CLAIM))); + // @formatter:on + } + + @Test + public void testDeviceCodeEndpoint() throws Exception { + // @formatter:off + mvc.perform(post(endpoint)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.device_authorization_endpoint", is("http://localhost:8080/devicecode"))); + // @formatter:on + } + +} diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/devicecode/DeviceCodeTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/devicecode/DeviceCodeTests.java index e41ae79d0..1f5ca5190 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/devicecode/DeviceCodeTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/devicecode/DeviceCodeTests.java @@ -63,7 +63,6 @@ import it.infn.mw.iam.test.oauth.client_registration.ClientRegistrationTestSupport.ClientJsonStringBuilder; import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; - @RunWith(SpringRunner.class) @IamMockMvcIntegrationTest @SpringBootTest(classes = {IamLoginService.class}, webEnvironment = WebEnvironment.MOCK) diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/jwk/JWKEndpointTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/jwk/JWKEndpointTests.java index d665b6f01..94aaeddb6 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/jwk/JWKEndpointTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/jwk/JWKEndpointTests.java @@ -55,4 +55,5 @@ public void jwkEndpointReturnsKeyMaterial() throws Exception { // @formatter:on } + } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/profile/AarcClaimValueHelperTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/profile/AarcClaimValueHelperTests.java index cc17a7806..57999bceb 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/profile/AarcClaimValueHelperTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/profile/AarcClaimValueHelperTests.java @@ -86,7 +86,6 @@ public void testGroupUrnEncode() { g.setName("test"); groupService.createGroup(g); - when(userInfo.getGroups()).thenReturn(Sets.newHashSet(g)); Set urns = helper.resolveGroups(userInfo); diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/RegistrationUsernameTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/RegistrationUsernameTests.java index dc61d61c1..9e0e6b861 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/RegistrationUsernameTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/RegistrationUsernameTests.java @@ -114,4 +114,41 @@ public void invalidUsernames() throws Exception { } } + private RegistrationRequestDto createRegistrationRequest(String username) { + + String email = username + "@example.org"; + RegistrationRequestDto request = new RegistrationRequestDto(); + request.setGivenname("Test"); + request.setFamilyname("User"); + request.setEmail(email); + request.setUsername(username); + request.setNotes("Some short notes..."); + request.setPassword("password"); + + return request; + } + + @Test + public void validUsernames() throws Exception { + final String[] validUsernames = {"bob", "b", "test$", "root", "test1234", "test_", "_test"}; + + for (String u : validUsernames) { + RegistrationRequestDto r = createRegistrationRequest(u); + mvc.perform(post("/registration/create").contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(r))).andExpect(status().isOk()); + } + + } + + @Test + public void nonUnixUsernames() throws Exception { + final String[] nonUnixUsernames = {"£$%^&*(", ".,", "-test", "1test", "test$$", "username@example.com", "username@domain", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}; + + for (String u : nonUnixUsernames) { + RegistrationRequestDto r = createRegistrationRequest(u); + mvc.perform(post("/registration/create").contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(r))).andExpect(status().isBadRequest()); + } + } } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/repository/IamTokenRepositoryTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/repository/IamTokenRepositoryTests.java index 64977268e..9ae170704 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/repository/IamTokenRepositoryTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/repository/IamTokenRepositoryTests.java @@ -68,6 +68,7 @@ public class IamTokenRepositoryTests { private IamOAuthRefreshTokenRepository refreshTokenRepo; @Autowired +<<<<<<< HEAD private AuthenticationHolderRepository authenticationHolderRepo; @Autowired diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/ScimRestUtilsMvc.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/ScimRestUtilsMvc.java index ef2a24dfd..c3df85dbd 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/ScimRestUtilsMvc.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/ScimRestUtilsMvc.java @@ -56,6 +56,8 @@ public ResultActions postUser(ScimUser user, HttpStatus expectedStatus) throws E return doPost(getUsersLocation(), user, SCIM_CONTENT_TYPE, expectedStatus); } + + public ScimUser getUser(String uuid) throws Exception { return mapper.readValue(getUser(uuid, OK).andReturn().getResponse().getContentAsString(), diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/core/provisioning/user/ScimUserServiceTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/core/provisioning/user/ScimUserServiceTests.java index 7255dcb89..69ff5bbe7 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/core/provisioning/user/ScimUserServiceTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/core/provisioning/user/ScimUserServiceTests.java @@ -17,8 +17,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import org.junit.Before; @@ -26,11 +26,9 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import it.infn.mw.iam.api.account.group_manager.AccountGroupManagerService; import it.infn.mw.iam.api.scim.converter.ScimResourceLocationProvider; -import it.infn.mw.iam.api.scim.model.ScimAttribute; import it.infn.mw.iam.api.scim.model.ScimEmail; import it.infn.mw.iam.api.scim.model.ScimGroupRef; import it.infn.mw.iam.api.scim.model.ScimLabel; @@ -42,9 +40,6 @@ import it.infn.mw.iam.api.scim.model.ScimUser; import it.infn.mw.iam.api.scim.provisioning.ScimUserProvisioning; import it.infn.mw.iam.persistence.model.IamAccount; -import it.infn.mw.iam.persistence.model.IamOidcId; -import it.infn.mw.iam.persistence.model.IamSamlId; -import it.infn.mw.iam.persistence.model.IamSshKey; import it.infn.mw.iam.persistence.repository.IamAccountRepository; import it.infn.mw.iam.test.SshKeyUtils; import it.infn.mw.iam.test.util.annotation.IamNoMvcTest; @@ -73,7 +68,6 @@ public class ScimUserServiceTests { final String TESTUSER_LABEL_NAME = "label-name"; final String TESTUSER_LABEL_VALUE = "label-value"; final String PRODUCTION_GROUP_UUID = "c617d586-54e6-411d-8e38-64967798fa8a"; - final String TESTUSER_USERNAME = "testProvisioningUser"; final String TESTUSER_PASSWORD = "password"; final ScimName TESTUSER_NAME = ScimName.builder().givenName("John").familyName("Lennon").build(); diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/me/patch/ScimMeEndpointPatchAddTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/me/patch/ScimMeEndpointPatchAddTests.java index 9ff9b6115..53a1bcc75 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/me/patch/ScimMeEndpointPatchAddTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/me/patch/ScimMeEndpointPatchAddTests.java @@ -45,6 +45,7 @@ import it.infn.mw.iam.test.util.WithMockOAuthUser; import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; + @RunWith(SpringRunner.class) @IamMockMvcIntegrationTest @SpringBootTest( @@ -327,5 +328,6 @@ public void testPatchAddX509CertificateNotSupported() throws Exception { public void testPatchAddX509CertificateNotSupportedNoToken() throws Exception { patchAddX509CertificateNotSupported(); + } } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserCreationTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserCreationTests.java index d7fee48be..ba99489f1 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserCreationTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserCreationTests.java @@ -96,6 +96,12 @@ public class ScimUserCreationTests extends ScimUserTestSupport { @Autowired private ObjectMapper mapper; + @Autowired + private MockMvc mvc; + + @Autowired + private ObjectMapper mapper; + @Autowired private MockOAuth2Filter mockOAuth2Filter; diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserProvisioningTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserProvisioningTests.java index 2768c0ae6..67354e44d 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserProvisioningTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserProvisioningTests.java @@ -339,6 +339,5 @@ public void testEmailIsNotAlreadyLinkedOnUpdate() throws Exception { .andExpect(jsonPath("$.detail", containsString("email user1@test.org already assigned to another user"))); - } } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/util/annotation/IamMockMvcIntegrationTest.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/util/annotation/IamMockMvcIntegrationTest.java index 989082579..e8e00c074 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/util/annotation/IamMockMvcIntegrationTest.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/util/annotation/IamMockMvcIntegrationTest.java @@ -37,6 +37,7 @@ classes = {IamLoginService.class, CoreControllerTestSupport.class, ScimRestUtilsMvc.class}, webEnvironment = WebEnvironment.MOCK) @AutoConfigureMockMvc(printOnlyOnFailure = true, print = MockMvcPrint.LOG_DEBUG) + @Transactional public @interface IamMockMvcIntegrationTest { diff --git a/iam-persistence/pom.xml b/iam-persistence/pom.xml index 81928ca94..487310a57 100644 --- a/iam-persistence/pom.xml +++ b/iam-persistence/pom.xml @@ -44,6 +44,11 @@ spring-boot-starter-validation + + org.springframework.boot + spring-boot-starter-validation + + org.springframework.boot spring-boot-starter-data-jpa diff --git a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/migrations/CreateGroupManagerAuthorities.java b/iam-persistence/src/main/java/it/infn/mw/iam/persistence/migrations/CreateGroupManagerAuthorities.java deleted file mode 100644 index b0c1402c6..000000000 --- a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/migrations/CreateGroupManagerAuthorities.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package it.infn.mw.iam.persistence.migrations; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.rowset.SqlRowSet; - -public class CreateGroupManagerAuthorities implements SpringJdbcFlywayMigration { - - public static final Logger LOG = LoggerFactory.getLogger(CreateGroupManagerAuthorities.class); - - @Override - public void migrate(JdbcTemplate jdbcTemplate) throws DataAccessException { - SqlRowSet rowSet = jdbcTemplate.queryForRowSet("SELECT id,uuid,name from iam_group"); - - while (rowSet.next()) { - String authority = String.format("ROLE_GM:%s", rowSet.getString("uuid")); - int updateResult = - jdbcTemplate.update("insert into iam_authority(auth) values (?)", authority); - if (updateResult == 1) { - LOG.debug("Created group manager authority '{}' for group '{}'", authority, - rowSet.getString("name")); - } - } - } - -} diff --git a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamTotpMfaRepositoryImpl.java b/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamTotpMfaRepositoryImpl.java index a8975abb1..f011a206c 100644 --- a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamTotpMfaRepositoryImpl.java +++ b/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamTotpMfaRepositoryImpl.java @@ -33,5 +33,4 @@ public class IamTotpMfaRepositoryImpl implements IamTotpMfaRepositoryCustom { public Optional findByAccount(IamAccount account) { return repo.findByAccountId(account.getId()); } - } diff --git a/iam-persistence/src/main/resources/db/migration/test/V100000___test_data.sql b/iam-persistence/src/main/resources/db/migration/test/V100000___test_data.sql index 552295e37..df691c2bd 100644 --- a/iam-persistence/src/main/resources/db/migration/test/V100000___test_data.sql +++ b/iam-persistence/src/main/resources/db/migration/test/V100000___test_data.sql @@ -28,6 +28,15 @@ INSERT INTO client_details (id, client_id, client_secret, client_name, dynamical false, null, 3600, 600, true,'PRIVATE_KEY', false, 'RS256', '{"keys":[{"kty":"RSA","e":"AQAB","kid":"rsa1","n":"1y1CP181zqPNPlV1JDM7Xv0QnGswhSTHe8_XPZHxDTJkykpk_1BmgA3ovP62QRE2ORgsv5oSBI_Z_RaOc4Zx2FonjEJF2oBHtBjsAiF-pxGkM5ZPjFNgFTGp1yUUBjFDcEeIGCwPEyYSt93sQIP_0DRbViMUnpyn3xgM_a1dO5brEWR2n1Uqff1yA5NXfLS03qpl2dpH4HFY5-Zs4bvtJykpAOhoHuIQbz-hmxb9MZ3uTAwsx2HiyEJtz-suyTBHO3BM2o8UcCeyfa34ShPB8i86-sf78fOk2KeRIW1Bju3ANmdV3sxL0j29cesxKCZ06u2ZiGR3Srbft8EdLPzf-w"}]}', true); +INSERT INTO client_details (id, client_id, client_secret, client_name, dynamically_registered, + refresh_token_validity_seconds, access_token_validity_seconds, id_token_validity_seconds, allow_introspection, + token_endpoint_auth_method, require_auth_time, token_endpoint_auth_signing_alg, jwks) VALUES + (15, 'jwt-auth-client_secret_jwt', 'c8e9eed0-e6e4-4a66-b16e-6f37096356a7', 'JWT Bearer Auth Client (client_secret_jwt)', + false, null, 3600, 600, true, 'SECRET_JWT', false, 'HS256', null), + (16, 'jwt-auth-private_key_jwt', 'secret', 'JWT Bearer Auth Client (private_key_jwt)', + false, null, 3600, 600, true,'PRIVATE_KEY', false, 'RS256', + '{"keys":[{"kty":"RSA","e":"AQAB","kid":"rsa1","n":"1y1CP181zqPNPlV1JDM7Xv0QnGswhSTHe8_XPZHxDTJkykpk_1BmgA3ovP62QRE2ORgsv5oSBI_Z_RaOc4Zx2FonjEJF2oBHtBjsAiF-pxGkM5ZPjFNgFTGp1yUUBjFDcEeIGCwPEyYSt93sQIP_0DRbViMUnpyn3xgM_a1dO5brEWR2n1Uqff1yA5NXfLS03qpl2dpH4HFY5-Zs4bvtJykpAOhoHuIQbz-hmxb9MZ3uTAwsx2HiyEJtz-suyTBHO3BM2o8UcCeyfa34ShPB8i86-sf78fOk2KeRIW1Bju3ANmdV3sxL0j29cesxKCZ06u2ZiGR3Srbft8EdLPzf-w"}]}'); + INSERT INTO client_scope (owner_id, scope) VALUES (1, 'openid'), (1, 'profile'), diff --git a/iam-test-protected-resource/pom.xml b/iam-test-protected-resource/pom.xml deleted file mode 100644 index 2111d81dd..000000000 --- a/iam-test-protected-resource/pom.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - 4.0.0 - - it.infn.mw - iam-parent - 1.7.1 - - - iam-test-protected-resource - jar - - IAM Test Protected Resource Application - A test protected resource application for the IAM - - - - - org.mitre - openid-connect-client - - - - org.bouncycastle - bcpkix-jdk15on - - - - org.italiangrid - voms-api-java - - - - org.apache.httpcomponents - httpclient - - - - org.springframework.boot - spring-boot-devtools - - - - org.springframework.security.oauth - spring-security-oauth2 - - - - org.springframework.security - spring-security-jwt - - - org.bouncycastle - bcpkix-jdk15on - - - - - - org.springframework.boot - spring-boot-starter-security - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-test - test - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - repackage - - - - - - -