I know it's only half an answer but I currently do this with login, but not registration (I don't need it).
I am using Symfony 4 and flex, but it should work on 3.4 I think. I am also using json.
Bundles
Bundles I use for this (on top of fosuser etc):
- jms/serializer-bundle
- lexik/jwt-authentication-bundle
- friendsofsymfony/rest-bundle
Config
Fos Rest
fos_rest:
body_listener: true
param_fetcher_listener: force
format_listener:
enabled: true
rules:
- { path: ^/, priorities: [ json ], fallback_format: json, prefer_extension: true }
view:
view_response_listener: 'force'
formats:
json: true
xml: false
rss: false
mime_types:
json: ['application/json', 'application/x-json']
routing_loader:
default_format: json
include_format: false
exception:
enabled: true
Fos User
fos_user:
db_driver: orm
firewall_name: api
user_class: App\Entity\User
from_email:
address: [email protected]
sender_name: Admin
JMS Serializer
jms_serializer:
visitors:
xml:
format_output: '%kernel.debug%'
Lexik JWT
You need you generate tokens and put their location in your .env file. More info and a guide here.
lexik_jwt_authentication:
private_key_path: '%kernel.project_dir%/%env(JWT_PRIVATE_KEY_PATH)%'
public_key_path: '%kernel.project_dir%/%env(JWT_PUBLIC_KEY_PATH)%'
pass_phrase: '%env(JWT_PASSPHRASE)%'
token_ttl: 3600 #whatever you like
token_extractors:
authorization_header: ~
cookie: ~
query_parameter: ~
Security
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
encoders:
FOS\UserBundle\Model\UserInterface: sha512 #probably use bcrypt
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api_login:
pattern: ^/login
stateless: true
anonymous: true
form_login:
check_path: /login
require_previous_session: false
username_parameter: username
password_parameter: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/
stateless: true
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
access_control:
- { path: ^/, role: IS_AUTHENTICATED_FULLY }
Routes
login:
type: rest
resource: App\Controller\LoginController
Controller
I made a loginController that is really just a placeholder to override the route
<?php
namespace App\Controller;
use FOS\RestBundle\Controller\Annotations;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Routing\ClassResourceInterface;
use FOS\RestBundle\Controller\Annotations\RouteResource;
/**
* @RouteResource("login", pluralize=false)
*/
class LoginController extends FOSRestController implements ClassResourceInterface
{
public function postAction()
{
throw new \DomainException('You should never see this');
}
}
Testing it
You can fire a POST request to /login and it should return a token!
{
"username": "my_user",
"password": "passw0rd"
}
Registration
I haven't actually done this but I have a simple enough idea...
Open a route to registration in your security.yaml
security:
firewalls:
api_register:
pattern: ^/register
anonymous: true
access_control:
- { path: ^/register$, role: IS_AUTHENTICATED_ANONYMOUSLY }
Register the route
registration:
type: rest
resource: App\Controller\RegistrationController
Write the controller method
- Get the request data
- User the FosUserManager to create a new user
- https://symfony.com/doc/current/bundles/FOSUserBundle/user_manager.html