diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1f856f93..c27e2520 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -16,16 +16,16 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: java queries: +security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/coverity-analysis.yml b/.github/workflows/coverity-analysis.yml index 13008097..f8035d46 100644 --- a/.github/workflows/coverity-analysis.yml +++ b/.github/workflows/coverity-analysis.yml @@ -15,15 +15,15 @@ jobs: PROJECTNAME: 'web-eid/web-eid-authtoken-validation-java' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: zulu java-version: 11 - name: Cache Maven packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-v8-${{ hashFiles('**/pom.xml') }} @@ -50,4 +50,4 @@ jobs: --form file=@upload.tgz \ --form version=master \ --form description="Github Actions CI build" \ - https://scan.coverity.com/builds?project=$PROJECTNAME \ No newline at end of file + https://scan.coverity.com/builds?project=$PROJECTNAME diff --git a/.github/workflows/maven-build-example.yml b/.github/workflows/maven-build-example.yml new file mode 100644 index 00000000..3893cbd4 --- /dev/null +++ b/.github/workflows/maven-build-example.yml @@ -0,0 +1,41 @@ +name: Maven build example + +on: + push: + paths: + - 'example/**' + - '.github/workflows/*example*' + pull_request: + paths: + - 'example/**' + - '.github/workflows/*example*' + +defaults: + run: + working-directory: ./example + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-java@v4 + with: + distribution: zulu + java-version: 17 + + - name: Cache Maven packages + uses: actions/cache@v4 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-v17-${{ secrets.CACHE_VERSION }}-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2-v17-${{ secrets.CACHE_VERSION }} + + - name: Build + run: mvn --batch-mode compile + + - name: Test and package + run: mvn --batch-mode package + diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-build.yml index 7d17deac..6528af68 100644 --- a/.github/workflows/maven-build.yml +++ b/.github/workflows/maven-build.yml @@ -1,21 +1,29 @@ name: Maven build -on: [ push, pull_request ] +on: + push: + paths-ignore: + - 'example/**' + - '.github/workflows/*example*' + pull_request: + paths-ignore: + - 'example/**' + - '.github/workflows/*example*' jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: zulu java-version: 11 - name: Cache Maven packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-v8-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/maven-deploy.yml b/.github/workflows/maven-deploy.yml index b37492e8..29a316f5 100644 --- a/.github/workflows/maven-deploy.yml +++ b/.github/workflows/maven-deploy.yml @@ -9,15 +9,15 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: zulu java-version: 11 - name: Cache Maven packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-v8-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/sonarcloud-analysis.yml b/.github/workflows/sonarcloud-analysis.yml index 2ed0c3a2..ea78e973 100644 --- a/.github/workflows/sonarcloud-analysis.yml +++ b/.github/workflows/sonarcloud-analysis.yml @@ -1,6 +1,14 @@ name: SonarCloud code analysis -on: [push, pull_request] +on: + push: + paths-ignore: + - 'example/**' + - '.github/workflows/*example*' + pull_request: + paths-ignore: + - 'example/**' + - '.github/workflows/*example*' jobs: analyze: @@ -13,18 +21,18 @@ jobs: with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: zulu java-version: 17 - name: Cache SonarCloud packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-v11-${{ hashFiles('**/pom.xml') }} diff --git a/README.md b/README.md index 1d470f2a..dd94fe3e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ A Java web application that uses Maven or Gradle to manage packages is needed fo In the following example we are using the [Spring Framework](https://spring.io/), but the examples can be easily ported to other Java web application frameworks. -See the full example [here](https://github.com/web-eid/web-eid-spring-boot-example). +## Full example project using the validation library in spring-boot +[example/README.md](example/README.md) ## 1. Add the library to your project @@ -98,7 +99,7 @@ import eu.webeid.security.challenge.ChallengeNonceStore; ## 4. Add trusted certificate authority certificates -You must explicitly specify which **intermediate** certificate authorities (CAs) are trusted to issue the eID authentication and OCSP responder certificates. CA certificates can be loaded from either the truststore file, resources or any stream source. We use the [`CertificateLoader`](https://github.com/web-eid/web-eid-authtoken-validation-java/blob/main/src/main/java/eu/webeid/security/certificate/CertificateLoader.java) helper class to load CA certificates from resources here, but consider using [the truststore file](https://github.com/web-eid/web-eid-spring-boot-example/blob/main/src/main/java/eu/webeid/example/config/ValidationConfiguration.java#L104-L123) instead. +You must explicitly specify which **intermediate** certificate authorities (CAs) are trusted to issue the eID authentication and OCSP responder certificates. CA certificates can be loaded from either the truststore file, resources or any stream source. We use the [`CertificateLoader`](https://github.com/web-eid/web-eid-authtoken-validation-java/blob/main/src/main/java/eu/webeid/security/certificate/CertificateLoader.java) helper class to load CA certificates from resources here, but consider using [the truststore file](./blob/example/main/src/main/java/eu/webeid/example/config/ValidationConfiguration.java#L104-L123) instead. First, copy the trusted certificates, for example `ESTEID2018.cer`, to `resources/cacerts/`, then load the certificates as follows: @@ -137,7 +138,7 @@ import eu.webeid.security.validator.AuthTokenValidatorBuilder; A REST endpoint that issues challenge nonces is required for authentication. The endpoint must support `GET` requests. -In the following example, we are using the [Spring RESTful Web Services framework](https://spring.io/guides/gs/rest-service/) to implement the endpoint, see also the full implementation [here](https://github.com/web-eid/web-eid-spring-boot-example/blob/main/src/main/java/eu/webeid/example/web/rest/ChallengeController.java). +In the following example, we are using the [Spring RESTful Web Services framework](https://spring.io/guides/gs/rest-service/) to implement the endpoint, see also the full implementation [here](example/blob/main/src/main/java/eu/webeid/example/web/rest/ChallengeController.java). ```java import org.springframework.web.bind.annotation.GetMapping; @@ -171,11 +172,11 @@ Authentication consists of calling the `validate()` method of the authentication When using [Spring Security](https://spring.io/guides/topicals/spring-security-architecture) with standard cookie-based authentication, -- implement a custom authentication provider that uses the authentication token validator for authentication as shown [here](https://github.com/web-eid/web-eid-spring-boot-example/blob/main/src/main/java/eu/webeid/example/security/AuthTokenDTOAuthenticationProvider.java), -- implement an AJAX authentication processing filter that extracts the authentication token and passes it to the authentication manager as shown [here](https://github.com/web-eid/web-eid-spring-boot-example/blob/main/src/main/java/eu/webeid/example/security/WebEidAjaxLoginProcessingFilter.java), -- configure the authentication provider and authentication processing filter in the application configuration as shown [here](https://github.com/web-eid/web-eid-spring-boot-example/blob/main/src/main/java/eu/webeid/example/config/ApplicationConfiguration.java). +- implement a custom authentication provider that uses the authentication token validator for authentication as shown [here](example/blob/main/src/main/java/eu/webeid/example/security/AuthTokenDTOAuthenticationProvider.java), +- implement an AJAX authentication processing filter that extracts the authentication token and passes it to the authentication manager as shown [here](example/blob/main/src/main/java/eu/webeid/example/security/WebEidAjaxLoginProcessingFilter.java), +- configure the authentication provider and authentication processing filter in the application configuration as shown [here](example/blob/main/src/main/java/eu/webeid/example/config/ApplicationConfiguration.java). -The gist of the validation is [in the `authenticate()` method](https://github.com/web-eid/web-eid-spring-boot-example/blob/main/src/main/java/eu/webeid/example/security/AuthTokenDTOAuthenticationProvider.java#L74-L76) of the authentication provider: +The gist of the validation is [in the `authenticate()` method](example/blob/main/src/main/java/eu/webeid/example/security/AuthTokenDTOAuthenticationProvider.java#L74-L76) of the authentication provider: ```java try { diff --git a/example/.github/workflows/maven-build.yml b/example/.github/workflows/maven-build.yml deleted file mode 100644 index be61680c..00000000 --- a/example/.github/workflows/maven-build.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Maven build - -on: [ push, pull_request ] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - - name: Cache Maven packages - uses: actions/cache@v1 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-v8-${{ secrets.CACHE_VERSION }}-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-m2-v8-${{ secrets.CACHE_VERSION }} - - - name: Build - run: mvn --batch-mode compile - - - name: Test and package - run: mvn --batch-mode package diff --git a/example/LICENSE b/example/LICENSE index 1d8f1fda..326ac324 100644 --- a/example/LICENSE +++ b/example/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2022 Estonian Information System Authority +Copyright (c) 2020-2023 Estonian Information System Authority Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/example/README.md b/example/README.md index 55049e77..f0e66519 100644 --- a/example/README.md +++ b/example/README.md @@ -17,7 +17,7 @@ Web eID only works over a HTTPS connection with a trusted HTTPS certificate. You can either setup a reverse HTTPS proxy during development or, alternatively, configure HTTPS support directly in the bundled web server. HTTPS configuration is described in more detail in section _[HTTPS support](#https-support)_ below. -You can use, for example, [_ngrok_](https://ngrok.com/) to get a reverse HTTPS proxy. Download _ngrok_ and run it in a terminal window by providing the protocol and Spring Boot application port arguments as follows: +You can use solutions like [_ngrok_](https://ngrok.com/), [_localtunnel_](https://theboroer.github.io/localtunnel-www/), or any other reverse HTTPS proxy tool. For example, with _ngrok_, download and run it in a terminal window by providing the protocol and the Spring Boot application port arguments as follows: ngrok http 8080 @@ -33,9 +33,11 @@ web-eid-auth-token: local-origin: "https://<>" ``` +**Note that the origin URL must not end with a slash `/`**. + ### 3. Configure the trusted certificate authority certificates -The algorithm, which performs the validation of the Web eID authentication token, needs to know which intermediate certificate authorities (CA) are trusted to issue the eID authentication certificates. CA certificates are loaded either from `.cer` files in the profile-specific subdirectory of the [`certs`resource directory](src/main/resources/certs) or the [truststore file](src/main/resources/certs/prod/trusted_certificates.jks). By default, Estonian eID test CA certificates are included in the `dev` profile and production CA certificates in the `prod` profile. +The algorithm, which performs the validation of the Web eID authentication token, needs to know which intermediate certificate authorities (CA) are trusted to issue the eID authentication certificates. CA certificates are loaded either from `.cer` files in the profile-specific subdirectory of the [`certs` resource directory](src/main/resources/certs) or the [truststore file](src/main/resources/certs/prod/trusted_certificates.jks). By default, Estonian eID test CA certificates are included in the `dev` profile and production CA certificates in the `prod` profile. In case you need to provide your own CA certificates, either add the `.cer` files to the `src/main/resources/certs/{dev,prod}` profile-specific directory or add the certificates to the truststore file. @@ -49,7 +51,7 @@ You can specify the profile as a command-line argument to the Maven wrapper comm ### 5. Run the application -Spring Boot web applications can be run from the command-line. You need to have the Java Development Kit 8 installed for building the application package and running the application. +Spring Boot web applications can be run from the command-line. You need to have the Java Development Kit 17 installed for building the application package and running the application. Build and run the application with the following command in a terminal window: @@ -108,7 +110,7 @@ There is also a Docker Compose configuration file `docker-compose.yml` in the ro The source code folder `src` contains the application source code and resources in the `main` subdirectory and tests in the `test` subdirectory. -The `src/main/java/org/webeid/example` directory contains the Spring Boot application Java class and the following subdirectories: +The `src/main/java/eu/webeid/example` directory contains the Spring Boot application Java class and the following subdirectories: - `config`: Spring and HTTP security configuration, Web eID authentication token validation library configuration, trusted CA certificates loading etc, - `security`: Web eID authentication token validation library integration with Spring Security via an `AuthenticationProvider` and `AuthenticationProcessingFilter`, @@ -142,13 +144,13 @@ Spring Security has CSRF protection enabled by default. Web eID requires CSRF pr ### Integration with Web eID components -Detailed overview of Java code changes required for integrating Web eID authentication token validation is available in the [_web-eid-authtoken-validation-java_ library README](https://github.com/web-eid/web-eid-authtoken-validation-java/blob/main/README.md). There are instructions for configuring the nonce generator, trusted certificate authority certificates, authentication token validator, Spring Security authentication integration and REST endpoints. The corresponding Java code is in the `src/main/java/org/webeid/example/{config,security,web/rest}` directories. +Detailed overview of Java code changes required for integrating Web eID authentication token validation is available in the [_web-eid-authtoken-validation-java_ library README](https://github.com/web-eid/web-eid-authtoken-validation-java/blob/main/README.md). There are instructions for configuring the nonce generator, trusted certificate authority certificates, authentication token validator, Spring Security authentication integration and REST endpoints. The corresponding Java code is in the `src/main/java/eu/webeid/example/{config,security,web/rest}` directories. A similar overview of JavaScript and HTML code changes required for authentication and digital signing with Web eID is available in the [web-eid.js library README](https://github.com/web-eid/web-eid.js/blob/main/README.md). The corresponding JavaScript and HTML code is in the `src/resources/{static,templates}` directories. ### Integration with DigiDoc4j components -Java code examples that show how to create and sign data containers that hold signed file objects and digital signatures is available in the [DigiDoc4j wiki](https://github.com/open-eid/digidoc4j/wiki/Examples-of-using-it). Further information and links to the API documentation is available in the project [README](https://github.com/open-eid/digidoc4j/blob/master/README.md). The corresponding Java code is in the `src/main/java/org/webeid/example/{service,web/rest}` directories. +Java code examples that show how to create and sign data containers that hold signed file objects and digital signatures is available in the [DigiDoc4j wiki](https://github.com/open-eid/digidoc4j/wiki/Examples-of-using-it). Further information and links to the API documentation is available in the project [README](https://github.com/open-eid/digidoc4j/blob/master/README.md). The corresponding Java code is in the `src/main/java/eu/webeid/example/{service,web/rest}` directories. #### Using the Certificates' _Authority Information Access_ (AIA) extension in DigiDoc4j diff --git a/example/docker-compose.yml b/example/docker-compose.yml index c7231bf7..2303e15a 100644 --- a/example/docker-compose.yml +++ b/example/docker-compose.yml @@ -1,7 +1,7 @@ version: '2' services: web-eid-springboot-example: - image: web-eid-springboot-example:2.0.0-SNAPSHOT + image: web-eid-springboot-example:3.1.1 restart: always environment: JAVA_TOOL_OPTIONS: '-Dspring.profiles.active=prod' diff --git a/example/pom.xml b/example/pom.xml index f16f38cd..55bb5092 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -5,26 +5,24 @@ org.springframework.boot spring-boot-starter-parent - 2.7.7 + 3.4.4 - org.webeid.example + eu.webeid.example web-eid-springboot-example - 2.0.0-SNAPSHOT + 3.1.1 web-eid-springboot-example - Example Spring Boot project that demonstrates how to use Web eID for authentication and digital + Example Spring Boot application that demonstrates how to use Web eID for authentication and digital signing - 1.8 - 2.22.1 - 2.8.5 - 2.1.1 - 4.3.0 - 31.1-jre - 4.10.0 + 17 + 3.5.2 + 3.1.1 + 6.0.0 1.44 + 3.4.5 @@ -34,59 +32,37 @@ org.springframework.boot - spring-boot-starter-validation + spring-boot-starter-security org.springframework.boot spring-boot-starter-thymeleaf - - org.springframework.boot - spring-boot-starter-security - - - org.springframework.security - spring-security-config - - - - com.google.guava - guava - ${guava.version} - - - com.squareup.okhttp3 - okhttp - ${okhttp.version} - org.digidoc4j digidoc4j ${digidoc4j.version} + - org.webeid.security + eu.webeid.security authtoken-validation ${webeid.version} - - org.springframework.boot - spring-boot-devtools - true - - org.springframework.boot spring-boot-starter-test test - - - org.junit.vintage - junit-vintage-engine - - org.springframework.security @@ -118,6 +94,16 @@ true + + com.google.cloud.tools + jib-maven-plugin + ${jib.version} + + + eclipse-temurin:${java.version}-jre-jammy + + + @@ -143,14 +129,8 @@ gitlab https://gitlab.com/api/v4/projects/19948337/packages/maven - - true - - - true - - diff --git a/example/src/main/java/eu/webeid/example/WebEidSpringbootExampleApplication.java b/example/src/main/java/eu/webeid/example/WebEidSpringbootExampleApplication.java index 8336b75f..5fe5195a 100644 --- a/example/src/main/java/eu/webeid/example/WebEidSpringbootExampleApplication.java +++ b/example/src/main/java/eu/webeid/example/WebEidSpringbootExampleApplication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/example/src/main/java/eu/webeid/example/config/ApplicationConfiguration.java b/example/src/main/java/eu/webeid/example/config/ApplicationConfiguration.java index d29add33..1728628b 100644 --- a/example/src/main/java/eu/webeid/example/config/ApplicationConfiguration.java +++ b/example/src/main/java/eu/webeid/example/config/ApplicationConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,12 +24,14 @@ import eu.webeid.example.security.AuthTokenDTOAuthenticationProvider; import eu.webeid.example.security.WebEidAjaxLoginProcessingFilter; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; @@ -37,42 +39,21 @@ @Configuration @EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true) -public class ApplicationConfiguration extends WebSecurityConfigurerAdapter implements WebMvcConfigurer { - final AuthTokenDTOAuthenticationProvider authTokenDTOAuthenticationProvider; - - public ApplicationConfiguration(AuthTokenDTOAuthenticationProvider authTokenDTOAuthenticationProvider) { - this.authTokenDTOAuthenticationProvider = authTokenDTOAuthenticationProvider; - } - - @Override - protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) { - authenticationManagerBuilder.authenticationProvider(authTokenDTOAuthenticationProvider); +@EnableMethodSecurity(securedEnabled = true) +public class ApplicationConfiguration implements WebMvcConfigurer { + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http, AuthTokenDTOAuthenticationProvider authTokenDTOAuthenticationProvider, AuthenticationConfiguration authConfig) throws Exception { + return http + .authenticationProvider(authTokenDTOAuthenticationProvider) + .addFilterBefore(new WebEidAjaxLoginProcessingFilter("/auth/login", authConfig.getAuthenticationManager()), + UsernamePasswordAuthenticationFilter.class) + .logout(logout -> logout.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())) + .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)) + .build(); } @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .addFilterBefore( - new WebEidAjaxLoginProcessingFilter("/auth/login", authenticationManager()), - UsernamePasswordAuthenticationFilter.class) - .authorizeRequests() - .antMatchers("/auth/challenge", "/auth/login", "/") - .permitAll() - .antMatchers("/welcome") - .authenticated() - .and() - .logout() - .logoutUrl("/logout") - .deleteCookies("JSESSIONID") - .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()) - .and() - .headers() - .frameOptions().sameOrigin(); - // @formatter:on - } - public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); registry.addViewController("/welcome").setViewName("welcome"); diff --git a/example/src/main/java/eu/webeid/example/config/SameSiteCookieConfiguration.java b/example/src/main/java/eu/webeid/example/config/SameSiteCookieConfiguration.java index 4803cf99..74602523 100644 --- a/example/src/main/java/eu/webeid/example/config/SameSiteCookieConfiguration.java +++ b/example/src/main/java/eu/webeid/example/config/SameSiteCookieConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/example/src/main/java/eu/webeid/example/config/SessionBackedChallengeNonceStore.java b/example/src/main/java/eu/webeid/example/config/SessionBackedChallengeNonceStore.java index c9021caf..2d57e1f5 100644 --- a/example/src/main/java/eu/webeid/example/config/SessionBackedChallengeNonceStore.java +++ b/example/src/main/java/eu/webeid/example/config/SessionBackedChallengeNonceStore.java @@ -1,11 +1,32 @@ +/* + * Copyright (c) 2020-2025 Estonian Information System Authority + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + package eu.webeid.example.config; -import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.ObjectFactory; import eu.webeid.security.challenge.ChallengeNonce; import eu.webeid.security.challenge.ChallengeNonceStore; -import javax.servlet.http.HttpSession; +import jakarta.servlet.http.HttpSession; public class SessionBackedChallengeNonceStore implements ChallengeNonceStore { @@ -29,7 +50,6 @@ public ChallengeNonce getAndRemoveImpl() { return challengeNonce; } - @NotNull private HttpSession currentSession() { return httpSessionFactory.getObject(); } diff --git a/example/src/main/java/eu/webeid/example/config/ValidationConfiguration.java b/example/src/main/java/eu/webeid/example/config/ValidationConfiguration.java index 4fcc5056..3e36793d 100644 --- a/example/src/main/java/eu/webeid/example/config/ValidationConfiguration.java +++ b/example/src/main/java/eu/webeid/example/config/ValidationConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,7 +37,7 @@ import eu.webeid.security.validator.AuthTokenValidator; import eu.webeid.security.validator.AuthTokenValidatorBuilder; -import javax.servlet.http.HttpSession; +import jakarta.servlet.http.HttpSession; import java.io.IOException; import java.io.InputStream; import java.net.URI; @@ -126,15 +126,11 @@ public X509Certificate[] loadTrustedCACertificatesFromTrustStore() { @Bean public AuthTokenValidator validator() { try { - AuthTokenValidatorBuilder validatorBuilder = new AuthTokenValidatorBuilder() + return new AuthTokenValidatorBuilder() .withSiteOrigin(URI.create(yamlConfig().getLocalOrigin())) .withTrustedCertificateAuthorities(loadTrustedCACertificatesFromCerFiles()) - .withTrustedCertificateAuthorities(loadTrustedCACertificatesFromTrustStore()); - if (activeProfile.equals("dev")) { - // Enable support for ESTEID 2015 test certificates in development profile. - validatorBuilder = validatorBuilder.withNonceDisabledOcspUrls(URI.create("http://aia.demo.sk.ee/esteid2015")); - } - return validatorBuilder.build(); + .withTrustedCertificateAuthorities(loadTrustedCACertificatesFromTrustStore()) + .build(); } catch (JceException e) { throw new RuntimeException("Error building the Web eID auth token validator.", e); } diff --git a/example/src/main/java/eu/webeid/example/config/YAMLConfig.java b/example/src/main/java/eu/webeid/example/config/YAMLConfig.java index 5c874ef5..234a8569 100644 --- a/example/src/main/java/eu/webeid/example/config/YAMLConfig.java +++ b/example/src/main/java/eu/webeid/example/config/YAMLConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/example/src/main/java/eu/webeid/example/security/AuthTokenDTOAuthenticationProvider.java b/example/src/main/java/eu/webeid/example/security/AuthTokenDTOAuthenticationProvider.java index 8cc05ac4..274a47bf 100644 --- a/example/src/main/java/eu/webeid/example/security/AuthTokenDTOAuthenticationProvider.java +++ b/example/src/main/java/eu/webeid/example/security/AuthTokenDTOAuthenticationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,9 +23,12 @@ package eu.webeid.example.security; import eu.webeid.example.security.dto.AuthTokenDTO; +import eu.webeid.security.authtoken.WebEidAuthToken; +import eu.webeid.security.challenge.ChallengeNonceStore; +import eu.webeid.security.exceptions.AuthTokenException; +import eu.webeid.security.validator.AuthTokenValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.core.Authentication; @@ -34,15 +37,9 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.stereotype.Component; -import eu.webeid.security.authtoken.WebEidAuthToken; -import eu.webeid.security.challenge.ChallengeNonceStore; -import eu.webeid.security.exceptions.AuthTokenException; -import eu.webeid.security.validator.AuthTokenValidator; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -56,10 +53,13 @@ public class AuthTokenDTOAuthenticationProvider implements AuthenticationProvide private static final Logger LOG = LoggerFactory.getLogger(AuthTokenDTOAuthenticationProvider.class); - @Autowired - private AuthTokenValidator tokenValidator; - @Autowired - private ChallengeNonceStore challengeNonceStore; + private final AuthTokenValidator tokenValidator; + private final ChallengeNonceStore challengeNonceStore; + + public AuthTokenDTOAuthenticationProvider(AuthTokenValidator tokenValidator, ChallengeNonceStore challengeNonceStore) { + this.tokenValidator = tokenValidator; + this.challengeNonceStore = challengeNonceStore; + } @Override public Authentication authenticate(Authentication auth) throws AuthenticationException { diff --git a/example/src/main/java/eu/webeid/example/security/WebEidAjaxLoginProcessingFilter.java b/example/src/main/java/eu/webeid/example/security/WebEidAjaxLoginProcessingFilter.java index 0d8ed013..4782ee93 100644 --- a/example/src/main/java/eu/webeid/example/security/WebEidAjaxLoginProcessingFilter.java +++ b/example/src/main/java/eu/webeid/example/security/WebEidAjaxLoginProcessingFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,13 +23,14 @@ package eu.webeid.example.security; import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import com.fasterxml.jackson.databind.ObjectReader; import eu.webeid.example.security.ajax.AjaxAuthenticationFailureHandler; import eu.webeid.example.security.ajax.AjaxAuthenticationSuccessHandler; import eu.webeid.example.security.dto.AuthTokenDTO; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpMethod; @@ -37,25 +38,35 @@ import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; +import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy; +import org.springframework.security.web.context.HttpSessionSecurityContextRepository; +import org.springframework.security.web.context.SecurityContextRepository; + +import java.io.IOException; public class WebEidAjaxLoginProcessingFilter extends AbstractAuthenticationProcessingFilter { private static final Logger LOG = LoggerFactory.getLogger(WebEidAjaxLoginProcessingFilter.class); + private final ObjectReader OBJECT_READER = new ObjectMapper().readerFor(AuthTokenDTO.class); + private final SecurityContextRepository securityContextRepository; public WebEidAjaxLoginProcessingFilter( - String defaultFilterProcessesUrl, - AuthenticationManager authenticationManager + String defaultFilterProcessesUrl, + AuthenticationManager authenticationManager ) { super(defaultFilterProcessesUrl); this.setAuthenticationManager(authenticationManager); this.setAuthenticationSuccessHandler(new AjaxAuthenticationSuccessHandler()); this.setAuthenticationFailureHandler(new AjaxAuthenticationFailureHandler()); + setSessionAuthenticationStrategy(new SessionFixationProtectionStrategy()); + this.securityContextRepository = new HttpSessionSecurityContextRepository(); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) - throws AuthenticationException, IOException { + throws AuthenticationException, IOException { if (!HttpMethod.POST.name().equals(request.getMethod())) { LOG.warn("HttpMethod not supported: {}", request.getMethod()); throw new AuthenticationServiceException("HttpMethod not supported: " + request.getMethod()); @@ -67,11 +78,16 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ } LOG.info("attemptAuthentication(): Reading request body"); - final ObjectMapper objectMapper = new ObjectMapper(); - final AuthTokenDTO authTokenDTO = objectMapper.readValue(request.getReader(), AuthTokenDTO.class); + final AuthTokenDTO authTokenDTO = OBJECT_READER.readValue(request.getReader()); LOG.info("attemptAuthentication(): Creating token"); final PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken(null, authTokenDTO); LOG.info("attemptAuthentication(): Calling authentication manager"); return getAuthenticationManager().authenticate(token); } + + @Override + protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { + super.successfulAuthentication(request, response, chain, authResult); + securityContextRepository.saveContext(SecurityContextHolder.getContext(), request, response); + } } diff --git a/example/src/main/java/eu/webeid/example/security/WebEidAuthentication.java b/example/src/main/java/eu/webeid/example/security/WebEidAuthentication.java index c9966980..5ba3ebf7 100644 --- a/example/src/main/java/eu/webeid/example/security/WebEidAuthentication.java +++ b/example/src/main/java/eu/webeid/example/security/WebEidAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,15 +22,16 @@ package eu.webeid.example.security; +import eu.webeid.security.certificate.CertificateData; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; -import eu.webeid.security.certificate.CertificateData; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.List; import java.util.Objects; +import java.util.Optional; public class WebEidAuthentication extends PreAuthenticatedAuthenticationToken implements Authentication { @@ -38,7 +39,8 @@ public class WebEidAuthentication extends PreAuthenticatedAuthenticationToken im public static Authentication fromCertificate(X509Certificate userCertificate, List authorities) throws CertificateEncodingException { final String principalName = getPrincipalNameFromCertificate(userCertificate); - final String idCode = Objects.requireNonNull(CertificateData.getSubjectIdCode(userCertificate)); + final String idCode = CertificateData.getSubjectIdCode(userCertificate) + .orElseThrow(() -> new CertificateEncodingException("Certificate does not contain subject ID code")); return new WebEidAuthentication(principalName, idCode, authorities); } @@ -52,13 +54,27 @@ private WebEidAuthentication(String principalName, String idCode, List givenName = CertificateData.getSubjectGivenName(userCertificate); + final Optional surname = CertificateData.getSubjectSurname(userCertificate); + + if (givenName.isPresent() && surname.isPresent()) { + return givenName.get() + ' ' + surname.get(); + } else { // Organization certificates do not have given name and surname fields. - return Objects.requireNonNull(CertificateData.getSubjectCN(userCertificate)); + return CertificateData.getSubjectCN(userCertificate) + .orElseThrow(() -> new CertificateEncodingException("Certificate does not contain subject CN")); } } + @Override + public boolean equals(Object o) { + if (!super.equals(o)) return false; + WebEidAuthentication that = (WebEidAuthentication) o; + return Objects.equals(idCode, that.idCode); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), idCode); + } } diff --git a/example/src/main/java/eu/webeid/example/security/ajax/AjaxAuthenticationFailureHandler.java b/example/src/main/java/eu/webeid/example/security/ajax/AjaxAuthenticationFailureHandler.java index a21e7e9d..1bec05fd 100644 --- a/example/src/main/java/eu/webeid/example/security/ajax/AjaxAuthenticationFailureHandler.java +++ b/example/src/main/java/eu/webeid/example/security/ajax/AjaxAuthenticationFailureHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,9 +27,9 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; import java.io.IOException; public class AjaxAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/example/src/main/java/eu/webeid/example/security/ajax/AjaxAuthenticationSuccessHandler.java b/example/src/main/java/eu/webeid/example/security/ajax/AjaxAuthenticationSuccessHandler.java index 4567db7a..a5ea20d0 100644 --- a/example/src/main/java/eu/webeid/example/security/ajax/AjaxAuthenticationSuccessHandler.java +++ b/example/src/main/java/eu/webeid/example/security/ajax/AjaxAuthenticationSuccessHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,19 +25,17 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import com.fasterxml.jackson.databind.ObjectWriter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; import org.springframework.stereotype.Component; +import java.io.IOException; + /** * Write custom response on having user successfully authenticated. *

