Symfony, security.yaml : using both form and token authentication for same uri - api

My Symfony 5 app provides:
api endpoints like api/entry/get/1 (secured with oauth2)
admin pages like users/list (secured with database user provider)
For this purpose, my security.yaml uses two firewalls:
firewalls:
api:
pattern: ^/api(?!/doc$)
security: true
stateless: true
oauth2: true
main:
lazy: true
provider: app_user_provider
form_login:
login_path: app_login
check_path: app_login
enable_csrf: true
default_target_path: app_index
use_referer: true
logout:
path: app_logout
target: app_index
Is this possible to also access api endpoints like api/entry/get/1 when connected as an admin (ie not with a token but through regular form login with credentials) ?
This would make using a swagger sandbox much easier.

Is this possible to also access api endpoints like api/entry/get/1 when connected as an admin (ie not with a token but through regular form login with credentials) ?
I'd say in your current configuration, the answer is no.
Since you api firewall is sateless: true there's only one way to tell symfony that request should be considered as authenticated. The presence of Bearer token (it's probably a JWT) in each request. Without a valid token, all request to /api would be considered as unauthorized
In other words: symfony just do not check session/cookies for possible (previously) logged in (admin) user to allow/deny access for all /api routes.
Unfortunately, I hadn't an opportunity to work with OAuth2ServerBundle. So maybe there's a configuration for that.
BUT:
Try to play around with staless and context
about stateless
about context
However, RESTful APIs are stateless by design, it's not just a fancy buzzword.
There is also a way to add "Authorize" button to your swagger doc/playgroung so anyone who has access to swaggerUI, could paste a valid auth-token (JWT) and all further request from swaggerUI would be authorized. See Swagger and JWT Token Authentication
I also had a wonderful experience with Insomnia http-client especially when I need to test/play with my apis.
It has great OAuth v.2 support. Free tier is more than enough for local development / quick testing. Just specify your token path, select GrantType as "Resource Owner" paste username/password of your admin user and insomnia will handle the rest automagically each time you hit a protected /api/entry/get/1

Related

symony 3.3 guard authetication with multiple providers

I am implementing a symfony (3.3) custom guard authenticator to authenticate a user against OKTA and it's working fine without any issues.
However, I'd like to authenticate an admin user against the credentials stored in the database.
Basically, if any user hits /api/login endpoint it should authenticate against OKTA, except for one admin user who should be authenticated against the password stored in the database. How can I achieve this pls?
Here is my security.yml
security:
providers:
db_user_provider:
entity:
class: MyApiBundle:ApiUser
property: username
okta_user_provider:
id: okta_user_provider
my_chain_provider:
chain:
providers:
- db_user_provider
- okta_user_provider
firewalls:
login:
pattern: ^/api/login
anonymous: true
stateless: true
provider: my_chain_provider
guard:
authenticators:
- authenticator_guard_okta
Many thanks
I solved this issue in my custom LoginFormAuthenticator
i.e in
public function getUser($credentials, UserProviderInterface $userProvider)
A) check if the $credentials['username'] exist in db. If yes, find the user entity from db and return the user
B) check if the $credentials['username'] exist in okta. If yes, load the user from okta and return the user
public function checkCredentials($credentials, UserInterface $user)
A) check if the user is an instance of db user entity. If yes, validate the password and return the user
B) check if the user is an instance of okta user. If yes, validate against okta and return okta user

How to manage two authentications systems: with and without state (cache)

I have an HTTP API using Symfony 3.
I am using GuardAuthenticator, so that we can call the API, using a login and password, with stateless (security attribute) set to false.
Today I add another way of authenticate, by using jwt from an external IDP. In this case, I would like to have statless set to true (the user will have to provide the jwt at every call).
Do you have any ideas please ? :)
api:
pattern: ^/api/
stateless: false
guard:
authenticators:
- api.security.guard_authenticator
switch_user: true
anonymous: ~
in my API I have a Basic Auth + Token system. To do so, in the pre_auth I had a check for the BasicAuth.
I Guess if you passing the stateless to true, you'll have to implements something similar.

Auth0 asks for consent to access tenent when logging in

