I would have liked in Symfony2 "v2.1" a page that can be accessed without authentication and Authenticated.
I used the anonymous, but here is a token of the Authenticated User Anonymous and not be proper token.
Does anyone have a solution
As mentioned in the security:
Anonymous users are technically authenticated, meaning that the
isAuthenticated() method of an anonymous user object will return true.
//if you want myPage to be accessible by everyone
security:
firewalls:
secured_area:
pattern: ^/
anonymous: ~
access_control:
- { path: ^/myPage, roles: IS_AUTHENTICATED_ANONYMOUSLY }
If you remove the anonymous key, the firewall will always make a user fully authenticate immediately.
Related
I have a question regarding authentication with JWT and Facebook for a restful API app.
I am using Symfony 4 and for authentication "lexik/jwt-authentication-bundle": "^2.6", to generate jwt tokens based on username and password.
Here is my configuration security.yaml:
security:
encoders:
App\Entity\User: bcrypt
providers:
database:
entity:
class: App\Entity\User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/api/login
stateless: true
anonymous: true
json_login:
check_path: /api/login
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
register:
pattern: ^/api/register
anonymous: true
methods: [POST]
docs:
pattern: ^/api/docs
anonymous: true
methods: [GET]
api:
pattern: ^/api
stateless: true
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
access_control:
- { path: ^/api/docs, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/profile/social-account, roles: ROLE_INFLUENCER }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
I am trying to add also login by facebook but I have no idea how to handle that with JWT, as I want to return after login a JWT token.
Is there any way to handle facebook login and JWT login?
You can have a good idea of how to implement it here : https://github.com/lexik/LexikJWTAuthenticationBundle/issues/295.
Basically after the user accept the Facebook login on your frontend :
send a POST request with the user's token to your custom endpoint (for example login/facebook.
Then you can make an extra request with the user's token to Facebook api to get extra information as firstname, lastname or user's email (for example with https://graph.facebook.com/me/?fields=first_name,last_name,email).
The token needs to have correct permissions to get access to those information (https://developers.facebook.com/docs/facebook-login/permissions/overview).
You can now create a user if the email is not in your database.
Finally just return the token with create method of JWTManager class.
$token = $this->jwtManager->create($user);
By using this logic, it is totally transparent for your frontend whether your user has already loged in with your app or not and it gets a token the same way a user would get with your /login endpoint.
I assume you have an frontend application (React/Angular/Vue...) that consumes your API.
I would handle the "login with Facebook" on the Frontend side. After the user accepts the authentication via Facebook, they will be send back to your frontend app. At that point you have access to all the information you need (e.g. e-mail, first name, last name, etc).
POST that information to a new endpoint (e.g. /api/facebook-login), which handles your registration and/or login process, and then return an JWT token with your newly created user. Lexik makes it possible to manually create tokens:
class ApiController extends Controller
{
public function getTokenUser(UserInterface $user, JWTTokenManagerInterface $JWTManager)
{
// ...
return new JsonResponse(['token' => $JWTManager->create($user)]);
}
}
I am using Gitlab authentication in my current symfony project. I am using following two packages.
omines/oauth2-gitlab
knpuniversity/oauth2-client-bundle
Inside my security.yaml file
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
app_user_provider:
id: App\Security\UserProvider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
guard:
authenticators:
- App\Security\GitlabAuthenticator
access_control:
- { path: ^/connect, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
This is working fine and it is storing cookie PHPSESSID. I need to retrieve the username after successful login.
It is very very simple. Just use $this->getUser().
public function index()
{
/** #var \App\Entity\User $user */
$user = $this->getUser();
return new Response('Well hi there '.$user->getFirstName());
}
UserProvider (that's used in login process) returns a UserInterface, which represent a User. From it you can access the username.
Now, how to retrieve that user?
Depending on Symfony version, and depending where you want to access it, you have several possibilities:
Symfony <3.2
In controller -> you can use $this->getUser()->getUsername();
Symfony >=3.2
In controller -> Inject UserInterface directly as a dependency (read more)
For both cases, if you need the user not in controller, you can inject (based on your symfony version) the TokenStorage or the Security service (can't find which version supports which, for sure Security component is supported in sf5).
If you choose (or are forced) to go with TokenStorage (or its interface), you need to perform the following steps:
getToken
check if the token is not null
retrieve the username from the token (or optionally retrieve the whole user and then retrieve the username from there)
I have two firewalls for auth and api. But i want to combine them and be able to check if there is some user in controller.
firewalls:
user:
pattern: ^/api/auth
stateless: true
anonymous: true
json_login:
check_path: /api/auth/login_check
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
require_previous_session: false
api:
pattern: ^/api
stateless: true
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
access_control:
- { path: ^/api/auth, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
What I want to do is to combine firewalls to one and allow any user everythere, but still be available to identify user if JWT passwed.
Is it possible?
In my opinion,to achieve this you will need only the firewall matching ^/api pattern and continue using guard authenticator. Then, inside your authenticator, check for the exact route requested and chose whether to continue with normal guard authenticator flow or use a custom logic to implement json login. But it is a little bit dirty even if guard permits you to implement your own logic. Keeping separated firewalls sounds better.
I think it is better to keep separate firewalls, as mentioned already, but in case you absolutely need to keep your application open to everybody and check if the user is authenticated in your controller, you can refer to symfony's documentation and use something like:
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
I am developing a backend service for my own project with Symfony2. What i would like to do is simple user registration. Whenever a user needs to be created there will be a POST call to
/v1.0/users (with POST method)
I would like to create a new user. For all of the other url should be authenticated except this one. So I created UserProvider and UserAuthenticator as described in here : http://symfony.com/doc/current/cookbook/security/api_key_authentication.html
I created a secured area and it works fine, but i want to disable this firewal for the url above with post method. I couldnt figure it out how. Here is my security.yml file
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api_user_secured_area:
pattern: ^/v1.0/users
stateless: true
simple_preauth:
authenticator: user_token_authenticator
provider: user_token_provider
access_control:
...
user_register:
path: /v1.0/users
roles: IS_AUTHENTICATED_ANONYMOUSLY ?? FOR POST ONLY ??
PS: I dont want to use annotation for security (like #Security in the controller)
Access control can be filtered to a given METHOD using the Methods property, please see here for more filters/options regarding access control:
http://symfony.com/doc/current/cookbook/security/access_control.html
Here is the option integrated into your code:
access_control:
user_register:
path: /v1.0/users
methods: [ POST ]
roles: IS_AUTHENTICATED_ANONYMOUSLY
I have login page with login form. So if user is already logged I want redirect him from login page to another. Secured area is all pages with .*/secured.html and login page url is - login/page.html. When I am trying to $this->container->get('security.context'); I got error that there is no security token because current page is not under secured area. So If I want to use token (if exists) should I add all these pages to the secured area? In this way symfony2 will check every time if user is logged (and maybe will redirect to login page) but If I add
login:
pattern: ^/demo/secured/login$
security: false
auth token also will not exist.
So what is the way to use auth token at all application pages? Or all these pages should be added to secured area?
If you turn off the security you don't have a token. Your login page have to place behind the firewall. And no you don't have to
add all your single pages to your settings.
Here is an example:
firewalls:
main:
pattern: ^/
form_login:
login_path: /account/login
check_path: /account/login_check
logout:
path: /account/logout
anonymous: true
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
access_control:
- { path: ^/account/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/account/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/movie/, role: ROLE_USER }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
As you can see I activated the security on all pages, but I'll allow to access anonymously.
With this access control: - { path: ^/movie/, role: ROLE_USER } I've full control which user can access the page,
which implies that the user is already logged in.
For a deeper look I can recommend the Documentation: http://symfony.com/doc/current/book/security.html
Cheers.
So If I want to use token (if exists) should I add all these pages to
the secured area?
Yes, you have to put those where you want to access security token behind firewall. If you want to also access security token in login page, you also have to put it in behind the same firewall. But then make the access control for it as IS_AUTHENTICATED_ANONYMOUSLY.
access_control:
- { path: ^/secured/login/page.html$, roles: IS_AUTHENTICATED_ANONYMOUSLY }