How to add a custom key in Symfony 2 in-memory user provider?
providers:
administrators:
memory:
users:
admin: { password: admin, roles: [ 'ROLE_USER' ] }
If I modify the above adding an image property the user isn't able to login anymore. Really a strange issue.
providers:
administrators:
memory:
users:
admin: { password: admin, roles: [ 'ROLE_USER' ], image: "img/plh.png" }
Reason is on Error log:
PHP Fatal error: Uncaught exception 'Symfony\Component\Config\Definition\Exception\InvalidConfigurationException' with message 'Unrecognized options "image" under "security.providers.in_memory.memory.users.manage"' in ~/vendor/symfony/symfony/src/Symfony/Component/Config/Definition/ArrayNode.php:306
Check:
https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php#L562
To fix it, you could extend Configuration of the SecurityBundle:
http://symfony.com/doc/current/cookbook/bundles/prepend_extension.html
Related
I'm having some problems with lexik JWT bundle and Symfony 6.0, for swagger I use NelmioApiDocBundle.
The thing is, that every in swagger works before I decide to apply my Authorization Token (Bearer token), which is generated from lexik JWT. But once I get my token generated through /api/sign/in endpoint, and put it into the field, suddenly all endpoints stop working. Like the swagger has this loading animation, but no request comes (tested with xDebug, but also symfony profiler).
Funny thing is when I use Postman and apply the token there, I immediately get a correct response. So I'm not sure where or what's the problem, but when calling from Swagger, I can see docker debug messages saying: PHP message: [debug] Authenticator does not support the request.
I will put my configuration below. Thanks in advance.
lexik_jwt_authentication.yaml:
lexik_jwt_authentication:
secret_key: '%env(resolve:JWT_SECRET_KEY)%'
public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
pass_phrase: '%env(JWT_PASSPHRASE)%'
token_ttl: 8640000
user_id_claim: id
user_identity_field: email
security.yaml
security:
enable_authenticator_manager: true
password_hashers:
App\Entity\User:
algorithm: bcrypt
cost: 10
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/api/sign
stateless: true
provider: app_user_provider
json_login:
check_path: /api/sign/in
username_path: email
password_path: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
provider: app_user_provider
pattern: ^/api
stateless: true
jwt: ~
access_control:
- { path: ^/api/sign/, roles: PUBLIC_ACCESS }
- { path: ^/api/(doc|doc.json), roles: PUBLIC_ACCESS }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
nelmio_api_doc.yaml
nelmio_api_doc:
documentation:
servers:
- url: http://bp.project
info:
title: BP PROJECT
description: This is an awesome app!
version: 1.0.0
components:
securitySchemes:
Bearer:
type: http
scheme: bearer
bearerFormat: JWT
security:
Bearer: [ ]
areas: # to filter documented areas
path_patterns: # an array of regexps
- ^/api(?!/(doc|doc.json|docs.{_format}|{index}.{_format}|contexts/{shortName}.{_format})$) # Accepts routes under /api except ...
models: { use_jms: false }
Found out api_platform swagger and nelmio are both interacting somehow, since I added this into api_platform.yaml and the header was available in nelmio too, which now works.
swagger:
versions: [3]
api_keys:
apiKey:
name: Authorization
type: header
I've implemented an api-platform app with Symfony4 + GraphQl + axios + vuejs; all this is working as a SPA which uses a single controller action to render a template and from there all the router is handled by vue-router. So far so good.
When I'm about to secure the app(regular symfony way) all is working fine, here is the config
security:
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH ]
encoders:
Symfony\Component\Security\Core\User\User: plaintext
App\Entity\User:
algorithm: bcrypt
providers:
in_memory:
memory:
users:
administrador: { password: p#ssw0rd, roles: [ 'ROLE_USER' ] }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
tempapi: #this should not be configured
pattern: ^/api
security: false
memory:
pattern: ^/
logout: true
anonymous: true
provider: in_memory
form_login:
login_path: /login
check_path: /login
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
I think everything is well configured but when I comment the tempapi firewall and make login I'm not able to access the api, all I get is a redirection to the login page. Notice that I'm accessig the api from a view behind the firewall, so I expected to behave as a regular ajax request(because it is).
When I remove the comment and left the tempapi firewall without security I'm able to access the api but I cannot have access to the logged user credentials, roles, etc.
apollo configuration to use graphql endpoint
const httpLink = new HttpLink({
uri: '/api/graphql'
})
const cache = new InMemoryCache()
export default new ApolloClient({
link: httpLink,
cache,
connectToDevTools: true
})
axios configuration to access rest endpoint
export const backend = axios.create({
baseURL: '/api',
headers: {
'Content-Type': 'application/json'
}
})
Why is symfony dealing with async requests made behind an authenticated firewall as they were externals?. I don't have problems with CORS
Thanks in advance!
I'm using FOSUser and I would like to return an exception or simply block access to registration if user is already connected. When I'm connected, by url, I can still go to /register.
This is my access_control :
access_control:
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
I could override registration controller action and return an AccessDeniedException but I'm sure there is a better solution, with security.yml maybe ?
if you add this:
- { path: ^/register, role: ROLE_ADMIN }
then use:
php bin/console fos:user:promote user_name ROLE_ADMIN
to add "user_name" to the ROLE_ADMIN, then other users will get an Access Denied message.
I finally found the answer. I have to use Voters to check user permissions.
This is doc : http://symfony.com/doc/current/cookbook/security/voters.html
And there is great example here : http://henrik.bjrnskov.dk/symfony2-anonymous-users-access/
And this is what I have :
- { path: ^/register, role: IS_ANONYMOUS }
I am having issue with FosUserBundle,
Acctualy I followed this tutorial
http://symfony.com/doc/current/bundles/FOSUserBundle/index.html
And in the end it says You now can log in at "/app.com/app_dev.php/login!"
Here is photo
My routing file:
app:
resource: "#AppBundle/Controller/"
type: annotation
# easy_admin_bundle:
# resource: "#EasyAdminBundle/Controller/"
# type: annotation
# prefix: /admin
fos_user:
resource: "#FOSUserBundle/Resources/config/routing/all.xml"
My security file:
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
# if you are using Symfony < 2.8, use the following config instead:
# csrf_provider: form.csrf_provider
logout: true
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
Manually putting the users details into the database is likely the issue. Unless you go through the proper process you'll end up with an unencrypted password, so when you try to authenticate using bcrypt (as stated in your security file) the passwords wont match.
You have 2 options. Command line or do it programatically.
Command line creation
Have a look at the list of FOSUserBundle command line tools.
Follow the instructions for creating a user and you should have more success. I know you tried this, but follow the tutorial and have another go. Its worth trying to do this:
$ php bin/console fos:user:create adminuser --super-admin
and putting in the extra data as it asks you.
Controller creation
From a controller point of view, you need to use the fos_user.user_manager service to setup your new user.
So, something like this:
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->createUser();
then inside your form handling script:
$userManager->updateUser($user);
This will parse the plainPassword data gathered in and extracted from your form through the correct password encoder. It'll then null the plainPassword property so remains secure in the database.
So, your finished controller method might look something like this:
public function newUser( Request $request ) {
// get a blank user, you can use new User if you like but I like to use their tools seeing as they took the time to build them.
$user = $this->get('fos_user.user.manager')->createUser();
// build the form
$form = $this->createForm(UserType::class, $user);
// bind the form data (if there) to the entity.
$form->handleRequest( $request );
if ( $form->isSubmitted && $form->isValid() ) {
// this will properly encode the password, if changed, remove any plain text versions and flush into the db.
$this->get('fos_user.user.manager')->updateUser($user);
// send the user somewhere with a congrats message
} else {
// anything for invalid form;
}
return $this->render('forms/form.html.twig', [
'form' => $form->createView()
]);
}
you have to use FOS\UserBundle\Model\User::setPlainPassword() method but not setPassword()
I want to allow access to users with ROLE_ADMIN to the following path:
/admin
And only allow access to users with ROLE_CONTENT or ROLE_ADMIN to the following path:
/admin?select=pending
Here is my access control config in security.yml:
access_control:
- { path: ^/admin?select=pending, role: [ ROLE_ADMIN, ROLE_CONTENT ] }
- { path: ^/admin, role: ROLE_ADMIN }
However if I try to access to the query string path with a user with ROLE_CONTENT it gives me a 403 access denied error message.
Any suggestions on how to achieve this?