Security & Users

Types of authentication

JWT Tokens for Users

This bundle uses LexikJWTAuthenticationBundle with some additions.

The API will refresh the token based on your bundle configuration. There is no refresh token returned to your final application. These are secrets which are stored internally. When an expired JWT token is used, the API will return a new JWT token in a Set-Cookie header.

Getting started

Configure security and firewalls

As described here - generate the keys for JWTs. (You fill find the passphrase that has been generated in your environment variables by the flex recipe for LexikJWTAuthenticationBundle)

mkdir -p config/jwt
openssl genpkey -out config/jwt/private.pem -aes256 -algorithm rsa -pkeyopt rsa_keygen_bits:4096
openssl pkey -in config/jwt/private.pem -out config/jwt/public.pem -pubout

Configure your security/firewall. Below is a recommended configuration, but please check it and ensure it meets your needs:

# /config/packages/security.yaml
security:
    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
    encoders:
        Silverback\ApiComponentsBundle\Entity\User\AbstractUser:
            algorithm: auto
    providers:
        user_provider:
            entity:
                class: Silverback\ApiComponentsBundle\Entity\User\AbstractUser
        jwt:
            lexik_jwt:
                class: Silverback\ApiComponentsBundle\Entity\User\AbstractUser
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        login:
            pattern:  ^/login
            stateless: true
            anonymous: lazy
            provider: user_provider
            user_checker: Silverback\ApiComponentsBundle\Security\UserChecker
            json_login:
                check_path: /login
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure
        main:
            pattern:   ^/
            stateless: true
            anonymous: lazy
            provider: jwt
            logout:
                path: /logout
                # Required for Symfony < 5.1
                # handlers: [silverback.security.logout_handler]
            guard:
                authenticators:
                    - lexik_jwt_authentication.jwt_token_authenticator
            # https://symfony.com/doc/current/security/impersonating_user.html
            switch_user: true
    access_control:
        - { path: ^/token/refresh, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/password/(reset|update), roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [POST] }
        # The 2 options below prevents anonymous users from making changes to your API resources while allowing form submissions
        - { path: ^/component/forms/(.*)/submit, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [POST, PATCH] }
        - { path: ^/, roles: IS_AUTHENTICATED_FULLY, methods: [POST, PUT, PATCH, DELETE] }

JWT Authentication

By using the flex recipe, you will already have a pre-configured App\Entity\User entity in your project.

By default, although there is a column for the username and one for the email address in the database, these are kept synchronised by the User class. You can modify the class to suit your needs. Just be sure to extend the class Silverback\ApiComponentsBundle\Entity\User\AbstractUser.

The repository automatically configured for your User entity will look up users by their email address or username properties.

If you do not use Flex, or you create a difference User class you must configure this in the bundle:

silverback_api_components:
  user:
    class_name: App\Entity\User
lexik_jwt_authentication:
    secret_key: '%env(resolve:JWT_SECRET_KEY)%'
    public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
    pass_phrase: '%env(JWT_PASSPHRASE)%'
    set_cookies:
        api_components:
            lifetime: 604800 # 1 week

Refresh token configuration

This documentation is incomplete. We may add the set_cookies configuration for lexik_jwt_authentication automatically based on the cookie name below. TBD.

silverback_api_components:
    refresh_token:
        handler_id: silverback.api_components.refresh_token.storage.doctrine
        options:
            class: Silverback\ApiComponentsBundle\Tests\Functional\TestBundle\Entity\RefreshToken
        cookie_name: api_components
        ttl: 604800 # 1 week

Table of contents


Copyright © 2018-2020 Silverback IS. Distributed by an MIT license.