@@ -50,11 +48,11 @@ public class AjaxAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuc @Override public void onAuthenticationSuccess( - HttpServletRequest request, - HttpServletResponse response, - Authentication authentication + HttpServletRequest request, + HttpServletResponse response, + Authentication authentication ) - throws IOException { + throws IOException { LOG.info("onAuthenticationSuccess(): {}", authentication); response.setStatus(HttpServletResponse.SC_OK); @@ -64,23 +62,19 @@ public void onAuthenticationSuccess( } public static class AuthSuccessDTO { - private final ObjectMapper objectMapper = new ObjectMapper(); + private static final ObjectWriter OBJECT_WRITER = new ObjectMapper().writerFor(AuthSuccessDTO.class); @JsonProperty("sub") private String sub; @JsonProperty("auth") - private List auth; + private String auth; public static String asJson(Authentication authentication) throws JsonProcessingException { final AuthSuccessDTO dto = new AuthSuccessDTO(); dto.sub = authentication.getName(); - dto.auth = convertAuthorities(authentication.getAuthorities()); - return dto.objectMapper.writeValueAsString(dto); - } - - private static List convertAuthorities(Collection authorities) { - return authorities.stream().map(GrantedAuthority::toString).collect(Collectors.toList()); + dto.auth = authentication.getAuthorities().toString(); + return OBJECT_WRITER.writeValueAsString(dto); } } } diff --git a/example/src/main/java/eu/webeid/example/security/dto/AuthTokenDTO.java b/example/src/main/java/eu/webeid/example/security/dto/AuthTokenDTO.java index a2f4b01f..73a70a4e 100644 --- a/example/src/main/java/eu/webeid/example/security/dto/AuthTokenDTO.java +++ b/example/src/main/java/eu/webeid/example/security/dto/AuthTokenDTO.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/example/src/main/java/eu/webeid/example/service/SigningService.java b/example/src/main/java/eu/webeid/example/service/SigningService.java index 80e7fc62..ddb3bd2a 100644 --- a/example/src/main/java/eu/webeid/example/service/SigningService.java +++ b/example/src/main/java/eu/webeid/example/service/SigningService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,43 +22,53 @@ package eu.webeid.example.service; -import com.google.common.io.ByteStreams; import eu.webeid.example.config.YAMLConfig; import eu.webeid.example.security.WebEidAuthentication; import eu.webeid.example.service.dto.CertificateDTO; import eu.webeid.example.service.dto.DigestDTO; import eu.webeid.example.service.dto.FileDTO; import eu.webeid.example.service.dto.SignatureDTO; +import eu.webeid.security.certificate.CertificateData; +import jakarta.servlet.http.HttpSession; +import jakarta.xml.bind.DatatypeConverter; import org.apache.commons.io.FilenameUtils; -import org.digidoc4j.*; +import org.digidoc4j.Configuration; +import org.digidoc4j.Container; +import org.digidoc4j.ContainerBuilder; +import org.digidoc4j.DataFile; +import org.digidoc4j.DataToSign; +import org.digidoc4j.DigestAlgorithm; +import org.digidoc4j.Signature; +import org.digidoc4j.SignatureBuilder; +import org.digidoc4j.SignatureProfile; import org.digidoc4j.utils.TokenAlgorithmSupport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.ObjectFactory; import org.springframework.core.io.ByteArrayResource; +import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Service; -import eu.webeid.example.web.rest.SigningController; -import eu.webeid.security.certificate.CertificateData; -import javax.servlet.http.HttpSession; -import javax.xml.bind.DatatypeConverter; import java.io.IOException; -import java.security.MessageDigest; +import java.io.InputStream; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Objects; +import static eu.webeid.example.security.AuthTokenDTOAuthenticationProvider.ROLE_USER; + @Service +@Secured(ROLE_USER) public class SigningService { private static final String SESSION_ATTR_FILE = "file-to-sign"; private static final String SESSION_ATTR_CONTAINER = "container-to-sign"; private static final String SESSION_ATTR_DATA = "data-to-sign"; - private static final Logger LOG = LoggerFactory.getLogger(SigningController.class); + private static final Logger LOG = LoggerFactory.getLogger(SigningService.class); private final Configuration signingConfiguration; - ObjectFactory httpSessionFactory; + private final ObjectFactory httpSessionFactory; public SigningService(ObjectFactory httpSessionFactory, YAMLConfig yamlConfig) { this.httpSessionFactory = httpSessionFactory; @@ -80,40 +90,48 @@ private HttpSession currentSession() { * @return data to be signed */ public DigestDTO prepareContainer(CertificateDTO certificateDTO, WebEidAuthentication authentication) throws CertificateException, NoSuchAlgorithmException, IOException { - X509Certificate certificate = certificateDTO.toX509Certificate(); - if (!authentication.getIdCode().equals(CertificateData.getSubjectIdCode(certificate))) { + final X509Certificate certificate = certificateDTO.toX509Certificate(); + final String signingIdCode = CertificateData.getSubjectIdCode(certificate) + .orElseThrow(() -> new RuntimeException("Certificate does not contain subject ID code")); + if (!signingIdCode.equals(authentication.getIdCode())) { throw new IllegalArgumentException("Authenticated subject ID code differs from " + "signing certificate subject ID code"); } - FileDTO fileDTO = FileDTO.getExampleForSigningFromResources(); - Container containerToSign = getContainerToSign(fileDTO); - String containerName = generateContainerName(fileDTO.getName()); + final FileDTO fileDTO = FileDTO.getExampleForSigningFromResources(); + final Container containerToSign = getContainerToSign(fileDTO); + final String containerName = generateContainerName(fileDTO.getName()); currentSession().setAttribute(SESSION_ATTR_CONTAINER, containerToSign); currentSession().setAttribute(SESSION_ATTR_FILE, fileDTO); LOG.info("Preparing container for signing for file '{}'", containerName); - DataToSign dataToSign = SignatureBuilder + final DigestAlgorithm signatureDigestAlgorithm = TokenAlgorithmSupport.determineSignatureDigestAlgorithm(certificate); + final String digestAlgorithmName = signatureDigestAlgorithm.uri().getRef() + .toUpperCase().replace("SHA", "SHA-"); // SHA256 -> SHA-256 + if (!certificateDTO.getSupportedHashFunctionNames().contains(digestAlgorithmName)) { + throw new IllegalArgumentException("Determined signature digest algorithm '" + digestAlgorithmName + + "' is not supported. Supported algorithms are: " + String.join(", ", certificateDTO.getSupportedHashFunctionNames())); + } + + final DataToSign dataToSign = SignatureBuilder .aSignature(containerToSign) .withSignatureProfile(SignatureProfile.LT) // AIA OCSP is supported for signatures with LT or LTA profile. .withSigningCertificate(certificate) - .withSignatureDigestAlgorithm(TokenAlgorithmSupport.determineSignatureDigestAlgorithm(certificate)) + .withSignatureDigestAlgorithm(signatureDigestAlgorithm) .buildDataToSign(); currentSession().setAttribute(SESSION_ATTR_DATA, dataToSign); LOG.info("Successfully prepared container for signing for file '{}'", containerName); - final String digestAlgorithm = certificateDTO.getSupportedAlgorithmNames().contains("SHA384") ? - "SHA-384" : "SHA-256"; + final byte[] digest = signatureDigestAlgorithm.getDssDigestAlgorithm().getMessageDigest() + .digest(dataToSign.getDataToSign()); - final byte[] digest = MessageDigest.getInstance(digestAlgorithm).digest(dataToSign.getDataToSign()); - - DigestDTO digestDTO = new DigestDTO(); + final DigestDTO digestDTO = new DigestDTO(); digestDTO.setHash(DatatypeConverter.printBase64Binary(digest)); - digestDTO.setHashFunction(digestAlgorithm); + digestDTO.setHashFunction(digestAlgorithmName); return digestDTO; } @@ -145,7 +163,9 @@ public String getContainerName() { public ByteArrayResource getSignedContainerAsResource() throws IOException { Container signedContainer = (Container) Objects.requireNonNull(currentSession().getAttribute(SESSION_ATTR_CONTAINER)); - return new ByteArrayResource(ByteStreams.toByteArray(signedContainer.saveAsStream())); + try (final InputStream stream = signedContainer.saveAsStream()) { + return new ByteArrayResource(stream.readAllBytes()); + } } private Container getContainerToSign(FileDTO fileDTO) { diff --git a/example/src/main/java/eu/webeid/example/service/dto/CertificateDTO.java b/example/src/main/java/eu/webeid/example/service/dto/CertificateDTO.java index 4d80ddec..7704d015 100644 --- a/example/src/main/java/eu/webeid/example/service/dto/CertificateDTO.java +++ b/example/src/main/java/eu/webeid/example/service/dto/CertificateDTO.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,8 +22,6 @@ package eu.webeid.example.service.dto; -import com.fasterxml.jackson.annotation.JsonProperty; - import java.io.ByteArrayInputStream; import java.io.InputStream; import java.security.cert.CertificateException; @@ -62,10 +60,10 @@ public X509Certificate toX509Certificate() throws CertificateException { return (X509Certificate) cf.generateCertificate(inStream); } - public List getSupportedAlgorithmNames() { + public List getSupportedHashFunctionNames() { return supportedSignatureAlgorithms == null ? new ArrayList<>() : supportedSignatureAlgorithms .stream() - .map(SignatureAlgorithmDTO::getHashAlgorithm) + .map(SignatureAlgorithmDTO::getHashFunction) .distinct() .collect(Collectors.toList()); } diff --git a/example/src/main/java/eu/webeid/example/service/dto/ChallengeDTO.java b/example/src/main/java/eu/webeid/example/service/dto/ChallengeDTO.java index 872a2604..4a6b9c93 100644 --- a/example/src/main/java/eu/webeid/example/service/dto/ChallengeDTO.java +++ b/example/src/main/java/eu/webeid/example/service/dto/ChallengeDTO.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/example/src/main/java/eu/webeid/example/service/dto/DigestDTO.java b/example/src/main/java/eu/webeid/example/service/dto/DigestDTO.java index 1b05dba7..c567d708 100644 --- a/example/src/main/java/eu/webeid/example/service/dto/DigestDTO.java +++ b/example/src/main/java/eu/webeid/example/service/dto/DigestDTO.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/example/src/main/java/eu/webeid/example/service/dto/FileDTO.java b/example/src/main/java/eu/webeid/example/service/dto/FileDTO.java index 47a2bcf8..949b358a 100644 --- a/example/src/main/java/eu/webeid/example/service/dto/FileDTO.java +++ b/example/src/main/java/eu/webeid/example/service/dto/FileDTO.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,12 +27,13 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.io.Serializable; import java.net.URI; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Objects; -public class FileDTO { +public class FileDTO implements Serializable { private static final String EXAMPLE_FILENAME = "example-for-signing.txt"; private final String name; diff --git a/example/src/main/java/eu/webeid/example/service/dto/SignatureAlgorithmDTO.java b/example/src/main/java/eu/webeid/example/service/dto/SignatureAlgorithmDTO.java index 142e3930..287682fb 100644 --- a/example/src/main/java/eu/webeid/example/service/dto/SignatureAlgorithmDTO.java +++ b/example/src/main/java/eu/webeid/example/service/dto/SignatureAlgorithmDTO.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,40 +22,61 @@ package eu.webeid.example.service.dto; -import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; public class SignatureAlgorithmDTO { - @JsonProperty("crypto-algo") + // See https://github.com/web-eid/web-eid-app/blob/main/src/controller/command-handlers/signauthutils.cpp#L121-L127 + private static final Set SUPPORTED_CRYPTO_ALGOS = new HashSet<>(Arrays.asList( + "ECC", "RSA" + )); + private static final Set SUPPORTED_PADDING_SCHEMES = new HashSet<>(Arrays.asList( + "NONE", "PKCS1.5", "PSS" + )); + // See https://github.com/web-eid/libelectronic-id/tree/main/src/electronic-id.cpp#L131 + private static final Set SUPPORTED_HASH_FUNCTIONS = new HashSet<>(Arrays.asList( + "SHA-224", "SHA-256", "SHA-384", "SHA-512", + "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512" + )); + private String cryptoAlgorithm; - @JsonProperty("hash-algo") - private String hashAlgorithm; + private String hashFunction; - @JsonProperty("padding-algo") - private String paddingAlgorithm; + private String paddingScheme; public String getCryptoAlgorithm() { return cryptoAlgorithm; } public void setCryptoAlgorithm(String cryptoAlgorithm) { + if (!SUPPORTED_CRYPTO_ALGOS.contains(cryptoAlgorithm)) { + throw new IllegalArgumentException("The provided crypto algorithm is not supported"); + } this.cryptoAlgorithm = cryptoAlgorithm; } - public String getHashAlgorithm() { - return hashAlgorithm; + public String getHashFunction() { + return hashFunction; } - public void setHashAlgorithm(String hashAlgorithm) { - this.hashAlgorithm = hashAlgorithm; + public void setHashFunction(String hashFunction) { + if (!SUPPORTED_HASH_FUNCTIONS.contains(hashFunction)) { + throw new IllegalArgumentException("The provided hash function is not supported"); + } + this.hashFunction = hashFunction; } - public String getPaddingAlgorithm() { - return paddingAlgorithm; + public String getPaddingScheme() { + return paddingScheme; } - public void setPaddingAlgorithm(String paddingAlgorithm) { - this.paddingAlgorithm = paddingAlgorithm; + public void setPaddingScheme(String paddingScheme) { + if (!SUPPORTED_PADDING_SCHEMES.contains(paddingScheme)) { + throw new IllegalArgumentException("The provided padding scheme is not supported"); + } + this.paddingScheme = paddingScheme; } } diff --git a/example/src/main/java/eu/webeid/example/service/dto/SignatureDTO.java b/example/src/main/java/eu/webeid/example/service/dto/SignatureDTO.java index c3df7023..68ffd3b8 100644 --- a/example/src/main/java/eu/webeid/example/service/dto/SignatureDTO.java +++ b/example/src/main/java/eu/webeid/example/service/dto/SignatureDTO.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/example/src/test/java/eu/webeid/example/DateMockingTest.java b/example/src/main/java/eu/webeid/example/web/IndexController.java similarity index 62% rename from example/src/test/java/eu/webeid/example/DateMockingTest.java rename to example/src/main/java/eu/webeid/example/web/IndexController.java index 75513a93..6da1b71a 100644 --- a/example/src/test/java/eu/webeid/example/DateMockingTest.java +++ b/example/src/main/java/eu/webeid/example/web/IndexController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,25 +20,18 @@ * SOFTWARE. */ -package eu.webeid.example; +package eu.webeid.example.web; -import eu.webeid.example.testutil.Dates; -import org.junit.jupiter.api.Test; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; -import java.text.ParseException; -import java.util.Date; - -import static org.assertj.core.api.Assertions.assertThat; - -public class DateMockingTest { - - @Test - void testDateMocking() throws ParseException { - final Date date = Dates.create("2020-04-14T13:36:49Z"); - Dates.setMockedDate(date); - - // Mocking native methods is unreliable, see https://github.com/jmockit/jmockit1/issues/689#issuecomment-702965484 - assertThat(System.currentTimeMillis()).isEqualTo(date.getTime()); +@Controller +public class IndexController { + @GetMapping("/") + public String welcome(Model model, HttpServletRequest request) { + model.addAttribute("serverName", request.getServerName()); + return "index"; } - } diff --git a/example/src/main/java/eu/webeid/example/web/WelcomeController.java b/example/src/main/java/eu/webeid/example/web/WelcomeController.java index 22befa97..bba34c23 100644 --- a/example/src/main/java/eu/webeid/example/web/WelcomeController.java +++ b/example/src/main/java/eu/webeid/example/web/WelcomeController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,23 +24,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; -import javax.validation.constraints.NotNull; import java.security.Principal; +import java.util.Objects; import static eu.webeid.example.security.AuthTokenDTOAuthenticationProvider.ROLE_USER; @Controller +@Secured(ROLE_USER) public class WelcomeController { private static final Logger LOG = LoggerFactory.getLogger(WelcomeController.class); - @PreAuthorize("hasAuthority('" + ROLE_USER + "')") @GetMapping("welcome") - public String welcome(Model model, @NotNull Principal principal) { + public String welcome(Model model, Principal principal) { + Objects.requireNonNull(principal); LOG.info("Showing welcome page, logged in as principal={}", principal.getName()); model.addAttribute("principalName", principal.getName()); return "welcome"; diff --git a/example/src/main/java/eu/webeid/example/web/rest/ChallengeController.java b/example/src/main/java/eu/webeid/example/web/rest/ChallengeController.java index 01eec9df..df54366a 100644 --- a/example/src/main/java/eu/webeid/example/web/rest/ChallengeController.java +++ b/example/src/main/java/eu/webeid/example/web/rest/ChallengeController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,10 +23,10 @@ package eu.webeid.example.web.rest; import eu.webeid.example.service.dto.ChallengeDTO; +import eu.webeid.security.challenge.ChallengeNonceGenerator; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import eu.webeid.security.challenge.ChallengeNonceGenerator; @RestController @RequestMapping("auth") diff --git a/example/src/main/java/eu/webeid/example/web/rest/SigningController.java b/example/src/main/java/eu/webeid/example/web/rest/SigningController.java index 840cde8e..2a1c6529 100644 --- a/example/src/main/java/eu/webeid/example/web/rest/SigningController.java +++ b/example/src/main/java/eu/webeid/example/web/rest/SigningController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,14 +32,22 @@ import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +import org.springframework.security.access.annotation.Secured; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; +import static eu.webeid.example.security.AuthTokenDTOAuthenticationProvider.ROLE_USER; + @RestController @RequestMapping("sign") +@Secured(ROLE_USER) public class SigningController { private final SigningService signingService; diff --git a/example/src/main/resources/application-prod.yaml b/example/src/main/resources/application-prod.yaml index 709d314b..3868f350 100644 --- a/example/src/main/resources/application-prod.yaml +++ b/example/src/main/resources/application-prod.yaml @@ -3,3 +3,6 @@ web-eid-auth-token: use-digidoc4j-prod-configuration: true local-origin: "https://web-eid.eu" truststore-password: "changeit" +spring: + thymeleaf: + cache: true diff --git a/example/src/main/resources/application.properties b/example/src/main/resources/application.properties index cbb42d2a..7d70ac4e 100644 --- a/example/src/main/resources/application.properties +++ b/example/src/main/resources/application.properties @@ -1 +1,2 @@ spring.profiles.active=dev +server.servlet.session.cookie.name=__Host-JSESSIONID \ No newline at end of file diff --git a/example/src/main/resources/certs/dev/TEST_ORG_2021E.cer b/example/src/main/resources/certs/dev/TEST_ORG_2021E.cer new file mode 100644 index 00000000..bf399a95 --- /dev/null +++ b/example/src/main/resources/certs/dev/TEST_ORG_2021E.cer @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDoDCCAwOgAwIBAgIQcyqWqJYuHMpg+S/gNJArMTAKBggqhkjOPQQDAzBuMQsw +CQYDVQQGEwJFRTEbMBkGA1UECgwSU0sgSUQgU29sdXRpb25zIEFTMRcwFQYDVQRh +DA5OVFJFRS0xMDc0NzAxMzEpMCcGA1UEAwwgVEVTVCBvZiBTSyBJRCBTb2x1dGlv +bnMgUk9PVCBHMUUwHhcNMjEwNzIyMDg0NDE2WhcNMzYwNzIyMDg0NDE2WjBvMQsw +CQYDVQQGEwJFRTEbMBkGA1UECgwSU0sgSUQgU29sdXRpb25zIEFTMRcwFQYDVQRh +DA5OVFJFRS0xMDc0NzAxMzEqMCgGA1UEAwwhVEVTVCBvZiBTSyBJRCBTb2x1dGlv +bnMgT1JHIDIwMjFFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEPN17jh+wlx7U0fND +5Vd+xix//r/XXBrK2JPgzXPT3ApkHQwBuMMcRAT3xTZ0UtiRbfo6mClvtZdyEcyf +qw8xUd7rZ/jJHkHE+Ea/5x8sZtgBRRBdga932N40gkRuTfdEo4IBYzCCAV8wHwYD +VR0jBBgwFoAU4hzeY9y++IR+ATsuS4Cx4X/V8eYwHQYDVR0OBBYEFEmnHNBblRgz +FcEe8pie53tLDoZpMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEA +MGwGCCsGAQUFBwEBBGAwXjAiBggrBgEFBQcwAYYWaHR0cDovL2RlbW8uc2suZWUv +b2NzcDA4BggrBgEFBQcwAoYsaHR0cDovL2Muc2suZWUvVEVTVF9TS19ST09UX0cx +XzIwMjFFLmRlci5jcnQwOQYDVR0fBDIwMDAuoCygKoYoaHR0cDovL2Muc2suZWUv +VEVTVF9TS19ST09UX0cxXzIwMjFFLmNybDBQBgNVHSAESTBHMEUGBFUdIAAwPTA7 +BggrBgEFBQcCARYvaHR0cHM6Ly93d3cuc2tpZHNvbHV0aW9ucy5ldS9lbi9yZXBv +c2l0b3J5L0NQUy8wCgYIKoZIzj0EAwMDgYoAMIGGAkFeLgoCd2OgKM/9YM2eizwD +Mdb8DIE2aX9a5czWUXypSa+fA5HXry4oAFqY3ed7TWrgaX+RgD4ejuHDJUN3fVmb +zwJBHI1S8XxeM2+c0YUJQMU1SY2VVcVax6110r1aBDr90RAF2a9H8sKRVYtz21lC +bM/wb9Lg61nkctY91DVjvWMj138= +-----END CERTIFICATE----- diff --git a/example/src/main/resources/certs/dev/TEST_ORG_2021R.cer b/example/src/main/resources/certs/dev/TEST_ORG_2021R.cer new file mode 100644 index 00000000..6eb80913 --- /dev/null +++ b/example/src/main/resources/certs/dev/TEST_ORG_2021R.cer @@ -0,0 +1,39 @@ +-----BEGIN CERTIFICATE----- +MIIGzDCCBLSgAwIBAgIQPadGvT+ZiMRhHPzivWSWBDANBgkqhkiG9w0BAQwFADBu +MQswCQYDVQQGEwJFRTEbMBkGA1UECgwSU0sgSUQgU29sdXRpb25zIEFTMRcwFQYD +VQRhDA5OVFJFRS0xMDc0NzAxMzEpMCcGA1UEAwwgVEVTVCBvZiBTSyBJRCBTb2x1 +dGlvbnMgUk9PVCBHMVIwHhcNMjEwODE4MTIyODE4WhcNMzYwODE4MTIyODE4WjBv +MQswCQYDVQQGEwJFRTEbMBkGA1UECgwSU0sgSUQgU29sdXRpb25zIEFTMRcwFQYD +VQRhDA5OVFJFRS0xMDc0NzAxMzEqMCgGA1UEAwwhVEVTVCBvZiBTSyBJRCBTb2x1 +dGlvbnMgT1JHIDIwMjFSMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA +vRcXPfY+T3pZl0ou0HQ76GEcOSqa8LmktDjFlWRlessGR+A70AiNw1k6s98Ic6wv +u+KUnRSdXCu+QANnkJVr75+W4heWAgJL0aOwDsBRIqn/aFiaW49+7Vw8zdlH6LnU +8YFDTvjy7tgX1ZyqFI9s31MJ84p9YH+DOwEYB8VMdkwa9wVBIu3oDh9hCTVUZtZF +G/yOI0/Tu9eKRbLSK6Je/op2IvEXqZwZVnWpR/yAAfyYOsY6/t9iieCknvQtWXnu +pxMm9HybUoOqHQ6QKz0nTY4As0sDuNom0aVmHeNR7W+ebJtiU8H/zqr+yR46qauD +QSrVqBlKfR7ZGLGPxvW38qfQpoQ2okaR+bUrrAcscJidwT3+0n1+2t4jSX6OTXu2 +HsPjk7dmcrGhTtQh2BcjbhHit+nOS3BuB1QOJ8tXsdj1nsaHPae6ZeH/KbMetBeh +BCwpXcNP3aR+AfVJWzgLObZSrqeCzGsfSfBQvracTjZzJp9NGXTZBe9MzcYomr2d +I7mqt/wa5N6i7eDa75cv+FncGrRKJkQ1JRRPynGcQK/dOVrmjjdeJGf6vgqWP/WI +KTuXYdovCnvXhO+PuOifRiP0scnWN+YXR7R3EXT50rk79lNrOOzcqmft3B2EVsVI +BPJTwjnSiNXZRHSoedOPJEInLQ7sP9uDWbqMd04/yYUCAwEAAaOCAWMwggFfMB8G +A1UdIwQYMBaAFMaIk1tHkln1YUO+2L6I5FaPti5RMB0GA1UdDgQWBBSJNpEi++WV +9vJUbwBlF9+7AA6VxTAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIB +ADBsBggrBgEFBQcBAQRgMF4wIgYIKwYBBQUHMAGGFmh0dHA6Ly9kZW1vLnNrLmVl +L29jc3AwOAYIKwYBBQUHMAKGLGh0dHA6Ly9jLnNrLmVlL1RFU1RfU0tfUk9PVF9H +MV8yMDIxUi5kZXIuY3J0MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jLnNrLmVl +L1RFU1RfU0tfUk9PVF9HMV8yMDIxUi5jcmwwUAYDVR0gBEkwRzBFBgRVHSAAMD0w +OwYIKwYBBQUHAgEWL2h0dHBzOi8vd3d3LnNraWRzb2x1dGlvbnMuZXUvZW4vcmVw +b3NpdG9yeS9DUFMvMA0GCSqGSIb3DQEBDAUAA4ICAQCInhE2mlWOwF5ZgXEgBP4G +rVAp7SLyqOoeeIB1PkTX9zZTN7zm+G1T9jYBYAbskIKsIQYz8Rg/HaXkg1MDl1lf +7M9CYbWTZanOPzSfAUS1u49pnyKr74DIRCo2bdD4e2ofS5y/uMu3qE1wClzO6TJo +oJtX1PGTptqKclZywxAVeoCisT1f48PW6dq0b5i6LTtDTDSSKGUgvdm18af0TSMn +kozsxIWzY06TmDfJvlPB12h8vIlzBZXHoVH89wBtffV1uVpc8btyZqqYnqPivXSM +clQMuTmJSZjZoOQ695JqN92kSy8aDc9Bxqb+XsBmmjr26nvvW54y68TUZSz1D29n +eBPy0DB60ZAFRgtyfanlPZL8KymBan45u88rE5S3GOl0kbkYOmsIoCv4BHILxlQl +ddFY+BGkDwM8bEQ480AERTXcp+4rXUj80kXIsa5NR5z2+LaDvy2j3tVcY7iRkdIU +nVWYwxEEgU0dbzxl+LlSx/ad9dGzbhvhsEiq93jz2qJdpsC6EiBlBGCRyfwEgv8a +CqDTAJNqnY3+UzTzYds1HlMfxSyzoi01zyfN4DtWl2RTCslBZ0/XLnn4HaTSU5Bq +wESseW9CPJRaO+W3ERsSRAW9tjDuEuBxWAN91OWlkk6GpLJkr3/4UcO85pVgNJf3 +Q4sZkdHlzV6yY/Cq1S+b9Q== +-----END CERTIFICATE----- diff --git a/example/src/main/resources/certs/dev/TEST_of_ESTEID-SK_2015.cer b/example/src/main/resources/certs/dev/TEST_of_ESTEID-SK_2015.cer deleted file mode 100644 index 7749286c..00000000 Binary files a/example/src/main/resources/certs/dev/TEST_of_ESTEID-SK_2015.cer and /dev/null differ diff --git a/example/src/main/resources/certs/dev/TestESTEID2025.cer b/example/src/main/resources/certs/dev/TestESTEID2025.cer new file mode 100644 index 00000000..ca8933f1 --- /dev/null +++ b/example/src/main/resources/certs/dev/TestESTEID2025.cer @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMTCCAregAwIBAgIUNtXxgsJYFy9r5Opm2j2LcsnZYtkwCgYIKoZIzj0EAwMw +XTEZMBcGA1UEAwwQVGVzdCBFRUdvdkNBMjAyNTEXMBUGA1UEYQwOTlRSRUUtMTcw +NjYwNDkxGjAYBgNVBAoMEVpldGVzIEVzdG9uaWEgT8OcMQswCQYDVQQGEwJFRTAe +Fw0yNDExMDQxMjU5NTVaFw0zOTExMDMxMjU5NTRaMFwxGDAWBgNVBAMMD1Rlc3Qg +RVNURUlEMjAyNTEXMBUGA1UEYQwOTlRSRUUtMTcwNjYwNDkxGjAYBgNVBAoMEVpl +dGVzIEVzdG9uaWEgT8OcMQswCQYDVQQGEwJFRTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABC8Uc5s70j1iWMZNbQyVYpDmwp4Ad5HlQmFB9noY2yBeDKL2KHKQG31SDTbo +KlBz7JUWsmaxF1Vj6ZkKAwcltO2cBnEU1B5H8hWgk5Un61GZxhX2wPkwJLm7vjyi +dKmftqOCATcwggEzMBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAU4Vbf +rsSXORfv3goMbOVys4vVchAwSQYIKwYBBQUHAQEEPTA7MDkGCCsGAQUFBzAChi1o +dHRwOi8vY3J0LXRlc3QuZWlkcGtpLmVlL3Rlc3RFRUdvdkNBMjAyNS5jcnQwQgYD +VR0gBDswOTA3BgRVHSAAMC8wLQYIKwYBBQUHAgEWIWh0dHBzOi8vcmVwb3NpdG9y +eS10ZXN0LmVpZHBraS5lZTA+BgNVHR8ENzA1MDOgMaAvhi1odHRwOi8vY3JsLXRl +c3QuZWlkcGtpLmVlL3Rlc3RFRUdvdkNBMjAyNS5jcmwwHQYDVR0OBBYEFO7ylT+M +svxRnoTm5l6EEX5CuiA2MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBl +AjEA3qECw4GIfbeoC5cFhtiPJRfFlzsjRGVBtQTH6DNbZsm+EF6Gc28/iZFX1H6n +UTRlAjAiwooqEyVbxA1KqT6PwVl1BXNbF59j6MaiNR43dYeJxrdOnxleR50EVdIC +DJFEm2E= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/example/src/main/resources/certs/dev/eID-TEST-EC-Citizen-CA.cer b/example/src/main/resources/certs/dev/eID-TEST-EC-Citizen-CA.cer new file mode 100644 index 00000000..06456b7a --- /dev/null +++ b/example/src/main/resources/certs/dev/eID-TEST-EC-Citizen-CA.cer @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKTCCAq+gAwIBAgIIcND8I1qptLUwCgYIKoZIzj0EAwMwKzELMAkGA1UEBhMC +QkUxHDAaBgNVBAMME2VJRCBURVNUIEVDIFJvb3QgQ0EwIBcNMDcwNDMwMjIwMDIw +WhgPMjA4NzA0MTAyMjAwMjBaMC4xCzAJBgNVBAYTAkJFMR8wHQYDVQQDDBZlSUQg +VEVTVCBFQyBDaXRpemVuIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEJAiNoOQf +Y0r8N6JVPMLedXyRZ7MwppGwQ9ZxFzLjVsbeKuUvqEFR0yKKyEidXc875m4UF5lR +pf/FSWagg2IXGWrypnRZkgnNVP6s5W2LzKdV09hd6v7O8j/8knfHOj+No4IBmTCC +AZUwHQYDVR0OBBYEFN2zf+OaGY5ZyRFWAi31+p1v3oRLMB8GA1UdIwQYMBaAFCHA +clfKHAQEGR3ZjH4+tYPrrBwCMA4GA1UdDwEB/wQEAwIBBjBIBgNVHSAEQTA/MD0G +BmA4DAEBAjAzMDEGCCsGAQUFBwIBFiVodHRwOi8vZWlkZGV2Y2FyZHMuemV0ZXNj +YXJkcy5iZS9jZXJ0MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDBCBgNV +HR8EOzA5MDegNaAzhjFodHRwOi8vZWlkZGV2Y2FyZHMuemV0ZXNjYXJkcy5iZS9j +cmwvcm9vdGNhRUMuY3JsMIGBBggrBgEFBQcBAQR1MHMwPgYIKwYBBQUHMAKGMmh0 +dHA6Ly9laWRkZXZjYXJkcy56ZXRlc2NhcmRzLmJlL2NlcnQvcm9vdGNhRUMuY3J0 +MDEGCCsGAQUFBzABhiVodHRwOi8vZWlkZGV2Y2FyZHMuemV0ZXNjYXJkcy5iZTo4 +ODg4MBIGA1UdEwEB/wQIMAYBAf8CAQAwCgYIKoZIzj0EAwMDaAAwZQIxAOMiiByF +0aLEA6zUrobMw7aSH5o2u1hGVMe0AL4ezYztRdfxvXVU+m1JosBVBDDjeAIwYJJN +7bLWw8BVi/lkxRjKL/+zAJP6djGywXI1pVh4HKb0D+tipq5StO+QnM8cnPmg +-----END CERTIFICATE----- diff --git a/example/src/main/resources/certs/dev/eID-TEST-EC-Root-CA.cer b/example/src/main/resources/certs/dev/eID-TEST-EC-Root-CA.cer new file mode 100644 index 00000000..3908e4c7 --- /dev/null +++ b/example/src/main/resources/certs/dev/eID-TEST-EC-Root-CA.cer @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICNDCCAbugAwIBAgIBATAKBggqhkjOPQQDAzArMQswCQYDVQQGEwJCRTEcMBoG +A1UEAwwTZUlEIFRFU1QgRUMgUm9vdCBDQTAgFw0wNzA0MzAyMjAwMTBaGA8yMDg4 +MDQwOTIyMDAxMFowKzELMAkGA1UEBhMCQkUxHDAaBgNVBAMME2VJRCBURVNUIEVD +IFJvb3QgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASYqtYIKayPGXFNDaGkPdCa +dQCSC8D2W8aKE7xh850ykG0bJXMV7IaKZWo0ZXUb55g9S95gjDNeZ0iNo75dY/mW +oozI6I2l106OdPL+yAcHI6id4uR7Fd0nQxeBICdmjnCjgbAwga0wHQYDVR0OBBYE +FCHAclfKHAQEGR3ZjH4+tYPrrBwCMB8GA1UdIwQYMBaAFCHAclfKHAQEGR3ZjH4+ +tYPrrBwCMA4GA1UdDwEB/wQEAwIBBjBHBgNVHSAEQDA+MDwGBWA4DAEBMDMwMQYI +KwYBBQUHAgEWJWh0dHA6Ly9laWRkZXZjYXJkcy56ZXRlc2NhcmRzLmJlL2NlcnQw +EgYDVR0TAQH/BAgwBgEB/wIBATAKBggqhkjOPQQDAwNnADBkAjBM2P48H8f2FY0N +Hm1uAdgXwYoBRkUFOq8Kccd7l6Y8RavzAkMQmLgVF3s5euuv6fcCMCW4UGWpnOTO +A+t4V9/+kPMjGqgC9Uw4nOKkwkwQs3IeWfc7Na6l+U8r4M7VH49/cw== +-----END CERTIFICATE----- diff --git a/example/src/main/resources/certs/prod/ESTEID-SK_2015.cer b/example/src/main/resources/certs/prod/ESTEID-SK_2015.cer deleted file mode 100644 index b1669556..00000000 Binary files a/example/src/main/resources/certs/prod/ESTEID-SK_2015.cer and /dev/null differ diff --git a/example/src/main/resources/static/js/errors.js b/example/src/main/resources/static/js/errors.js index 7bc8c92c..7f42d5ff 100644 --- a/example/src/main/resources/static/js/errors.js +++ b/example/src/main/resources/static/js/errors.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/example/src/main/resources/static/js/web-eid.js b/example/src/main/resources/static/js/web-eid.js index ee9b770c..520fa88f 100644 --- a/example/src/main/resources/static/js/web-eid.js +++ b/example/src/main/resources/static/js/web-eid.js @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020-2022 Estonian Information System Authority + * Copyright (c) 2020-2023 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -104,7 +104,7 @@ class ExtensionUnavailableError extends Error { } var config = Object.freeze({ - VERSION: "2.0.1", + VERSION: "2.0.2", EXTENSION_HANDSHAKE_TIMEOUT: 1000, NATIVE_APP_HANDSHAKE_TIMEOUT: 5 * 1000, DEFAULT_USER_INTERACTION_TIMEOUT: 2 * 60 * 1000, @@ -243,7 +243,7 @@ class WebExtensionService { (_d = message.warnings) === null || _d === void 0 ? void 0 : _d.forEach((warning) => { if (!this.loggedWarnings.includes(warning)) { this.loggedWarnings.push(warning); - console.warn(warning); + console.warn(warning.replace(/\n|\r/g, "")); } }); } diff --git a/example/src/main/resources/static/scripts/download-install-web-eid.sh b/example/src/main/resources/static/scripts/download-install-web-eid.sh deleted file mode 100755 index 9eb11483..00000000 --- a/example/src/main/resources/static/scripts/download-install-web-eid.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/bash -# -# This script downloads and installs Web eID in .deb based Linux distributions. -# License: public domain. -# Based on https://github.com/open-eid/linux-installer/blob/master/install-open-eid.sh - -set -eu - -test_sudo() { - if ! command -v sudo>/dev/null; then - make_fail "You must have sudo and be in sudo group\nAs root do: apt-get install sudo && adduser $USER sudo" - fi -} - -test_root() { - if test $(id -u) -eq 0; then - echo "You run this script as root. DO NOT RUN RANDOM SCRIPTS AS ROOT." - exit 2 - fi -} - -make_fail() { - echo -e "$1" - exit 3 -} - -make_warn() { - echo "### $1" - echo "Press ENTER to continue, CTRL-C to cancel" - read -r dummy -} - -make_install() { - echo "Installing Web eID packages for Ubuntu $1" - TMPDIR=`mktemp -d` - cd $TMPDIR - VERSION='2.2.0' - # BUILD=`[[ $1 == *0 ]] && echo 555 || echo 552` - BUILD='572' - UBUNTU_VERSION=${1//./} - wget "https://installer.id.ee/media/web-eid/Ubuntu/web-eid_${VERSION}.${BUILD}-${UBUNTU_VERSION}_all.deb" - wget "https://installer.id.ee/media/web-eid/Ubuntu/web-eid-chrome_${VERSION}.${BUILD}-${UBUNTU_VERSION}_all.deb" - wget "https://installer.id.ee/media/web-eid/Ubuntu/web-eid-firefox_${VERSION}.${BUILD}-${UBUNTU_VERSION}_all.deb" - wget "https://installer.id.ee/media/web-eid/Ubuntu/web-eid-native_${VERSION}.${BUILD}-${UBUNTU_VERSION}_amd64.deb" - sudo apt install -y ./web-eid*.deb - cd /tmp - rm -r $TMPDIR -} - -### main - -# Check for Debian derivative. -if ! command -v lsb_release>/dev/null; then - make_fail "# Not a Debian Linux derivative, cannot continue." -fi - -# We use sudo. -test_root -test_sudo - -# version name LTS supported until -# 18.04 bionic LTS 2023-04 -# 20.04 focal LTS 2025-04 -# 22.04 jammy LTS 2027-04 -# 22.10 kinetic - 2023-07 -LATEST_SUPPORTED_UBUNTU_CODENAME='kinetic' -LATEST_SUPPORTED_UBUNTU_VERSION='22.10' - -# Check the distro and release. -distro=$(lsb_release -is | tr '[:upper:]' '[:lower:]') -release=$(lsb_release -rs) -codename=$(lsb_release -cs) - -case $distro in - debian) - make_warn "Debian is not officially supported" - case "$codename" in - buster) - make_warn "Debian $codename is not officially supported" - make_warn "Installing from ubuntu-bionic repository" - make_install '18.04' - ;; - bullseye) - make_warn "Debian $codename is not officially supported" - make_warn "Installing from ubuntu-focal repository" - make_install '20.04' - ;; - *) - make_fail "Debian $codename is not officially supported" - ;; - esac - ;; - ubuntu|neon) - case $distro in - neon) make_warn "Neon is not officially supported; assuming that it is equivalent to Ubuntu" ;; - *) ;; - esac - case $codename in - utopic|vivid|wily|trusty|artful|cosmic|disco|xenial|eoan|groovy|hirsute|impish) - make_fail "Ubuntu $codename is not officially supported" - ;; - bionic|focal|jammy|kinetic) - make_install $release - ;; - *) - make_warn "Ubuntu $codename is not officially supported" - make_warn "Trying to install package for Ubuntu ${LATEST_SUPPORTED_UBUNTU_CODENAME}" - make_install ${LATEST_SUPPORTED_UBUNTU_VERSION} - ;; - esac - ;; - linuxmint) - case $release in - 21*) - make_warn "Linuxmint 21 is not officially supported" - make_install '22.04' - ;; - 20*) - make_warn "Linuxmint 20 is not officially supported" - make_install '20.04' - ;; - 19*) - make_warn "LinuxMint 19 is not officially supported" - make_install '18.04' - ;; - *) - make_fail "LinuxMint $release is not officially supported" - ;; - esac - ;; - elementary*os|elementary) - case $release in - 5.*) - make_warn "Elementary OS 5 is not officially supported" - make_install '18.04' - ;; - *) - make_fail "Elementary OS $release is not officially supported" - ;; - esac - ;; - pop) - case $codename in - artful|cosmic|disco|eoan) - make_fail "Pop!_OS $codename is not officially supported" - ;; - bionic|focal) - make_warn "Pop!_OS $codename is not officially supported" - make_install $release - ;; - *) - make_warn "Pop!_OS $codename is not officially supported" - make_warn "Trying to install package for Pop!_OS ${LATEST_SUPPORTED_UBUNTU_CODENAME}" - make_install ${LATEST_SUPPORTED_UBUNTU_VERSION} - ;; - esac - ;; - *) - make_fail "$distro is not supported :(" - ;; -esac diff --git a/example/src/main/resources/static/scripts/install-web-eid.sh b/example/src/main/resources/static/scripts/install-web-eid.sh new file mode 100755 index 00000000..8a2828ce --- /dev/null +++ b/example/src/main/resources/static/scripts/install-web-eid.sh @@ -0,0 +1,222 @@ +#!/bin/sh +# This script configures .deb based Linux repositories +# License: public domain +# Script https://github.com/open-eid/linux-installer +# See wiki https://github.com/open-eid/linux-installer/wiki/Linux-Packages +set -e + +# Key used for signing releases +RIA_KEY="""-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: GPGTools - https://gpgtools.org + +mQINBFcrMk4BEADCimHCTTCsBbUL+MtrRGNKEo/ccdjv0hArPqn1yt/7w9BFH17f +kY+w6IFdfD0o1Uc7MOofsF3ROVIsw/mul6k1YUh2HxtKmsVOMLE0eWHShvMlXKDV +1H1dCAk3A2c7nmzTedJaMMu+cLCRpt9zpmF1kG4i07UuyBxpRmolq/+hYa2JHPw4 +CFDW0s1T/rF1KUTbGHQKhT9Qek2tTsHQn4C33QUnCMkb3HCbDQksW69FoLiwa3am +fAgGSOI8iZ3uofh3LU9kEy6dL6ZFKUevOETlDidHaNNDhC8g0seMkMLTuSmWc64X +DTobStcuZcHtakzeWZ/V2kXouhUsgXOMxhPGHFkfd+qqk3LGqZ29wTK2bYyTjCsD +gYPO2YHGmCzLzH9DgHNfjDWzeAWClg5PO/oB5sg5fYMwmHJtLeqGJarFKl22p9/K +odRruGQiGqkHptxwdoNjgvgluiSb6C+dCU5pGU8t+9/+IfqxChltUkI02O6jfPO4 +mweflYBQ8zkXOLPlVIfJnO5xw4wwrh3rV/fXxlNMI+Ni7/zPF61OQ50r/oya6zRR +rSLEAig2lZY+vhbv9WDgJKIPwb8oe13d1UCRDdtkj70MBQFh1m6RFzDXy4821U9w +TRtRy+92UN5jRRkeMb0yaO/EboTRjOy7BToJSVeYGRQy73M2vhxhWXSXrwARAQAB +tClSSUEgU29mdHdhcmUgU2lnbmluZyBLZXkgPHNpZ25pbmdAcmlhLmVlPokCNwQT +AQoAIQUCVysyTgIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRDpqyFNxsg9 +aJJ9D/sGXNgFsEvbGEYlKtrhY9ungOBk7B5iH/Nxy+yMjIZY9mLdp9RMEO6oZFam +3vC+3o01veRUkf0KRDjtDAK2c358aHsNAVcFXfJk950OuqUzywZvuNwlCOMCYZ41 +KBUfcwebhqiqMDzOLnx2mwUvV0OQGKgpqQes1+LE0pI2ySsgUyTp50mvLt8e9yXq +1uO82WzmAYcR8VGOViavjtV8ZF4X09d1ugZAWeOsZHdjl7Yb/aUy4WW35wQsHmo8 +Tro6KuG9KgvrNM798gdhwA6kt29B2YGGTQGODwIt8jydN2o0P3UhpVW+C+60Axqw +jSnPOJFPNVsRJ5se9PvhJS0xmUVOttRJFU74FmsK4dArG4pqMjBzXReEk9Pz03FW +9EbD8PY+n/hrp2zp7kEa5umzLJePi3117r06OkiQoI0Wfmi3bISBe0oN2lS7QUBo +DUursJNSMKpEhQBc3lPsyKoZwb73fl86iOm5/GpdMkKBXOQzGbgJV96I+s6ZemQ4 +psbxQCWStcwLnenkKEU2eezP9codmtRivRftx9+/xt9DxIfbtvZMPsrG6+EI+Ovo +onO6lMgnQJmxhjJ5FUwyBn27b41LDUnQhdMHtSwr7HCyU/ufnte1dQQy+xxYH4fG +oafemhM54Tx0fi47HruFu+DjSLECP57TVAVFJTyn6wr4U2Lya7kCDQRXKzJOARAA +q1I36MBmlWenlq9ZqwAvA0kT1l4uyrkj7EIpPXNmkkMYtW3jHWe/4M4k6b0NmNnj +FoaPmK86b037AoODd40xQYWV3Y5arwSfcZPYx35/+uiim4vykNI7u9MMujHDvMvV +AE2RXK/s1Lj+7B37H9AkcpAdj+YngYEKrVjzUbiPJXisbEc/g94F56YqbnGB1g6Y +pMXSGC1SvaYCBnUyWzLlmHYlib36R3dWXmpuQuTTn65QQU1jIKm5na7c37AP6k7G +RBthPmDveXV+UFlWBl3ybqhVcf7svGcSLf/n7ekF9PlUEDoQ+4rA+mQARS138R3I +WbZAB7KOTBrLPpPvKXvbq5r1/wfArBbKxOiB7c4xlejqeRbXFig4acQHK7vDfrIG +yA6hyR1H73kp3uFl0SEa/RKsPcYUagkFn3tlUBrX+6/ZuOcowaN9FuShJlMrgk1K +DiPprE7+gwA1fnGo6X/Jto6M6xkeGf0Lj2YZ6B0u2x8BIwSJUDqISd2TJoireMBb +0GQRUyfBDGB9ZDvMvC0SIezw3aEPW68uLadJa98QUGyYWQunIfiKfGzKHhpc4ser +V28WIJ/QJf2oJ3Cp3Ot2DI4qgJbSPkQYcizK/dNXJ6KoUv95i5SEQ82tw0vsytmI +3jZseGWLOnz9+LS41O55JjylDUAgJchroNF7bJZ2DocAEQEAAYkCHwQYAQoACQUC +VysyTgIbDAAKCRDpqyFNxsg9aKrtD/wM9pDDvLeeA6fg5mmAb6dmfhr2hAecbI/n +sGD5qslu0oE11Zj9gwYD5ixhieLbudEWk+YaGsg1/s1vMIEZsAXQYY0kihOBYGtr +heFA7YPzJSac1uwlF+unb7wvW8zYbyjkDpBmuyA08fHOFisHp1A4v4zsaLKZbCy7 +qQJWk8JU7eJnGecAuKnF8Zqpxur2k17QlsaoA3DIUDiSJyQVsFgTAgSkzjdQYVH2 +LVsb3XZeJnOoV1fs0E6kCCDUXtVx2yVzRgLKNnZvbufTKRAjr+mggUH+JOBbrDf/ +zf9Ud8PHBaLJh9+OA3AO310FwiJX0SnZjcCg29C7N0SkuDWowDLjwT8XAikdAsRC +xPZcOJSQjnSrd/X6ZjvDEBNlnY0dBOnuWt3CmwEdIreEJGomGMBE2/mw5ieFhlpN +6pp4Oe8kLl3mpd11RxfY2wW2r1BkxihtV/4pts7kCgSyRb8DwSZVYDHai5OtfeMZ +OTbaIP5/7aWoxd3R4JoKX5zHqY6slzi+MERJmDcIR5v1Np8HGJIHR/10uG3WvQ43 +CBVNV1KxDSWiO99+50ajU2humchuZKucVQUirUGd5ZPijAuZzrQeE9yboEMSB5nj +WxoE6tFHd17wOg+ImAMerVY53I4h0EkmbzPfeszZYR0geGvu4sngt69wJmmTINUC +K2czbpReKw== +=aSyh +-----END PGP PUBLIC KEY BLOCK----- +""" + +add_key() { + # keystring=`echo "$RIA_KEY" | gpg` # XXX: can't be automated, gpg always creates files on disk + keystring="0xC6C83D68 'RIA Software Signing Key '" + echo "Adding key to trusted key set" + echo "$keystring" + echo "$RIA_KEY" | gpg --dearmor | sudo tee /usr/share/keyrings/ria-repository.gpg > /dev/null +} + +test_sudo() { + if ! command -v sudo>/dev/null; then + make_fail "You must have sudo and be in sudo group\nAs root do: apt install sudo && adduser $USER sudo" + fi +} + +test_root() { + if test $(id -u) -eq 0; then + echo "You run this script as root. DO NOT RUN RANDOM SCRIPTS AS ROOT." + exit 2 + fi +} + +# add the given repository into /etc/apt/sources.list.d +add_repository() { + umask 0022 + echo "Adding RIA repository to APT sources list (/etc/apt/sources.list.d/ria-repository.list)" + echo "deb [signed-by=/usr/share/keyrings/ria-repository.gpg] https://installer.id.ee/media/ubuntu/ $1 main" | sudo tee /etc/apt/sources.list.d/ria-repository.list +} + +make_install() { + echo "Installing software (apt update && apt install web-eid)" + sudo apt update + sudo apt install "$@" +} + +make_fail() { + echo "$1" + exit 3 +} + +make_warn() { + echo "### $1" + echo "Press ENTER to continue, CTRL-C to cancel" + read -r dummy +} + +### Install Estonian ID card software + +# check for Debian derivative. +if ! command -v lsb_release>/dev/null; then + make_fail "# Not a Debian Linux :(" +fi + +# we use sudo +test_root +test_sudo + +# version name LTS supported until +# 22.04 jammy LTS 2027-04 +# 24.04 noble LTS 2029-04 +# 24.10 oracular - 2025-07 +LATEST_SUPPORTED_UBUNTU_CODENAME='oracular' + +# check if Debian or Ubuntu +distro=$(lsb_release -is | tr '[:upper:]' '[:lower:]') +release=$(lsb_release -rs) +codename=$(lsb_release -cs) + +case $distro in + debian) + make_warn "Debian is not officially supported" + echo "### Installing possibly missing https support for APT (apt install apt-transport-https)" + # Debian lacks https support for apt, by default + sudo apt install apt-transport-https + case "$codename" in + bookworm) + make_warn "Debian $codename is not officially supported" + make_warn "Installing from ubuntu-jammy repository" + add_repository jammy + ;; + *) + make_fail "Debian $codename is not officially supported" + ;; + esac + ;; + ubuntu|neon|zorin) + case $distro in + neon) make_warn "Neon is not officially supported; assuming that it is equivalent to Ubuntu" ;; + *) ;; + esac + case $codename in + utopic|vivid|wily|trusty|artful|cosmic|disco|xenial|eoan|groovy|hirsute|impish|bionic|zorin|kinetic|lunar|mantic|focal) + make_fail "Ubuntu $codename is not officially supported" + ;; + jammy|noble|oracular) + add_repository $codename + ;; + *) + make_warn "Ubuntu $codename is not officially supported" + make_warn "Trying to install package for Ubuntu ${LATEST_SUPPORTED_UBUNTU_CODENAME}" + add_repository ${LATEST_SUPPORTED_UBUNTU_CODENAME} + ;; + esac + ;; + linuxmint) + case $release in + 22*) + make_warn "Linux Mint 22 is not officially supported" + add_repository noble + ;; + 21*) + make_warn "Linux Mint 21 is not officially supported" + add_repository jammy + ;; + *) + make_fail "Linux Mint $release is not officially supported" + ;; + esac + ;; + elementary*os|elementary) + case $release in + 7*) + make_warn "Elementary OS 7 is not officially supported" + add_repository jammy + ;; + *) + make_fail "Elementary OS $release is not officially supported" + ;; + esac + ;; + pop) + case $codename in + artful|cosmic|disco|eoan|bionic|focal) + make_fail "Pop!_OS $codename is not officially supported" + ;; + jammy) + make_warn "Pop!_OS $codename is not officially supported" + add_repository $codename + ;; + *) + make_warn "Pop!_OS $codename is not officially supported" + make_warn "Trying to install package for Pop!_OS ${LATEST_SUPPORTED_UBUNTU_CODENAME}" + add_repository ${LATEST_SUPPORTED_UBUNTU_CODENAME} + ;; + esac + ;; + *) + make_fail "$distro is not supported :(" + ;; +esac + +add_key +make_install web-eid + +echo +echo "Thank you for using Estonian ID card!" +read -p "Would you like to read instructions on how to configure browsers for using ID-card? (Y/n): " instructions +case $instructions in + [Yy]*|"" ) xdg-open "https://www.id.ee/en/article/ubuntu-id-software-installation-updating-and-removal/#removing-mozilla-firefox";; + * ) ;; +esac diff --git a/example/src/main/resources/templates/index.html b/example/src/main/resources/templates/index.html index e24d4c74..051ab855 100644 --- a/example/src/main/resources/templates/index.html +++ b/example/src/main/resources/templates/index.html @@ -27,9 +27,8 @@

Web eID: electronic ID smart cards on the Web

secure authentication and digital signing of documents on the web using public-key cryptography.

- Estonian, Finnish, Latvian, Lithuanian and Croatian eID cards are supported in the first phase, but only - Estonian eID card support is currently enabled in the test application below. Belgian eID support is - upcoming. + Estonian, Finnish, Latvian, Lithuanian, Belgian and Croatian eID cards are supported in the first phase, + but only Estonian eID card support is currently enabled in the test application below.

Please get in touch by email at help@ria.ee in case you need support with adding Web eID to your project @@ -56,27 +55,22 @@

Usage

Download and run the Web eID native app and browser extension installer:
  • on Ubuntu Linux, for Firefox and Chrome, download and execute the
    - download-install-web-eid.sh + install-web-eid.sh script from the console with
    - wget -O - https:///scripts/download-install-web-eid.sh + wget -O - https:///scripts/install-web-eid.sh | bash
    - Note that Firefox is installed with Snap in Ubuntu 22.04 or later by default and as the - Snap sandbox does not allow communication with the external native messaging host, Web - eID will not work. - Install Firefox via the Debian package instead of Snap if you want to use Web eID with - Firefox in Ubuntu 22.04+. Instructions how to do that are available here. + Note: as of the 2.5 version, Web eID supports Firefox installed via Snap.
  • -
  • on macOS 10.15 or later, for Firefox and Chrome from here, +
  • on macOS 12 or later, for Firefox and Chrome from here,
  • -
  • on macOS 10.15 or later, for Safari, install the extension from on macOS 12 or later, for Safari, install the extension from App Store,
  • on Windows 10, Windows 11, Windows Server 2016, Windows Server 2019, Windows Server 2022, for Firefox, Chrome and Edge from here. + href="https://installer.id.ee/media/web-eid/web-eid_2.6.0.900.x64.exe">here.
@@ -226,7 +220,7 @@

For developers

  • in Java use the digidoc4j library in the back end of the web application according to the instructions - here, + here,
  • in .NET/C# use the libdigidocpp library in the back end of the web application according to the instructions @@ -238,11 +232,11 @@

    For developers

    The full source code of an example Spring Boot web application that uses Web eID for authentication and digital signing is available - here. + here. The .NET/C# version of the example is available here. The PHP version of the example is available - here. + here.

    diff --git a/example/src/main/resources/templates/welcome.html b/example/src/main/resources/templates/welcome.html index ab0a0938..67b31311 100644 --- a/example/src/main/resources/templates/welcome.html +++ b/example/src/main/resources/templates/welcome.html @@ -59,8 +59,17 @@

    Digital signing

    const fileNameText = document.querySelector("#file-name"); const exampleDocument = document.querySelector("#example-document"); + const csrfToken = document.querySelector('#csrftoken').content; + const csrfHeaderName = document.querySelector('#csrfheadername').content; + document.querySelector("#webeid-logout-button").addEventListener("click", async () => { - await fetch("/logout"); + await fetch("/logout", { + method: "POST", + headers: { + "Content-Type": "application/json", + [csrfHeaderName]: csrfToken + } + }); window.location.href = "/"; }); @@ -68,9 +77,6 @@

    Digital signing

    window.location.href = "/sign/download"; }); - const csrfToken = document.querySelector('#csrftoken').content; - const csrfHeaderName = document.querySelector('#csrfheadername').content; - const lang = new URLSearchParams(window.location.search).get("lang") || "en"; signButton.addEventListener("click", async () => { diff --git a/example/src/test/java/eu/webeid/example/AuthenticationRestControllerTest.java b/example/src/test/java/eu/webeid/example/AuthenticationRestControllerTest.java index 74bf6b52..ec5345a5 100644 --- a/example/src/test/java/eu/webeid/example/AuthenticationRestControllerTest.java +++ b/example/src/test/java/eu/webeid/example/AuthenticationRestControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/example/src/test/java/eu/webeid/example/WebApplicationTest.java b/example/src/test/java/eu/webeid/example/WebApplicationTest.java index f4e51acf..f7f5a3de 100644 --- a/example/src/test/java/eu/webeid/example/WebApplicationTest.java +++ b/example/src/test/java/eu/webeid/example/WebApplicationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,6 +37,7 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpSession; import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; @@ -58,7 +59,7 @@ public class WebApplicationTest { private WebApplicationContext context; @Autowired - private javax.servlet.Filter[] springSecurityFilterChain; + private jakarta.servlet.Filter[] springSecurityFilterChain; private static DefaultMockMvcBuilder mvcBuilder; @@ -98,16 +99,18 @@ public void validateOcspResponse(XadesSignature xadesSignature) { } }; - final MockHttpSession session = new MockHttpSession(); + MockHttpSession session = new MockHttpSession(); session.setAttribute("challenge-nonce", new ChallengeNonce(ObjectMother.VALID_CHALLENGE_NONCE, DateAndTime.utcNow().plusMinutes(1))); - Dates.setMockedDate(Dates.create("2020-04-14T13:36:49Z")); + Dates.setMockedSignatureDate(Dates.getSigningDateTime()); // Act and assert mvcBuilder.build().perform(get("/auth/challenge")); - MockHttpServletResponse response = HttpHelper.login(mvcBuilder, session, ObjectMother.mockAuthToken()); - assertEquals("{\"sub\":\"JAAK-KRISTJAN JÕEORG\",\"auth\":[\"ROLE_USER\"]}", response.getContentAsString()); + MvcResult result = HttpHelper.login(mvcBuilder, session, ObjectMother.mockAuthToken()); + session = (MockHttpSession) result.getRequest().getSession(); + MockHttpServletResponse response = result.getResponse(); + assertEquals("{\"sub\":\"JAAK-KRISTJAN JÕEORG\",\"auth\":\"[ROLE_USER]\"}", response.getContentAsString()); /* Example how to test file upload. response = HttpHelper.upload(mvcBuilder, session, mockMultipartFile()); diff --git a/example/src/test/java/eu/webeid/example/security/WebEidAjaxLoginProcessingFilterTest.java b/example/src/test/java/eu/webeid/example/security/WebEidAjaxLoginProcessingFilterTest.java index 0640a4d6..828399b1 100644 --- a/example/src/test/java/eu/webeid/example/security/WebEidAjaxLoginProcessingFilterTest.java +++ b/example/src/test/java/eu/webeid/example/security/WebEidAjaxLoginProcessingFilterTest.java @@ -1,11 +1,33 @@ +/* + * Copyright (c) 2020-2025 Estonian Information System Authority + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + package eu.webeid.example.security; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.junit.jupiter.api.Test; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.StringReader; diff --git a/example/src/test/java/eu/webeid/example/security/WebEidAuthenticationTest.java b/example/src/test/java/eu/webeid/example/security/WebEidAuthenticationTest.java index 630cf499..1da776b6 100644 --- a/example/src/test/java/eu/webeid/example/security/WebEidAuthenticationTest.java +++ b/example/src/test/java/eu/webeid/example/security/WebEidAuthenticationTest.java @@ -1,3 +1,25 @@ +/* + * Copyright (c) 2020-2025 Estonian Information System Authority + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + package eu.webeid.example.security; import eu.webeid.security.certificate.CertificateLoader; diff --git a/example/src/test/java/eu/webeid/example/testutil/Dates.java b/example/src/test/java/eu/webeid/example/testutil/Dates.java index 152a9ff6..3f5f76ae 100644 --- a/example/src/test/java/eu/webeid/example/testutil/Dates.java +++ b/example/src/test/java/eu/webeid/example/testutil/Dates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,27 +22,27 @@ package eu.webeid.example.testutil; -import com.fasterxml.jackson.databind.util.StdDateFormat; +import eu.europa.esig.dss.model.BLevelParameters; import mockit.Mock; import mockit.MockUp; -import java.text.ParseException; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Date; public final class Dates { - private static final StdDateFormat STD_DATE_FORMAT = new StdDateFormat(); - public static Date create(String iso8601Date) throws ParseException { - return STD_DATE_FORMAT.parse(iso8601Date); + public static ZonedDateTime getSigningDateTime() { + return ZonedDateTime.of(2020, 4, 14, 13, 36, 49, 0, + ZoneId.of("Europe/Tallinn")); } - public static void setMockedDate(Date mockedDate) { - new MockUp() { + public static void setMockedSignatureDate(ZonedDateTime mockedDateTime) { + new MockUp() { @Mock - public long currentTimeMillis() { - return mockedDate.getTime(); + public Date getSigningDate() { + return Date.from(mockedDateTime.toInstant()); } }; } - } diff --git a/example/src/test/java/eu/webeid/example/testutil/HttpHelper.java b/example/src/test/java/eu/webeid/example/testutil/HttpHelper.java index a45c74c1..9c8b0dc9 100644 --- a/example/src/test/java/eu/webeid/example/testutil/HttpHelper.java +++ b/example/src/test/java/eu/webeid/example/testutil/HttpHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,7 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpSession; import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; import eu.webeid.example.security.dto.AuthTokenDTO; @@ -38,7 +39,7 @@ public class HttpHelper { - public static MockHttpServletResponse login(DefaultMockMvcBuilder mvcBuilder, MockHttpSession session, AuthTokenDTO authTokenDTO) throws Exception { + public static MvcResult login(DefaultMockMvcBuilder mvcBuilder, MockHttpSession session, AuthTokenDTO authTokenDTO) throws Exception { // @formatter:off return mvcBuilder .build() @@ -47,8 +48,7 @@ public static MockHttpServletResponse login(DefaultMockMvcBuilder mvcBuilder, Mo .with(csrf()) .contentType(MediaType.APPLICATION_JSON) .content(ObjectMother.toJson(authTokenDTO))) - .andReturn() - .getResponse(); + .andReturn(); // @formatter:on } diff --git a/example/src/test/java/eu/webeid/example/testutil/ObjectMother.java b/example/src/test/java/eu/webeid/example/testutil/ObjectMother.java index 5d4b0810..288b1368 100644 --- a/example/src/test/java/eu/webeid/example/testutil/ObjectMother.java +++ b/example/src/test/java/eu/webeid/example/testutil/ObjectMother.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Web eID Project + * Copyright (c) 2020-2025 Estonian Information System Authority * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,6 +24,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import eu.webeid.example.service.dto.SignatureAlgorithmDTO; import eu.webeid.security.authtoken.WebEidAuthToken; import org.apache.commons.lang3.ArrayUtils; import org.digidoc4j.DigestAlgorithm; @@ -32,13 +33,14 @@ import eu.webeid.example.service.dto.CertificateDTO; import eu.webeid.example.service.dto.SignatureDTO; -import javax.xml.bind.DatatypeConverter; +import jakarta.xml.bind.DatatypeConverter; import java.io.FileInputStream; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.util.Base64; +import java.util.List; public class ObjectMother { @@ -51,10 +53,10 @@ public class ObjectMother { try { VALID_AUTH_TOKEN = MAPPER.readValue( "{\"algorithm\":\"ES384\"," + - "\"unverifiedCertificate\":\"MIIEAzCCA2WgAwIBAgIQHWbVWxCkcYxbzz9nBzGrDzAKBggqhkjOPQQDBDBgMQswCQYDVQQGEwJFRTEbMBkGA1UECgwSU0sgSUQgU29sdXRpb25zIEFTMRcwFQYDVQRhDA5OVFJFRS0xMDc0NzAxMzEbMBkGA1UEAwwSVEVTVCBvZiBFU1RFSUQyMDE4MB4XDTE4MTAyMzE1MzM1OVoXDTIzMTAyMjIxNTk1OVowfzELMAkGA1UEBhMCRUUxKjAoBgNVBAMMIUrDlUVPUkcsSkFBSy1LUklTVEpBTiwzODAwMTA4NTcxODEQMA4GA1UEBAwHSsOVRU9SRzEWMBQGA1UEKgwNSkFBSy1LUklTVEpBTjEaMBgGA1UEBRMRUE5PRUUtMzgwMDEwODU3MTgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ/u+9IncarVpgrACN6aRgUiT9lWC9H7llnxoEXe8xoCI982Md8YuJsVfRdeG5jwVfXe0N6KkHLFRARspst8qnACULkqFNat/Kj+XRwJ2UANeJ3Gl5XBr+tnLNuDf/UiR6jggHDMIIBvzAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIDiDBHBgNVHSAEQDA+MDIGCysGAQQBg5EhAQIBMCMwIQYIKwYBBQUHAgEWFWh0dHBzOi8vd3d3LnNrLmVlL0NQUzAIBgYEAI96AQIwHwYDVR0RBBgwFoEUMzgwMDEwODU3MThAZWVzdGkuZWUwHQYDVR0OBBYEFOTddHnA9rJtbLwhBNyn0xZTQGCMMGEGCCsGAQUFBwEDBFUwUzBRBgYEAI5GAQUwRzBFFj9odHRwczovL3NrLmVlL2VuL3JlcG9zaXRvcnkvY29uZGl0aW9ucy1mb3ItdXNlLW9mLWNlcnRpZmljYXRlcy8TAkVOMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDAfBgNVHSMEGDAWgBTAhJkpxE6fOwI09pnhClYACCk+ezBzBggrBgEFBQcBAQRnMGUwLAYIKwYBBQUHMAGGIGh0dHA6Ly9haWEuZGVtby5zay5lZS9lc3RlaWQyMDE4MDUGCCsGAQUFBzAChilodHRwOi8vYy5zay5lZS9UZXN0X29mX0VTVEVJRDIwMTguZGVyLmNydDAKBggqhkjOPQQDBAOBiwAwgYcCQgHYElkX4vn821JR41akI/lpexCnJFUf4GiOMbTfzAxpZma333R8LNrmI4zbzDp03hvMTzH49g1jcbGnaCcbboS8DAJBObenUp++L5VqldHwKAps61nM4V+TiLqD0jILnTzl+pV+LexNL3uGzUfvvDNLHnF9t6ygi8+Bsjsu3iHHyM1haKM=\"," + - "\"appVersion\":\"https://web-eid.eu/web-eid-app/releases/2.0.0+0\"," + - "\"signature\":\"tbMTrZD4CKUj6atjNCHZruIeyPFAEJk2htziQ1t08BSTyA5wKKqmNmzsJ7562hWQ6+tJd6nlidHGE5jVVJRKmPtNv3f9gbT2b7RXcD4t5Pjn8eUCBCA4IX99Af32Z5ln\"," + - "\"format\":\"web-eid:1\"}", + "\"unverifiedCertificate\":\"MIIEBDCCA2WgAwIBAgIQY5OGshxoPMFg+Wfc0gFEaTAKBggqhkjOPQQDBDBgMQswCQYDVQQGEwJFRTEbMBkGA1UECgwSU0sgSUQgU29sdXRpb25zIEFTMRcwFQYDVQRhDA5OVFJFRS0xMDc0NzAxMzEbMBkGA1UEAwwSVEVTVCBvZiBFU1RFSUQyMDE4MB4XDTIxMDcyMjEyNDMwOFoXDTI2MDcwOTIxNTk1OVowfzELMAkGA1UEBhMCRUUxKjAoBgNVBAMMIUrDlUVPUkcsSkFBSy1LUklTVEpBTiwzODAwMTA4NTcxODEQMA4GA1UEBAwHSsOVRU9SRzEWMBQGA1UEKgwNSkFBSy1LUklTVEpBTjEaMBgGA1UEBRMRUE5PRUUtMzgwMDEwODU3MTgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQmwEKsJTjaMHSaZj19hb9EJaJlwbKc5VFzmlGMFSJVk4dDy+eUxa5KOA7tWXqzcmhh5SYdv+MxcaQKlKWLMa36pfgv20FpEDb03GCtLqjLTRZ7649PugAQ5EmAqIic29CjggHDMIIBvzAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIDiDBHBgNVHSAEQDA+MDIGCysGAQQBg5EhAQIBMCMwIQYIKwYBBQUHAgEWFWh0dHBzOi8vd3d3LnNrLmVlL0NQUzAIBgYEAI96AQIwHwYDVR0RBBgwFoEUMzgwMDEwODU3MThAZWVzdGkuZWUwHQYDVR0OBBYEFPlp/ceABC52itoqppEmbf71TJz6MGEGCCsGAQUFBwEDBFUwUzBRBgYEAI5GAQUwRzBFFj9odHRwczovL3NrLmVlL2VuL3JlcG9zaXRvcnkvY29uZGl0aW9ucy1mb3ItdXNlLW9mLWNlcnRpZmljYXRlcy8TAkVOMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDAfBgNVHSMEGDAWgBTAhJkpxE6fOwI09pnhClYACCk+ezBzBggrBgEFBQcBAQRnMGUwLAYIKwYBBQUHMAGGIGh0dHA6Ly9haWEuZGVtby5zay5lZS9lc3RlaWQyMDE4MDUGCCsGAQUFBzAChilodHRwOi8vYy5zay5lZS9UZXN0X29mX0VTVEVJRDIwMTguZGVyLmNydDAKBggqhkjOPQQDBAOBjAAwgYgCQgDCAgybz0u3W+tGI+AX+PiI5CrE9ptEHO5eezR1Jo4j7iGaO0i39xTGUB+NSC7P6AQbyE/ywqJjA1a62jTLcS9GHAJCARxN4NO4eVdWU3zVohCXm8WN3DWA7XUcn9TZiLGQ29P4xfQZOXJi/z4PNRRsR4plvSNB3dfyBvZn31HhC7my8woi\"," + + "\"appVersion\":\"https://web-eid.eu/web-eid-app/releases/2.5.0+0\"," + + "\"signature\":\"0Ov7ME6pTY1K2GXMj8Wxov/o2fGIMEds8OMY5dKdkB0nrqQX7fG1E5mnsbvyHpMDecMUH6Yg+p1HXdgB/lLqOcFZjt/OVXPjAAApC5d1YgRYATDcxsR1zqQwiNcHdmWn\"," + + "\"format\":\"web-eid:1.0\"}", WebEidAuthToken.class); } catch (JsonProcessingException e) { throw new RuntimeException("Token parsing failed"); @@ -94,6 +96,11 @@ public static T jsonStringToBean(String jsonString, Class valueType) thro public static CertificateDTO mockPrepareRequest() { CertificateDTO certificateDTO = new CertificateDTO(); certificateDTO.setCertificate(mockCertificateInBase64()); + final SignatureAlgorithmDTO signatureAlgorithmDTO = new SignatureAlgorithmDTO(); + signatureAlgorithmDTO.setCryptoAlgorithm("RSA"); + signatureAlgorithmDTO.setHashFunction("SHA-256"); + signatureAlgorithmDTO.setPaddingScheme("PKCS1.5"); + certificateDTO.setSupportedSignatureAlgorithms(List.of(signatureAlgorithmDTO)); return certificateDTO; }