I am developing an Angular2 app which uses auth0 for authentication. I used the auth0 lock widget to authenticate users.
Now, I want to use auth0-js instead of the lock widget for authentication. I followed this guide to add auth0-js to the app.
After adding auth-js, when a new user tries to log in to the app, Auth0 displays following consent screen to the user.
I want the users to be able to directly access my app, without needing to accept a consent screen. The consent question asked in this dialog can be confusing to users since it mentions about tenants.
When I searched for a solution, the solution mentioned in various places was to make the client a first party client. But, I cannot find any place in the management console to make the client a first party client.
How can I disable this consent screen?
Following is the auth-js config I used in the app.
auth0 = new auth0.WebAuth({
clientID: 'my_client_id',
domain: 'my_domain.auth0.com',
responseType: 'token id_token',
audience: 'https://my_domain.auth0.com/userinfo',
redirectUri: window.location.origin + '/auth_loading',
scope: 'openid'
});
In Auth0 Dashboard, under APIs -> Auth0 Management API -> Settings (tab)
If you are using a specific audience for a Resource API you have defined yourself in the Dashboard, then there is a similar Allow Skipping User Consent toggle for that particuar API. Use that. audience specifies the target API for your access token. If you don't want to call a specific API, keep it set to https://my_domain.auth0.com/userinfo
Re. question about First Party. If you created your client in the Auth0 Dashboard, then it is Firsty Party by default. Only first-party clients can skip the consent dialog, assuming the resource server they are trying to access on behalf of the user has the "Allow Skipping User Consent" option enabled. The Auth0 Dashboard does not offer a flag for this, but if you use the Auth0 Management API v2 Get Clients endpoint, then you will see the flag (boolean) value listed for your client eg.
"is_first_party": true
See https://auth0.com/docs/api/management/v2#!/Clients/get_clients for details.
Finally, please note the following: https://auth0.com/docs/api-auth/user-consent#skipping-consent-for-first-party-clients - in particular note that consent cannot be skipped on localhost. As per the docs (link above), During development, you can work around this by modifying your /etc/hosts file (which is supported on Windows as well as Unix-based OS's) to add an entry such as the following:
127.0.0.1 myapp.dev

Possible to validate ServiceStack's authentication cookie client side?

I am having a HTML (Angular) site which has a login button and needs (of course) to present a different GUI when the user is authenticated. I am using ServiceStack based REST services. Now when a user is successfully authenticated I was wondering if it is possible to check the generated authentication cookie (by ServiceStack) on the client only. I just need to check the userid, maybe role and expiration date of the cookie. Advantage is I do not have to make 'CheckUserIsAuthenticated' server rest call's just for showing a different GUI (of source CRUD actions are validated serverside).
You can check that a cookie exists with document.cookie, as it's hard to work with directly Mozilla provides a lightweight cookies wrapper to make it easier to work with, likewise AngularJS provides $cookies provider.
But a cookie doesn't tell you anything about the user since even non-authenticated / anonymous users will have cookies. Instead to check if the user is authenticated you can call /auth route via ajax which when authenticated ServiceStack will return summary info about the user, e.g:
{
UserId: "1",
SessionId: "{sessionId}",
UserName: "user#gmail.com",
DisplayName: "First Last"
}
If the user is not authenticated /auth will return 401 Unauthorized.

Authentication for a Symfony2 api (for mobile app use)

I've developed a REST api for my Symfony2 application. This api will be used by a mobile app. Much of the functionality is done in the context of the currently authenticated user, ie:
$this->container->get('security.context')->getToken()->getUser()
I'm hoping that the mobile app will be able to post to the login action just like a traditional web form. If the credentials check out then Symfony2 does it's thing and sets a cookie (does this even work in the context of a mobile app accessing an api?). Then later api requests from that mobile phone will (hopefully) work with the native symfony2 security.context service container.
Would this work? I need to figure out this authorization process before I take the API to the mobile developers. If possible I'd obviously like to be able to use the native security.context service instead of building out a new auth system for the api that uses xAuth or something similar.
Thanks
I think you should do it stateless (without cookie).
I had the same problem, what i did:
in your app/config/security.yml, add:
security:
...
firewalls:
rest_webservice:
pattern: /webservice/rest/.*
stateless: true
http_basic:
provider: provider_name
...
Now you can make a request to your webservice:
class AuthTest extends WebTestCase
{
public function testAuthenticatedWithWebservice()
{
$client = $this->createClient();
// not authenticated
$client->request('GET', '/webservice/rest/url');
$this->assertEquals(401, $client->getResponse()->getStatusCode());
// authenticated
$client->request('GET', '/webservice/rest/url', array(), array(), array(
'PHP_AUTH_USER' => 'username',
'PHP_AUTH_PW' => 'password'
));
$this->assertEquals(200, $client->getResponse()->getStatusCode());
}
}
Here you are, How to create a custom Authentication Provider awesome article.
To Authentication to a Symfony2 application through api, you need use:
WS-Security
Yes Marc, jules is pointing to an example just to show you how to test authentication with http_basic.
To be RESTful you should avoid using cookies, otherwise just call it an API. About how secure is your authentication system you can go with http_digest over https or more secure signed request with api_key/api_secret approach.
Have a look here http://wiki.zanox.com/en/RESTful_API_authentication