Skip to content

Commit d0142c7

Browse files
committed
fix(webauthn): address PR #287 review feedback
- Fix import ordering (alphabetical: jakarta < java < lombok < org) in WebAuthnCredential.java and WebAuthnCredentialColumnMappingTest.java - Add Javadoc rationale to byte[] fields explaining Length.LONG32 is intentional to prevent future reversion to smaller lengths - Add MIGRATION.md note for existing deployments with VARBINARY columns
1 parent 6bc18e5 commit d0142c7

3 files changed

Lines changed: 48 additions & 6 deletions

File tree

MIGRATION.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,32 @@ The `/user/updateUser` endpoint now uses `UserProfileUpdateDto`.
359359

360360
---
361361

362+
**Issue: `user_credentials` table not created on MariaDB/MySQL (WebAuthn)**
363+
364+
With `ddl-auto: update` or `create`, Hibernate previously mapped the `attestationObject` and
365+
`attestationClientDataJson` columns to `VARBINARY(65535)`. Two such columns exceed MariaDB's
366+
InnoDB 65,535-byte row-size limit, causing silent table creation failure. Symptoms include 500
367+
errors on `/user/auth-methods` or `/user/webauthn/credentials`.
368+
369+
**Solution (upgrading from a version prior to this fix):**
370+
371+
If the `user_credentials` table was never created, it will be created automatically on next
372+
startup with `ddl-auto: update` once you upgrade to this version.
373+
374+
If the table exists with `VARBINARY` columns (created on a non-MariaDB database), run:
375+
376+
```sql
377+
ALTER TABLE user_credentials
378+
MODIFY COLUMN public_key LONGBLOB NOT NULL,
379+
MODIFY COLUMN attestation_object LONGBLOB,
380+
MODIFY COLUMN attestation_client_data_json LONGBLOB;
381+
```
382+
383+
With `ddl-auto: update`, Hibernate will handle this automatically on MariaDB/MySQL. On
384+
PostgreSQL no schema change is needed — the columns map to `bytea` in both old and new versions.
385+
386+
---
387+
362388
**Issue: Java version incompatibility**
363389

364390
Spring Boot 4.0 requires Java 21.

src/main/java/com/digitalsanctuary/spring/user/persistence/model/WebAuthnCredential.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package com.digitalsanctuary.spring.user.persistence.model;
22

3-
import java.time.Instant;
4-
import org.hibernate.Length;
53
import jakarta.persistence.Column;
64
import jakarta.persistence.Entity;
75
import jakarta.persistence.FetchType;
86
import jakarta.persistence.Id;
97
import jakarta.persistence.JoinColumn;
108
import jakarta.persistence.ManyToOne;
119
import jakarta.persistence.Table;
10+
import java.time.Instant;
1211
import lombok.Data;
12+
import org.hibernate.Length;
1313

1414
/**
1515
* JPA entity for the {@code user_credentials} table. Stores WebAuthn credentials (public keys) for passkey
@@ -30,7 +30,15 @@ public class WebAuthnCredential {
3030
@JoinColumn(name = "user_entity_user_id", nullable = false)
3131
private WebAuthnUserEntity userEntity;
3232

33-
/** COSE-encoded public key (typically 77-300 bytes, RSA keys can be larger). */
33+
/**
34+
* COSE-encoded public key (typically 77-300 bytes, RSA keys can be larger).
35+
*
36+
* <p>{@code length = Length.LONG32} is intentional: it forces Hibernate to emit {@code LONGBLOB} on
37+
* MariaDB/MySQL (stored off-page, avoiding the 65,535-byte InnoDB row-size limit) while mapping to
38+
* {@code bytea} on PostgreSQL. Do not reduce this to a smaller value — doing so reintroduces the
39+
* MariaDB DDL failure described in GitHub issue #286. Do not replace with {@code @Lob}, which maps
40+
* to {@code OID} on PostgreSQL.</p>
41+
*/
3442
@Column(name = "public_key", nullable = false, length = Length.LONG32)
3543
private byte[] publicKey;
3644

@@ -58,11 +66,19 @@ public class WebAuthnCredential {
5866
@Column(name = "backup_state", nullable = false)
5967
private boolean backupState;
6068

61-
/** Attestation data from registration (can be several KB). */
69+
/**
70+
* Attestation data from registration (can be several KB).
71+
*
72+
* <p>See {@link #publicKey} for why {@code length = Length.LONG32} is used here.</p>
73+
*/
6274
@Column(name = "attestation_object", length = Length.LONG32)
6375
private byte[] attestationObject;
6476

65-
/** Client data JSON from registration (can be several KB). */
77+
/**
78+
* Client data JSON from registration (can be several KB).
79+
*
80+
* <p>See {@link #publicKey} for why {@code length = Length.LONG32} is used here.</p>
81+
*/
6682
@Column(name = "attestation_client_data_json", length = Length.LONG32)
6783
private byte[] attestationClientDataJson;
6884

src/test/java/com/digitalsanctuary/spring/user/persistence/model/WebAuthnCredentialColumnMappingTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package com.digitalsanctuary.spring.user.persistence.model;
22

33
import static org.assertj.core.api.Assertions.assertThat;
4-
import java.lang.reflect.Field;
54
import jakarta.persistence.Column;
5+
import java.lang.reflect.Field;
66
import org.hibernate.Length;
77
import org.junit.jupiter.api.DisplayName;
88
import org.junit.jupiter.params.ParameterizedTest;

0 commit comments

Comments
 (0)