|
| 1 | +# Java Reference Client |
| 2 | + |
| 3 | +The [`mobileid-client-java`](https://github.com/MobileID-Strong-Authentication/mobileid-client-java) repository provides the official Java reference implementation for the Mobile ID REST API (and SOAP API). It is designed for Java 8+ projects that need secure authentication and authorization using Swisscom Mobile ID. |
| 4 | + |
| 5 | +The client library handles all the complexity of mTLS connections, request construction, response parsing, async polling, and signature validation — letting you focus on integrating Mobile ID into your application. |
| 6 | + |
| 7 | +## Features |
| 8 | + |
| 9 | +- **Synchronous and asynchronous** signature requests with polling |
| 10 | +- **Signature receipt** delivery to mobile users |
| 11 | +- **Profile queries** (account status, capabilities, certificate info) |
| 12 | +- **Signature validation** (certificate path, signature integrity, DTBS matching) |
| 13 | +- **Thread-safe** — create once, reuse across your application |
| 14 | +- **Connection pooling** for efficient resource usage |
| 15 | +- **HTTP proxy support** with optional authentication |
| 16 | + |
| 17 | +## Getting the Library |
| 18 | + |
| 19 | +### Maven |
| 20 | + |
| 21 | +```xml |
| 22 | +<dependency> |
| 23 | + <groupId>ch.mobileid.mid-java-client</groupId> |
| 24 | + <artifactId>mid-java-client-rest</artifactId> |
| 25 | + <version>1.5.7</version> |
| 26 | +</dependency> |
| 27 | +``` |
| 28 | + |
| 29 | +### Gradle |
| 30 | + |
| 31 | +```groovy |
| 32 | +dependencies { |
| 33 | + implementation 'ch.mobileid.mid-java-client:mid-java-client-rest:1.5.7' |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +::: tip |
| 38 | +Check the [Releases page](https://github.com/MobileID-Strong-Authentication/mobileid-client-java/releases) for the latest version. |
| 39 | +The library is also available on [Maven Central](https://search.maven.org/search?q=ch.mobileid). |
| 40 | +::: |
| 41 | + |
| 42 | +## Quick Start |
| 43 | + |
| 44 | +### 1. Configure the Client |
| 45 | + |
| 46 | +Create a `ClientConfiguration` with your AP credentials and TLS settings. This is done **once** per application lifetime. |
| 47 | + |
| 48 | +```java |
| 49 | +import ch.swisscom.mid.client.config.*; |
| 50 | +import ch.swisscom.mid.client.impl.MIDClientImpl; |
| 51 | +import ch.swisscom.mid.client.MIDClient; |
| 52 | + |
| 53 | +ClientConfiguration config = new ClientConfiguration(); |
| 54 | +config.setProtocolToRest(); |
| 55 | +config.setApId("mid://id-received-from-swisscom"); |
| 56 | +config.setApPassword("pass-received-from-swisscom"); |
| 57 | + |
| 58 | +// Service endpoint |
| 59 | +UrlsConfiguration urls = config.getUrls(); |
| 60 | +urls.setAllServiceUrlsTo( |
| 61 | + DefaultConfiguration.DEFAULT_INTERNET_BASE_URL |
| 62 | + + DefaultConfiguration.REST_ENDPOINT_SUB_URL); |
| 63 | + |
| 64 | +// mTLS client certificate |
| 65 | +TlsConfiguration tls = config.getTls(); |
| 66 | +tls.setKeyStoreFile("keystore.jks"); |
| 67 | +tls.setKeyStorePassword("secret"); |
| 68 | +tls.setKeyStoreKeyPassword("secret"); |
| 69 | +tls.setKeyStoreCertificateAlias("mid-cert"); |
| 70 | +tls.setTrustStoreFile("truststore.jks"); |
| 71 | +tls.setTrustStorePassword("secret"); |
| 72 | + |
| 73 | +// HTTP timeouts |
| 74 | +HttpConfiguration http = config.getHttp(); |
| 75 | +http.setConnectionTimeoutInMs(20_000); |
| 76 | +http.setResponseTimeoutInMs(100_000); |
| 77 | + |
| 78 | +// Create the client (thread-safe, reusable) |
| 79 | +MIDClient client = new MIDClientImpl(config); |
| 80 | +``` |
| 81 | + |
| 82 | +::: warning |
| 83 | +Call `client.close()` when your application shuts down to properly release resources. Do **not** close it after each request. |
| 84 | +::: |
| 85 | + |
| 86 | +### 2. Request a Synchronous Signature |
| 87 | + |
| 88 | +```java |
| 89 | +import ch.swisscom.mid.client.model.*; |
| 90 | + |
| 91 | +SignatureRequest request = new SignatureRequest(); |
| 92 | +request.setUserLanguage(UserLanguage.ENGLISH); |
| 93 | +request.getDataToBeSigned().setData("Bank ACME: Confirm login (REF-8F2K)"); |
| 94 | +request.getMobileUser().setMsisdn("41791234567"); |
| 95 | +request.setSignatureProfile(SignatureProfiles.DEFAULT_PROFILE); |
| 96 | +request.addAdditionalService(new GeofencingAdditionalService()); |
| 97 | + |
| 98 | +SignatureResponse response = client.requestSyncSignature(request); |
| 99 | +``` |
| 100 | + |
| 101 | +### 3. Request an Asynchronous Signature with Polling |
| 102 | + |
| 103 | +For better control and user experience, use the async flow with status polling: |
| 104 | + |
| 105 | +```java |
| 106 | +SignatureRequest request = new SignatureRequest(); |
| 107 | +request.setUserLanguage(UserLanguage.ENGLISH); |
| 108 | +request.getDataToBeSigned().setData("Bank ACME: Confirm login (REF-8F2K)"); |
| 109 | +request.getMobileUser().setMsisdn("41791234567"); |
| 110 | +request.setSignatureProfile(SignatureProfiles.DEFAULT_PROFILE); |
| 111 | + |
| 112 | +SignatureResponse response = client.requestAsyncSignature(request); |
| 113 | + |
| 114 | +// Poll until the signature completes or fails |
| 115 | +while (response.getStatus().getStatusCode() == StatusCode.REQUEST_OK || |
| 116 | + response.getStatus().getStatusCode() == StatusCode.OUTSTANDING_TRANSACTION) { |
| 117 | + Thread.sleep(5000); |
| 118 | + response = client.pollForSignatureStatus(response.getTracking()); |
| 119 | +} |
| 120 | + |
| 121 | +if (response.getStatus().getStatusCode() == StatusCode.SIGNATURE) { |
| 122 | + // Signature successful — validate and proceed |
| 123 | +} |
| 124 | +``` |
| 125 | + |
| 126 | +### 4. Send a Receipt |
| 127 | + |
| 128 | +After a successful signature, send a receipt message to the mobile user: |
| 129 | + |
| 130 | +```java |
| 131 | +ReceiptRequest receiptRequest = new ReceiptRequest(); |
| 132 | +receiptRequest.getMessageToBeDisplayed().setData("Login completed successfully"); |
| 133 | +receiptRequest.setStatusCode(StatusCode.REQUEST_OK); |
| 134 | +receiptRequest.addReceiptRequestExtension(); |
| 135 | + |
| 136 | +ReceiptResponse receiptResponse = client.requestSyncReceipt( |
| 137 | + response.getTracking(), receiptRequest); |
| 138 | +``` |
| 139 | + |
| 140 | +### 5. Query a User Profile |
| 141 | + |
| 142 | +Check if a user is registered and what methods are available: |
| 143 | + |
| 144 | +```java |
| 145 | +ProfileRequest request = new ProfileRequest(); |
| 146 | +request.getMobileUser().setMsisdn("41791234567"); |
| 147 | +request.setExtensionParamsToAllValues(); |
| 148 | + |
| 149 | +ProfileResponse response = client.requestProfile(request); |
| 150 | +``` |
| 151 | + |
| 152 | +## Signature Validation |
| 153 | + |
| 154 | +After acquiring a mobile signature, you should validate it to ensure the signing certificate is valid, the certificate path is trusted, and the signed data matches what was requested. |
| 155 | + |
| 156 | +```java |
| 157 | +import ch.swisscom.mid.client.crypto.*; |
| 158 | + |
| 159 | +// Configure the trust store for certificate path validation |
| 160 | +SignatureValidationConfiguration svConfig = new SignatureValidationConfiguration(); |
| 161 | +svConfig.setTrustStoreFile("signature-validation-truststore.jks"); |
| 162 | +svConfig.setTrustStoreType("jks"); |
| 163 | +svConfig.setTrustStorePassword("secret"); |
| 164 | + |
| 165 | +// Validate the signature |
| 166 | +SignatureValidator validator = new SignatureValidatorImpl(svConfig); |
| 167 | +SignatureValidationResult result = validator.validateSignature( |
| 168 | + response.getBase64Signature(), |
| 169 | + request.getDataToBeSigned().getData(), |
| 170 | + null |
| 171 | +); |
| 172 | + |
| 173 | +if (result.isValidationSuccessful()) { |
| 174 | + String midSerialNumber = result.getMobileIdSerialNumber(); |
| 175 | + // Store and compare the serial number for strong 2FA assurance |
| 176 | +} else { |
| 177 | + // Inspect what failed |
| 178 | + System.out.println("Cert path valid: " + result.isSignerCertificatePathValid()); |
| 179 | + System.out.println("Cert valid: " + result.isSignerCertificateValid()); |
| 180 | + System.out.println("Signature valid: " + result.isSignatureValid()); |
| 181 | + System.out.println("DTBS matching: " + result.isDtbsMatching()); |
| 182 | +} |
| 183 | +``` |
| 184 | + |
| 185 | +See [Best Practices — Signature Response](/rest-api-guide/best-practices#signature-response) for the full validation checklist. |
| 186 | + |
| 187 | +## Error Handling |
| 188 | + |
| 189 | +The client uses structured exceptions to communicate failures: |
| 190 | + |
| 191 | +```java |
| 192 | +import ch.swisscom.mid.client.MIDFlowException; |
| 193 | +import ch.swisscom.mid.client.config.ConfigurationException; |
| 194 | + |
| 195 | +try { |
| 196 | + SignatureResponse response = client.requestSyncSignature(request); |
| 197 | + // handle success |
| 198 | +} catch (MIDFlowException e) { |
| 199 | + // Communication or business-level failure |
| 200 | + Fault fault = e.getFault(); |
| 201 | + StatusCode code = fault.getStatusCode(); |
| 202 | + FailureReason reason = fault.getFailureReason(); |
| 203 | + String detail = fault.getStatusDetail(); |
| 204 | + |
| 205 | + switch (code) { |
| 206 | + case USER_CANCEL: |
| 207 | + // User cancelled on their phone |
| 208 | + break; |
| 209 | + case EXPIRED_TRANSACTION: |
| 210 | + // User didn't respond in time |
| 211 | + break; |
| 212 | + case PIN_NR_BLOCKED: |
| 213 | + // User's Mobile ID PIN is blocked |
| 214 | + break; |
| 215 | + case UNAUTHORIZED_ACCESS: |
| 216 | + // Check TLS certificate and AP ID configuration |
| 217 | + break; |
| 218 | + default: |
| 219 | + // See Status and Fault Codes for the full list |
| 220 | + break; |
| 221 | + } |
| 222 | +} catch (ConfigurationException e) { |
| 223 | + // Invalid client configuration (keystore, truststore, etc.) |
| 224 | +} |
| 225 | +``` |
| 226 | + |
| 227 | +See [Status and Fault Codes](/rest-api-guide/status-fault-codes) for the complete reference. |
| 228 | + |
| 229 | +## Per-Request AP Credentials |
| 230 | + |
| 231 | +If a single client instance serves multiple Application Providers, you can override the AP ID and password per request: |
| 232 | + |
| 233 | +```java |
| 234 | +SignatureRequest request = new SignatureRequest(); |
| 235 | +request.setOverrideApId("custom-ap-id"); |
| 236 | +request.setOverrideApPassword("custom-ap-password"); |
| 237 | +// ... remaining request setup |
| 238 | +``` |
| 239 | + |
| 240 | +These overridden credentials are automatically carried into the tracking object used for async polling. |
| 241 | + |
| 242 | +## Logging |
| 243 | + |
| 244 | +The client uses SLF4J with the following logger hierarchy: |
| 245 | + |
| 246 | +| Logger | Purpose | |
| 247 | +|--------|---------| |
| 248 | +| `ch.swisscom.mid.client` | General client activity | |
| 249 | +| `ch.swisscom.mid.client.config` | Configuration-related activity | |
| 250 | +| `ch.swisscom.mid.client.protocol` | Protocol-level communication | |
| 251 | +| `ch.swisscom.mid.client.requestResponse` | Request/response messages (large data stripped) | |
| 252 | +| `ch.swisscom.mid.client.fullRequestResponse` | Full request/response messages (including Base64 data) | |
| 253 | + |
| 254 | +::: tip |
| 255 | +Set `ch.swisscom.mid.client.requestResponse` to `DEBUG` for development and troubleshooting. Avoid enabling `fullRequestResponse` in production as it logs all certificate and signature data. |
| 256 | +::: |
| 257 | + |
| 258 | +## Command-Line Interface |
| 259 | + |
| 260 | +The client also ships as a CLI tool for quick testing. Download the full package from the [Releases page](https://github.com/MobileID-Strong-Authentication/mobileid-client-java/releases). |
| 261 | + |
| 262 | +```bash |
| 263 | +# Generate sample configuration files |
| 264 | +./bin/mid-client.sh -init |
| 265 | + |
| 266 | +# Query a user profile |
| 267 | +./bin/mid-client.sh -profile-query -msisdn 41791234567 |
| 268 | + |
| 269 | +# Request a signature (async with receipt) |
| 270 | +./bin/mid-client.sh -sign -msisdn=41791234567 -lang=en \ |
| 271 | + -dtbs "Bank ACME: Confirm login" -receipt |
| 272 | + |
| 273 | +# Use verbose logging for debugging |
| 274 | +./bin/mid-client.sh -sign -msisdn=41791234567 -lang=en \ |
| 275 | + -dtbs "Bank ACME: Confirm login" -vv |
| 276 | +``` |
| 277 | + |
| 278 | +## Further Resources |
| 279 | + |
| 280 | +- [GitHub Repository](https://github.com/MobileID-Strong-Authentication/mobileid-client-java) — Source code, full documentation, and releases |
| 281 | +- [Configuration Guide](https://github.com/MobileID-Strong-Authentication/mobileid-client-java/blob/main/docs/configure-the-client.md) — Detailed configuration reference |
| 282 | +- [Proxy Configuration](https://github.com/MobileID-Strong-Authentication/mobileid-client-java/blob/main/docs/configure-proxy-connection.md) — HTTP proxy setup |
| 283 | +- [Troubleshooting](/rest-api-guide/troubleshooting) — Common problems and solutions |
0 commit comments