Chapters
37 Chapters
|
3:43:31
|
Login to bookmark this video
-
Course Code
Subscribe to download the code!
Subscribe to download the code!
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Subscribe to jump to this part in the video!
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": ">=8.2",
"ext-ctype": "*",
"ext-iconv": "*",
"api-platform/core": "^3.0", // v3.1.2
"doctrine/annotations": "^2.0", // 2.0.1
"doctrine/doctrine-bundle": "^2.8", // 2.8.3
"doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.2
"doctrine/orm": "^2.14", // 2.14.1
"nelmio/cors-bundle": "^2.2", // 2.2.0
"nesbot/carbon": "^2.64", // 2.66.0
"phpdocumentor/reflection-docblock": "^5.3", // 5.3.0
"phpstan/phpdoc-parser": "^1.15", // 1.16.1
"symfony/asset": "6.2.*", // v6.2.5
"symfony/console": "6.2.*", // v6.2.5
"symfony/dotenv": "6.2.*", // v6.2.5
"symfony/expression-language": "6.2.*", // v6.2.5
"symfony/flex": "^2", // v2.2.4
"symfony/framework-bundle": "6.2.*", // v6.2.5
"symfony/property-access": "6.2.*", // v6.2.5
"symfony/property-info": "6.2.*", // v6.2.5
"symfony/runtime": "6.2.*", // v6.2.5
"symfony/security-bundle": "6.2.*", // v6.2.6
"symfony/serializer": "6.2.*", // v6.2.5
"symfony/twig-bundle": "6.2.*", // v6.2.5
"symfony/ux-react": "^2.6", // v2.7.1
"symfony/ux-vue": "^2.7", // v2.7.1
"symfony/validator": "6.2.*", // v6.2.5
"symfony/webpack-encore-bundle": "^1.16", // v1.16.1
"symfony/yaml": "6.2.*" // v6.2.5
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.2
"mtdowling/jmespath.php": "^2.6", // 2.6.1
"phpunit/phpunit": "^9.5", // 9.6.3
"symfony/browser-kit": "6.2.*", // v6.2.5
"symfony/css-selector": "6.2.*", // v6.2.5
"symfony/debug-bundle": "6.2.*", // v6.2.5
"symfony/maker-bundle": "^1.48", // v1.48.0
"symfony/monolog-bundle": "^3.0", // v3.8.0
"symfony/phpunit-bridge": "^6.2", // v6.2.5
"symfony/stopwatch": "6.2.*", // v6.2.5
"symfony/web-profiler-bundle": "6.2.*", // v6.2.5
"zenstruck/browser": "^1.2", // v1.2.0
"zenstruck/foundry": "^1.26" // v1.28.0
}
}
14 Comments
For those who need it, I always got a 415 response and in the error document that I created, it appeared
{ "@context": "/api/contexts/Error", "@type": "hydra:Error", "hydra:title": "An error occurred", "hydra:description": "The content-type \"application/json\" is not supported. Supported MIME types are \"application/ld+json\".", .....more ....I had to add the Content-Type in the headers to fix it and continue with the flow of the course.
Hey @Rodrypaladin ,
I see in this chapter we allow
application/jsoncontent type as well along withapplication/ld+json. Probably your config is different? Anyway, thanks for this tip!Cheers!
I don't know if my configuration is different. I only know that from the very first moment following the course, in the Patch applications I have had to incorporate it if necessary.
The important thing is that I was able to solve it by my own means.
Hey @Rodrypaladin ,
Good catch on solving this yourself 👍
Cheers!
I'm following this awesome tutorial using Symfony 7.2 ;)
I'm getting the following error on the second test (testPostToCreateTreasure):
Naturally, the rest of the tests then fail because Entity Manager is closed after the afore mentioned failure.
Been Googling for a while now, and I can't seem to find anything that relates to the issue I'm having.
I'm guessing I need to clear the Entity Manager... I'm just not exactly sure how to do that correctly from inside a test case.
Everything I've tried so far doesn't work... so I'm hoping someone maybe has a solution to this minor headache ^_^
Appreciate the help... and keep up the good work :D
Hey @NinjaScareCrow ,
Hm, if your database is truncated between tests but somehow the entity manager isn't cleared, Doctrine might still hold references to old entities in memory. You can try to clear the entity manager manually in the beginning of your test, or in the
setUp()method called before each test, something like this:I wonder if it helps with that test failure.
Cheers!
Hey Victor
Unfortunately that didn't work :(
I had to adapt it slightly as
self::$containerdoesn't exist.I'm still getting the same error on the second test when I rull all the tests using symfony php bin/phpunit.
I even tried getting the entity manager and clearing it at the beginning of the test cases, but that also didn't work.
Any other ideas? ;)
Hey @NinjaScareCrow
How are you restoring your database after each test? Are you using the dama bundle?
Cheers!
So, my app has two firewalls configured. One for the API called "api" (using LexikJWTAuthenticationBundle) and one for the Web-Admin-Backend ("main") using "knpuniversity/oauth2-client-bundle" in combination with "stevenmaguire/oauth2-keycloak".
That means, that different from Chtioui's config, the API-Tokens are created externally, meaning that in my TestClass inside the setUp() function I do the following:
And in the test function that test the secured API-Endpoint, I can do the following:
But now I also wanted to test a web-route, but that somehow is not possible.
If I try:
I get a 500 response, an in the dump from the template it says:
The profileUrl is set in the KeycloakAuthenticator, in which a PostAuthenticationToken is set, which is why I also create one of these in the setup cuntion with the Admin-User I created in the fixtures.
Then I try to do the following:
But that does not seem to work, because my app still thinks, that I am logged out.
Any ideas on what I am doing wrong?
Thanks in advance.
Hey @TristanoMilano!
Sorry for my super slow reply! Hmm, this is tricky. Here's what I can tell you:
->actingAs()method from browser is a wrapper around the->loginUser()method of Symfony - https://github.com/symfony/symfony/blob/9e810dea50cb47deb8500ad7ffb56d5a5622b46e/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php#L103TestBrowserTokenobject - https://github.com/symfony/symfony/blob/9e810dea50cb47deb8500ad7ffb56d5a5622b46e/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php#L113So, it may be that simple. Your user is getting logged in, but instead of a
PostAuthenticationTokenwith thisprofileUrlset, it's aTestBrowserTokenwith no attribute set.If that's true, you may need to write your own fake authentication logic in your test that mimics the
loginUser()method from Symfony... but with your token.Let me know if that helps!
Cheers!
Hello symfonycasts Team !
i'm using LexikJWTAuthenticationBundle to handle token authentication everything works fine until I tried to update a user's login credentials (password & email) with the PATCH operation the update request succedeed but i've got token this error : "Invalid credentials" after finishing updating the user I want to understand something here do we need to login again the user after updating his login credentials or therre is any other solution to generate a new token after the user updates his login credentials?
Cheers!
Hey @Chtioui!
Hmm very interesting! So, you're using LexikJWTAuthenticationBundle with "stateless" authentication is that correct? What I mean is: you send the JWT with every API request, right? You do not rely on just "logging in once" and then using the session to authenticate you on future request. Let me know if that assumption is incorrect :).
Anyways, if you ARE using "stateless" authentication, then I have no idea what's happening yet :P.
But if you ARE relying on session authentication, then I still don't totally know what's happening, but I can offer some info. On each request, Symfony attempts to load the
Userobject from the session. It then checks to see if some of the important fields on thatUserobject (the one that was stored in the session) have since changed in the database - for example, if the password has been changed. If any of these fields have changed, it does NOT load yourUser(i.e. it effectively logs you out). This is a security mechanism so that if you change your password on one computer because someone hacked your account, it will log ALL devices out of your account immediately. The logic for this is here: https://github.com/symfony/symfony/blob/0eb03203c800b11bac4496a3e84c75e2966d5507/src/Symfony/Component/Security/Http/Firewall/ContextListener.php#L281-L321However, normally, if you change your password on a request, then at the end of that request, when Symfony serializes the
Userinto the session, it will serialize theUserobject that contains the NEW hashed password. And so, in the next request, everything will work fine.So, something feels weird to me. Can you tell me a bit more about your situation - are you using stateless auth or session-based auth? When exactly do you get the "Invalid credentials" error - is that on the NEXT request? Are you sending a JWT on that? What does your JWT contain?
Cheers!
Hello @weaverryan,
-Yes i'm using stateless authentication with the LexikJWTAuthenticationBundle and i'm using the user's username and password for generating the JWT token.
-I get the "Invalid credentials" error on the next request and the user is no longer authenticated in my web app.
-I think whats happening is normal because the user is updating his login credentials (username & password in my case) that's why i'm getting the error "Invalid credentials" with the status 401 also I get this error only when update the user's login credentials but if I update other properties of the user's class everything works fine and I got no errors from the api response.
-I want to know if there is any mechanism to integrate to solve the problem or do I need to authenticate again the user after he updates one of his login credentials.
*firewalls in security.yaml:
security firewall
Lexik bundle file configuration:
Lexic bundle configuration file
Cheers!
Hey @Chtioui!
Hmm. If the user changes their username, it DOES make sense that you would lose authentication since the
usernameis what's added to the JWT... and then thatusernameis read from the JWT to find the user. So if you change the username, that user won't be found. To fix that, you could change your JWT to use theidinstead, which is probably safer anyways. I'm not sure exactly how you're supposed to do this - but the https://symfony.com/bundles/LexikJWTAuthenticationBundle/current/2-data-customization.html seems to be close.I don't understand why changing the
passwordis also causing problems - but you did mention that:So perhaps you're adding and using the password in the token in some manual way already.
Anyways, to fix the issue, you'll need to either:
A) Re-authenticate after this (as you know is already possible)
or
B) Somehow send back a fresh JWT from the user endpoint where you update the email/password. I'm not sure how standard this is... but in theory, you could register an event listener that could add a custom response header - e.g.
X-JWTto this endpoint. It's a non-trivial problem. You might, insideUser::setPlainPassword()andsetUsername()set some flag on yourUserlike$this->needsNewJWT = true. Then register aResponseListenerand look for that (you can get theUserobject via$request->attributes->get('data').I hope this gives you some hints :)
Cheers!
"Houston: no signs of life"
Start the conversation!