Skip to content

Commit ca29f04

Browse files
feat: add configurable identity uniqueness to registration flow
1 parent c5f6ff8 commit ca29f04

File tree

3 files changed

+441
-7
lines changed

3 files changed

+441
-7
lines changed

config/authkit.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,65 @@
8686
],
8787
],
8888

89+
/* Registration configuration.
90+
*
91+
* This section controls package-level registration behavior that should remain
92+
* configurable without requiring consumers to publish or replace form requests.
93+
*
94+
* Initial responsibilities:
95+
* - control whether the primary registration identity must be unique
96+
* - allow consumers to override the table/column used by the default uniqueness rule
97+
*
98+
* Notes:
99+
* - These settings affect only AuthKit's built-in default registration rules.
100+
* - A custom rules provider may still fully replace or reshape validation behavior.
101+
* - When uniqueness is disabled here, AuthKit will not add a default unique rule.
102+
*/
103+
'registration' => [
104+
105+
/**
106+
* Identity uniqueness enforcement.
107+
*
108+
* When enabled:
109+
* - AuthKit adds a default unique rule for the configured registration/login
110+
* identity field when that field exists in the resolved register schema.
111+
*
112+
* When disabled:
113+
* - AuthKit does not apply a default unique rule.
114+
* - Consumers may still enforce uniqueness through a custom rules provider
115+
* or at the database level.
116+
*
117+
* Recommended:
118+
* - Keep enabled for most applications.
119+
*/
120+
'enforce_unique_identity' => true,
121+
122+
/**
123+
* Identity uniqueness target.
124+
*
125+
* These values control the database table and column used by AuthKit's
126+
* default registration unique rule.
127+
*
128+
* Resolution behavior:
129+
* - table:
130+
* - null: attempt to resolve automatically from the configured auth provider model
131+
* - string: use the provided table name directly
132+
*
133+
* - column:
134+
* - null: use the configured identity field name
135+
* - string: use the provided column name directly
136+
*
137+
* Example use cases:
138+
* - custom users table name
139+
* - registering by username while authenticating through a renamed DB column
140+
* - integrating with legacy schemas
141+
*/
142+
'unique_identity' => [
143+
'table' => null,
144+
'column' => null,
145+
],
146+
],
147+
89148
/**
90149
* Routing configuration for AuthKit.
91150
*

docs/configuration.md

Lines changed: 222 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,6 @@ For example:
276276

277277
Custom normalization logic can be introduced later through actions or extension points.
278278

279-
---
280279

281280
### What this affects
282281

@@ -300,8 +299,6 @@ AuthKit uses the **schema system** to define:
300299

301300
If you want to change how the login field appears in the UI, you should modify the relevant schema configuration instead.
302301

303-
---
304-
305302
### Important note
306303

307304
Changing the identity configuration does **not** modify your database schema automatically.
@@ -312,8 +309,6 @@ If you switch from `email` to another field such as `username`, you must ensure:
312309
- your user provider can resolve users using that field
313310
- your authentication flow is aligned with the chosen identity
314311

315-
---
316-
317312
### Example: username-based authentication
318313

319314
```php
@@ -339,6 +334,228 @@ If you switch from `email` to another field such as `username`, you must ensure:
339334
],
340335
],
341336
```
337+
## Registration Configuration
338+
The `registration` section controls package-level behavior related to account creation.
339+
340+
At the moment, this section is primarily responsible for AuthKit’s default identity uniqueness behavior during registration.
341+
342+
This allows AuthKit to provide a safe default for common registration flows while still giving consumers full control when they need custom validation behavior.
343+
344+
#### Overview
345+
````php
346+
'registration' => [
347+
'enforce_unique_identity' => true,
348+
'unique_identity' => [
349+
'table' => null,
350+
'column' => null,
351+
],
352+
],
353+
````
354+
### Why this section exists
355+
In most applications, the primary registration identity should be unique.
356+
For example:
357+
358+
- an email address should usually not be reused across multiple accounts
359+
- a username should usually be unique
360+
- a phone-based identity may also need uniqueness depending on the application
361+
362+
AuthKit therefore adds a default unique validation rule for the configured identity field during registration.
363+
However, because not every application has the same schema or requirements, this behavior is configurable.
364+
365+
#### `registration.enforce_unique_identity`
366+
367+
```php
368+
'enforce_unique_identity' => true,
369+
```
370+
Controls whether AuthKit should automatically apply a default unique rule to the configured registration identity field.
371+
372+
**Behavior**
373+
374+
When set to true:
375+
376+
- AuthKit checks the configured identity field from authkit.identity.login.field
377+
- if that field exists in the resolved register schema
378+
- AuthKit adds a default unique validation rule for that field
379+
380+
When set to false:
381+
382+
- AuthKit does not apply its default identity uniqueness rule
383+
- consumers may still enforce uniqueness through:
384+
- a custom validation provider
385+
- database constraints
386+
- custom controller or action logic
387+
388+
**Recommended usage**
389+
390+
For most applications, this should remain enabled.
391+
392+
Disabling it is mainly useful when:
393+
394+
- your application handles uniqueness in a custom validation provider
395+
- your registration flow needs non-standard identity behavior
396+
- you are integrating AuthKit into a legacy schema or workflow
397+
398+
#### `registration.unique_identity.table`
399+
```php
400+
'table' => null,
401+
```
402+
403+
Defines the database table AuthKit should use when building the default unique rule for the registration identity.
404+
405+
**Resolution behavior**
406+
407+
When set to `null`:
408+
409+
-AuthKit attempts to resolve the table automatically from the configured auth provider model
410+
411+
When set to a `string`:
412+
413+
- AuthKit uses that table name directly
414+
415+
**Example**
416+
417+
```php
418+
'registration' => [
419+
'unique_identity' => [
420+
'table' => 'users',
421+
],
422+
],
423+
```
424+
425+
This is useful when:
426+
427+
- your user data lives in a custom table
428+
- you want to avoid relying on automatic provider-based resolution
429+
- your application uses a legacy schema
430+
431+
#### `registration.unique_identity.column`
432+
```php
433+
'column' => null,
434+
```
435+
436+
Defines the database column AuthKit should use for the default registration identity uniqueness rule.
437+
438+
**Resolution behavior**
439+
440+
When set to `null`:
441+
442+
- AuthKit uses the configured identity field from authkit.identity.login.field
443+
444+
When set to a `string`:
445+
446+
- AuthKit uses that column name directly
447+
448+
**Example**
449+
```php
450+
451+
'registration' => [
452+
'unique_identity' => [
453+
'column' => 'email_address',
454+
],
455+
],
456+
```
457+
This is useful when:
458+
459+
- your registration identity field maps to a differently named database column
460+
- your application uses a legacy schema
461+
- your UI field naming and persistence column naming are intentionally different
462+
463+
### How this works with identity configuration
464+
465+
The registration uniqueness logic builds on top of the identity configuration.
466+
467+
For example, if you set:
468+
469+
```php
470+
'identity' => [
471+
'login' => [
472+
'field' => 'username',
473+
],
474+
],
475+
````
476+
then AuthKit will treat username as the canonical identity field for registration uniqueness, unless you explicitly override the column in:
477+
478+
`registration.unique_identity.column`
479+
This means: `identity.login.field` defines the canonical identity key registration controls whether and how uniqueness is enforced for that identity during registration
480+
481+
## Important note
482+
483+
This configuration affects only AuthKit’s built-in default registration validation behavior.
484+
485+
It does not prevent you from replacing or extending registration validation through a custom validation provider.
486+
487+
If a custom provider is configured for the register context, you remain fully in control of the final validation rules used by your application.
488+
489+
**Example: default email-based uniqueness**
490+
491+
```php
492+
'identity' => [
493+
'login' => [
494+
'field' => 'email',
495+
],
496+
],
497+
498+
'registration' => [
499+
'enforce_unique_identity' => true,
500+
'unique_identity' => [
501+
'table' => null,
502+
'column' => null,
503+
],
504+
],
505+
```
506+
With this configuration:
507+
508+
- AuthKit uses email as the primary identity field
509+
- AuthKit attempts to resolve the user table automatically
510+
- AuthKit applies a default unique rule to the email field during registration
511+
512+
**Example: username-based registration**
513+
514+
```php
515+
'identity' => [
516+
'login' => [
517+
'field' => 'username',
518+
'label' => 'Username',
519+
'input_type' => 'text',
520+
'autocomplete' => 'username',
521+
'normalize' => 'trim',
522+
],
523+
],
524+
525+
'registration' => [
526+
'enforce_unique_identity' => true,
527+
'unique_identity' => [
528+
'table' => 'users',
529+
'column' => 'username',
530+
],
531+
],
532+
```
533+
With this configuration:
534+
535+
- AuthKit uses username as the canonical identity
536+
- registration applies uniqueness against users.username
537+
538+
**Example: disable default uniqueness**
539+
540+
```php
541+
'registration' => [
542+
'enforce_unique_identity' => false,
543+
],
544+
```
545+
With this configuration:
546+
547+
- AuthKit does not apply its built-in unique rule
548+
- you are responsible for uniqueness behavior elsewhere
549+
550+
This can be appropriate when uniqueness is enforced through a custom register validation provider or another application-specific rule layer.
551+
552+
### Best practice
553+
554+
- keep identity uniqueness enabled in most production applications
555+
- override the table or column only when your schema requires it
556+
- use a custom validation provider when your registration rules go beyond AuthKit defaults
557+
- keep database-level unique indexes aligned with your validation behavior
558+
342559
## Routes Configuration
343560

344561
The routes configuration controls the top-level structure used when AuthKit registers its routes.

0 commit comments

Comments
 (0)