diff --git a/README.md b/README.md index 9d16ea9f..5d747c1f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ More information about the Web eID project is available on the project [website] # Quickstart -Complete the steps below to add support for secure authentication with eID cards to your Java web application back end. Instructions for the front end are available [here](https://github.com/web-eid/web-eid.js). +Complete the steps below to add support for secure authentication with eID cards to your Java web application back end. Instructions for the front end are available [here](https://github.com/web-eid/web-eid.js). If your application already uses Web eID and you only need to add the mobile flow, see [Adding Web eID for Mobile support to an existing integration](#adding-web-eid-for-mobile-support-to-an-existing-integration). A Java web application that uses Maven or Gradle to manage packages is needed for running this quickstart. Examples are for Maven, but they are straightforward to translate to Gradle. @@ -183,7 +183,7 @@ public final class WebEidChallengeNonceFilter extends OncePerRequestFilter { } ``` -The `WebEidMobileAuthInitFilter` handles `/auth/mobile/init` requests for authentication flows using **Web eID token format v1.1**. It generates a challenge nonce and returns a deep link URI that embeds both the challenge nonce and the authentication endpoint required for initiating the v1.1 flow. +The `WebEidMobileAuthInitFilter` handles `/auth/mobile/init` requests for mobile authentication. It generates a challenge nonce and returns a deep link URI containing the challenge nonce, the login page URL and an optional request for a signing certificate. The response uses token format `web-eid:1.1` when a signing certificate is requested, or `web-eid:1.0` for authentication only. See the full implementation [here](example/src/main/java/eu/webeid/example/security/WebEidMobileAuthInitFilter.java). ```java @@ -252,9 +252,21 @@ try { ... ``` +## Adding Web eID for Mobile support to an existing integration + +Reuse your existing challenge nonce generator and store, trusted CA configuration, token validation and authorization logic. The mobile flow adds an App Link/Universal Link that opens the RIA DigiDoc app and a login page that receives the response in its URL fragment and posts the token to your back end. Authentication-only responses use `web-eid:1.0`; requesting a signing certificate with `getSigningCertificate=true` requires a validator that supports `web-eid:1.1`. The validator configuration stays the same. + +1. Add `POST /auth/mobile/init` to generate and store a challenge nonce and return `authUri`: `https://id.eesti.ee/auth#`, where the payload is Base64-encoded JSON containing `challenge`, `loginUri` and optionally `getSigningCertificate` ([init filter](example/src/main/java/eu/webeid/example/security/WebEidMobileAuthInitFilter.java)). Set `web-eid-mobile.base-request-uri` to `https://id.eesti.ee` for the RIA DigiDoc app; the example defaults to the development scheme `web-eid-mobile://`. Configure `web-eid-mobile.request-signing-cert` as needed and enable `web-eid-mobile.enabled` if previously disabled. +2. Serve `GET /auth/mobile/login` at an HTTPS `loginUri` on the validator's configured `web-eid-auth-token.validation.local-origin`. Its script must decode the response, handle errors and post `authToken` to the existing `POST /auth/login` endpoint ([login page](example/src/main/resources/templates/webeid-login.html), [payload parser](example/src/main/resources/static/js/payload.js)). Retrieve and consume the session's unexpired challenge nonce, validate the token, apply your authorization checks and establish the authenticated session as before. +3. Use `Secure`, `HttpOnly`, `SameSite=Lax` for the pre-authentication session cookie so it accompanies the return from the app. Keep CSRF protection on POST endpoints and protect the login page against XSS. Callback fragments are untrusted input; the CSRF token alone does not authenticate them. See the architecture document's [security assumptions](https://github.com/web-eid/web-eid-for-mobile-architecture-doc#security-assumptions). +4. Add a mobile login button that calls the init endpoint and opens the returned `authUri` ([front end](example/src/main/resources/templates/index.html)). Keep the existing desktop login control. + +Optional mobile signing is demonstrated by [SigningController](example/src/main/java/eu/webeid/example/web/rest/SigningController.java) and [MobileSigningService](example/src/main/java/eu/webeid/example/service/MobileSigningService.java). A validated signing certificate returned during authentication can be stored with its supported algorithms to skip the separate certificate request. Check that the signing certificate belongs to the authenticated user before preparing the data to sign. + # Table of contents - [Quickstart](#quickstart) + - [Adding Web eID for Mobile support to an existing integration](#adding-web-eid-for-mobile-support-to-an-existing-integration) - [Introduction](#introduction) - [Authentication token format](#authentication-token-format) - [Authentication token validation](#authentication-token-validation) diff --git a/example/README.md b/example/README.md index c78bba33..865970be 100644 --- a/example/README.md +++ b/example/README.md @@ -80,6 +80,7 @@ When the application has started, open the _ngrok_ HTTPS URL in your preferred w + [Overview of the source code](#overview-of-the-source-code) + [Configuration](#configuration) + [Integration with Web eID components](#integration-with-web-eid-components) + + [Adding Web eID for Mobile support to an existing integration](#adding-web-eid-for-mobile-support-to-an-existing-integration) + [Integration with DigiDoc4j components](#integration-with-digidoc4j-components) - [Using the Certificates' *Authority Information Access* (AIA) extension in DigiDoc4j](#using-the-certificates-authority-information-access-aia-extension-in-digidoc4j) - [Using DigiDoc4j in test mode with the `dev` profile](#using-digidoc4j-in-test-mode-with-the-dev-profile) @@ -158,6 +159,14 @@ Detailed overview of Java code changes required for integrating Web eID authenti 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. +### Adding Web eID for Mobile support to an existing integration + +To add mobile authentication to an existing integration, follow the [library migration guide](../README.md#adding-web-eid-for-mobile-support-to-an-existing-integration). This example adds `POST /auth/mobile/init` through `WebEidMobileAuthInitFilter` and `GET /auth/mobile/login` through `WebEidLoginPageGeneratingFilter`, using `templates/webeid-login.html` and `static/js/payload.js`. Both login flows submit to `POST /auth/login` and share `WebEidAuthenticationProvider`. + +Configure `web-eid-mobile.base-request-uri`, `web-eid-mobile.request-signing-cert` and `web-eid-auth-token.validation.local-origin` in `application-{dev,prod}.yaml`. Set the base request URI to `https://id.eesti.ee` for the RIA DigiDoc app; both profiles currently use `web-eid-mobile://` for development. `web-eid-mobile.enabled` selects the mobile-enabled security filter chain in `ApplicationConfiguration`. The mobile button is in `templates/index.html`; `SameSiteCookieConfiguration` sets `SameSite=Lax`, and `application.yaml` enables forwarded HTTPS detection behind a reverse proxy. Spring Security CSRF protection remains enabled. + +For optional mobile signing, see `SigningController`, `MobileSigningService` and `templates/webeid-callback.html`. `WebEidAuthentication` stores a signing certificate from the validated token when requested; `SigningService.prepareContainer()` checks its subject ID against the authenticated user's ID. + ### 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/eu/webeid/example/{service,web/rest}` directories. diff --git a/example/src/test/java/eu/webeid/example/WebApplicationTest.java b/example/src/test/java/eu/webeid/example/WebApplicationTest.java index 8b2ed8ec..901aa3cf 100644 --- a/example/src/test/java/eu/webeid/example/WebApplicationTest.java +++ b/example/src/test/java/eu/webeid/example/WebApplicationTest.java @@ -29,6 +29,7 @@ import eu.webeid.security.authtoken.WebEidAuthToken; import eu.webeid.security.challenge.ChallengeNonce; import eu.webeid.security.util.DateAndTime; +import eu.webeid.security.validator.certvalidators.SubjectCertificateNotRevokedValidator; import mockit.Mock; import mockit.MockUp; import org.digidoc4j.impl.asic.AsicSignatureFinalizer; @@ -49,6 +50,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import java.security.cert.X509Certificate; import java.util.stream.Stream; import static eu.webeid.example.testutil.ObjectMother.VALID_AUTH_TOKEN; @@ -101,6 +103,15 @@ public void validateOcspResponse(XadesSignature xadesSignature) { } }; + new MockUp() { + @Mock + public void validateCertificateNotRevoked(X509Certificate subjectCertificate) { + // Do not call real OCSP service in tests. The test certificates have expired, so the + // validation clock is mocked to a date in the past, but OCSP responses are always + // current, which makes the OCSP response time and responder certificate checks fail. + } + }; + MockHttpSession session = new MockHttpSession(); session.setAttribute("challenge-nonce", new ChallengeNonce(ObjectMother.VALID_CHALLENGE_NONCE, DateAndTime.utcNow().plusMinutes(1))); diff --git a/src/main/java/eu/webeid/security/validator/AuthTokenValidatorImpl.java b/src/main/java/eu/webeid/security/validator/AuthTokenValidatorImpl.java deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/eu/webeid/security/validator/certvalidators/SubjectCertificateValidator.java b/src/main/java/eu/webeid/security/validator/certvalidators/SubjectCertificateValidator.java index 08eccdf8..aed25aec 100644 --- a/src/main/java/eu/webeid/security/validator/certvalidators/SubjectCertificateValidator.java +++ b/src/main/java/eu/webeid/security/validator/certvalidators/SubjectCertificateValidator.java @@ -29,7 +29,7 @@ /** * Validators perform the actual user certificate validation actions. *

- * They are used by AuthTokenValidatorImpl and are not part of the public API. + * They are used by AuthTokenVersionValidatorFactory and are not part of the public API. */ @FunctionalInterface public interface SubjectCertificateValidator {