Security — authentication and authorization
Who this is for
Pionia Shop already lists products. Now you need login and clear rules for who may create catalog rows or place orders. For attribute-only how-tos, start with Protecting actions. This page covers backends, secrets, and custom authentication classes.
What you will learn
- What an authentication backend does
- How to keep signing secrets out of git
- When to use built-in JWT vs
make:auth - How attributes and in-method checks fit together
Before you start
- Shop tutorial Step 7 — catalog writes work
- A place for secrets in
environment/.env
Two moments in every request
- Identify — backends look at headers. The first match fills
$this->auth()(usuallyJwtAuthentication). - Authorize — attributes on the service/method decide if this action may run.
flowchart TD Req[HTTP request] --> Backends[Auth backends] Backends -->|recognized| User["$this->auth()"] Backends -->|unknown| Empty[no user] User --> Attr["#[Authenticated] / #[Can]"] Empty --> Attr Attr -->|no| Stop[401 or 403] Attr -->|yes| Action[Your action]
Secrets stay in .env
| Do | Don’t |
|---|---|
Put JWT_SECRET in .env | Commit production secrets |
| Use placeholders in tutorials | Return password hashes in returnData |
| Rotate leaked values | Reuse sample keys from screenshots |
php pionia shell
# secure_random_hex(32);Usual path: JWT
[app_authentications]
jwt = "Pionia\Auth\JwtAuthentication"Issue tokens in customer.login with jwt_encode(). Full guide: JWT authentication.
Custom backend
Sessions, partner API keys, or a proxy that already authenticated the user:
php pionia make:auth ApiKeyReturn a ContextUserObject or null. Register under [app_authentications]. Order matters — first success wins.
After identify: authorize
#[Authenticated(except: ['login', 'register'])]
class CustomerService extends Service { /* … */ }Ownership checks (“only cancel your own order”) stay inside the method with $this->auth(). Walkthrough: Protecting actions.
| Helper | Meaning |
|---|---|
$this->auth() | Current user context |
$this->mustAuthenticate() | Require login (401) |
$this->can('…') | One permission |
$this->canAny / canAll | Any / all permissions |
Common mistakes
- Backend class exists but missing from
[app_authentications] - Locking
login/register - Permission string typos → quiet 403s
- Scaffolding a custom JWT class when
JwtAuthenticationalready fits
What’s next
Protecting actions
Shop-focused attribute guide.
JWT authentication
customer.login tokens.
Security utilities
hash_password and more.