Build and Secure a CRUD Application with Laravel 6

Hi @roenfeldt! Thanks for following along!

Laravel recently released 7.0 and we’re currently working to update the Auth0 package compatibility. It should be updated soon, but for now a quick fix to get the tutorial working is to specify to use Laravel 6. Laravel 6 was also just recently released and will continue to be supported into late 2021, so don’t worry about starting with 6. There isn’t a huge difference between the 2.

In composer.json, find where it says laravel/framework and change it to "laravel/framework": "^6.0",. Then run composer install again.

Let me know if that works for you! I’m going to update the article with that note as well, so thanks for pointing it out!

Hey @holly

Thanks for replying as well as providing me with the workaround! The thing is, I’ve recently started working with Laravel (coming from a WordPress background) so I’m hoping my questions don’t sound excessively ridiculous :slight_smile:

I tried out your solution, but I still couldn’t get past the same error. I ended up specifiying which Laravel version to use when creating the project the “Composer way”, i.e.

composer create-project --prefer-dist laravel/laravel tpc "6.*".

All went well this time, except for the step where laravel/ui Bootstrap package had to be added. Apparently, version 2 of laravel/ui is incompatible with Laravel 6.*. The error I encountered is described in this SO post, and the solution provided along with the first answer worked a treat for me. For the record, I simply replaced

composer require laravel/ui
with
composer require laravel/ui="1.*" --dev

The best thing is, I was finally able to complete the tutorial!

I really like the flexibility and insight into logins, that Auth0 provides. I’ll be looking forward to more high quality tutorials from you, @holly!

Finally have a little time to work on my web app again. Came back to your wonderful tutorial again when having trouble with Register. Getting the following error:

WE’RE SORRY, SOMETHING WENT WRONG WHEN ATTEMPTING TO SIGN UP.

Web console shows:

auth0.min.esm.js:8 GET https://dev-pqc7zd86.auth0.com/user/ssodata 404
u._end @ auth0.min.esm.js:8
u.end @ auth0.min.esm.js:8
N.end @ auth0.min.esm.js:8
X.getSSOData @ auth0.min.esm.js:8
nt.getSSOData @ auth0.min.esm.js:8
t.getSSOData @ p2_api.js:190
t.getSSOData @ web_api.js:64
(anonymous) @ data.js:4
t.fetch @ cache.js:17
t.get @ cache.js:13
r @ data.js:7
syncFn @ remote_data.js:27
(anonymous) @ sync.js:56
D @ sync.js:51
(anonymous) @ index.js:29
St @ immutable.js:1971
St @ immutable.js:1980
St @ immutable.js:1980
pt.updateIn @ immutable.js:1278
a @ index.js:29
t.swap @ atom.js:12
i @ index.js:25
(anonymous) @ sync.js:91
setTimeout (async)
(anonymous) @ sync.js:91
(anonymous) @ index.js:11
(anonymous) @ atom.js:38
t._change @ atom.js:38
t.swap @ atom.js:12
i @ index.js:25
(anonymous) @ sync.js:91
setTimeout (async)
(anonymous) @ sync.js:91
(anonymous) @ index.js:11
(anonymous) @ atom.js:38
t._change @ atom.js:38
t.swap @ atom.js:12
i @ index.js:25
(anonymous) @ sync.js:60
setTimeout (async)
(anonymous) @ sync.js:59
(anonymous) @ cdn_utils.js:17
setTimeout (async)
(anonymous) @ cdn_utils.js:17
i.<computed>.t.Auth0.<computed> @ cdn_utils.js:15
(anonymous) @ fbS7fgZtZTjFPzd4Gf47gIjZvnRxy4yz.js?t1584159367246:1
index.js:429 There was an error fetching the SSO data. This is expected - and not a problem - if the tenant has Seamless SSO enabled. If the tenant doesn't have Seamless SSO enabled, this could simply mean that there was a problem with the network. But, if a "Origin" error has been logged before this warning, please add "https://dev-pqc7zd86.auth0.com" to the "Allowed Web Origins" list in the Auth0 dashboard: https://manage.auth0.com/#/applications/fbS7fgZtZTjFPzd4Gf47gIjZvnRxy4yz/settings
R @ index.js:429
errorFn @ remote_data.js:41
(anonymous) @ sync.js:64
setTimeout (async)
(anonymous) @ sync.js:64
(anonymous) @ index.js:29
St @ immutable.js:1971
St @ immutable.js:1980
St @ immutable.js:1980
pt.updateIn @ immutable.js:1278
a @ index.js:29
t.swap @ atom.js:12
i @ index.js:25
(anonymous) @ sync.js:60
setTimeout (async)
(anonymous) @ sync.js:59
(anonymous) @ cache.js:30
t.execCallbacks @ cache.js:30
(anonymous) @ cache.js:19
(anonymous) @ auth0.min.esm.js:8
u.callback @ auth0.min.esm.js:8
(anonymous) @ auth0.min.esm.js:8
e.emit @ auth0.min.esm.js:8
e.onreadystatechange @ auth0.min.esm.js:8
XMLHttpRequest.send (async)
u._end @ auth0.min.esm.js:8
u.end @ auth0.min.esm.js:8
N.end @ auth0.min.esm.js:8
X.getSSOData @ auth0.min.esm.js:8
nt.getSSOData @ auth0.min.esm.js:8
t.getSSOData @ p2_api.js:190
t.getSSOData @ web_api.js:64
(anonymous) @ data.js:4
t.fetch @ cache.js:17
t.get @ cache.js:13
r @ data.js:7
syncFn @ remote_data.js:27
(anonymous) @ sync.js:56
D @ sync.js:51
(anonymous) @ index.js:29
St @ immutable.js:1971
St @ immutable.js:1980
St @ immutable.js:1980
pt.updateIn @ immutable.js:1278
a @ index.js:29
t.swap @ atom.js:12
i @ index.js:25
(anonymous) @ sync.js:91
setTimeout (async)
(anonymous) @ sync.js:91
(anonymous) @ index.js:11
(anonymous) @ atom.js:38
t._change @ atom.js:38
t.swap @ atom.js:12
i @ index.js:25
(anonymous) @ sync.js:91
setTimeout (async)
(anonymous) @ sync.js:91
(anonymous) @ index.js:11
(anonymous) @ atom.js:38
t._change @ atom.js:38
t.swap @ atom.js:12
i @ index.js:25
(anonymous) @ sync.js:60
setTimeout (async)
(anonymous) @ sync.js:59
(anonymous) @ cdn_utils.js:17
setTimeout (async)
(anonymous) @ cdn_utils.js:17
i.<computed>.t.Auth0.<computed> @ cdn_utils.js:15
(anonymous) @ fbS7fgZtZTjFPzd4Gf47gIjZvnRxy4yz.js?t1584159367246:1
8557d39a829c684961f4734ba222225d:1 GET https://secure.gravatar.com/avatar/8557d39a829c684961f4734ba222225d?d=404&s=160 404
Image (async)
r @ preload_utils.js:9
(anonymous) @ avatar.js:29
i @ gravatar_provider.js:30
r @ avatar.js:26
e.componentDidMount @ email_pane.jsx:14
t.notifyAll @ CallbackQueue.js:74
close @ ReactReconcileTransaction.js:78
closeAll @ Transaction.js:207
perform @ Transaction.js:154
perform @ Transaction.js:141
perform @ ReactUpdates.js:87
z @ ReactUpdates.js:170
closeAll @ Transaction.js:207
perform @ Transaction.js:154
batchedUpdates @ ReactDefaultBatchingStrategy.js:60
i @ ReactUpdates.js:95
dispatchEvent @ ReactEventListener.js:145
index.js:94 GET https://secure.gravatar.com/8557d39a829c684961f4734ba222225d.json?callback=__jp0 net::ERR_ABORTED 404
o @ index.js:94
t.get @ jsonp_utils.js:5
o @ gravatar_provider.js:17
r @ avatar.js:36
e.componentDidMount @ email_pane.jsx:14
t.notifyAll @ CallbackQueue.js:74
close @ ReactReconcileTransaction.js:78
closeAll @ Transaction.js:207
perform @ Transaction.js:154
perform @ Transaction.js:141
perform @ ReactUpdates.js:87
z @ ReactUpdates.js:170
closeAll @ Transaction.js:207
perform @ Transaction.js:154
batchedUpdates @ ReactDefaultBatchingStrategy.js:60
i @ ReactUpdates.js:95
dispatchEvent @ ReactEventListener.js:145
index.js:94 GET https://secure.gravatar.com/8557d39a829c684961f4734ba222225d.json?callback=__jp1 net::ERR_ABORTED 404
o @ index.js:94
t.get @ jsonp_utils.js:5
o @ gravatar_provider.js:17
r @ avatar.js:36
r @ fn_utils.js:6
setTimeout (async)
(anonymous) @ fn_utils.js:9
e.handleChange @ email_pane.jsx:21
executeOnChange @ LinkedValueUtils.js:130
i @ ReactDOMInput.js:239
r @ ReactErrorUtils.js:24
a @ EventPluginUtils.js:83
s @ EventPluginUtils.js:106
d @ EventPluginHub.js:41
h @ EventPluginHub.js:52
r @ forEachAccumulated.js:22
processEventQueue @ EventPluginHub.js:252
r @ ReactEventEmitterMixin.js:15
handleTopLevel @ ReactEventEmitterMixin.js:25
i @ ReactEventListener.js:70
perform @ Transaction.js:141
batchedUpdates @ ReactDefaultBatchingStrategy.js:60
i @ ReactUpdates.js:95
dispatchEvent @ ReactEventListener.js:145
auth0.min.esm.js:8 POST https://dev-pqc7zd86.auth0.com/dbconnections/signup 400

Also, can you explain about where the new user register info is stored - in your database or mine? Tutorial doesn’t really explain it in depth.

@greg7
When you get that error at signup, is there anything to see in the logs in Auth0 side?

Auth0 Dashboard > Logs > Search ?

Any failure logged that you can check? (If logged, click on it to view details)

Ah, yes. It says I already exist. That makes sense. I didn’t realize user info was actually being stored on Auth0 site. If the logs are smart enough to know the real reason for the error, would it be possible to tell the customer the real reason, rather than the vague message they get now?

Just wanted to say this is by far one of the best tutorials I’ve had the pleasure of following along to. Please keep up with this style of writing and teaching! It works incredibly well with the 0Auth/Laravel workflow.

Just as I found myself wondering a of couple things and noticing changes weren’t saving when editing reservations I went back to the page to find exactly what I was after! I’ve been following along to 0Auth tutorials for laravel authentication for a couple days now and this is the only one that got me up and running in a way that I expected the end result to be. Also the bonus for touching on how to use homestead and VM’s was an awesome addition! :smiley:

4 Likes

@holly I’m building a Laravel-driven SaaS website, and I’m seriously considering subscribing to the paid “DEVELOPER” Auth0 plan. As a matter of fact, I’ll do it in a heartbeat, if what I need is achievable :slight_smile:

Long story short, my SaaS website would provide 3 membership levels: Free / Premium / Premium Plus. I’ve already created three different roles under my Auth0 dahsboard ready for the users to get assigned to them, based on their chosen plan. Each plan will require users to input a rather wide array of personal info (first/last name, gender, date of birth, avatar image, street, zipcode, city, country, phone no. ) during the actual registering process. On top of that, the desired membership level must be also chosen by the user.

Would it be, therefore, possible that, when the user finishes filling up all the required info, and clicks the “Submit/Create Account” button, all the above mentioned info to be sent to Auth0, and the user account gets programatically created, along with all the personal details I was referring to?

And another question: what do you think is better, should I rely solely on the Auth0’s database to store the members’ account information, or should I also save the users’ info in the application’s database?

One final question: if I sign up for the “DEVELOPER” Auth0 annual plan, with the default 1,000 External Active Users, is it difficult to upgrade without any interruption in service, should my application require additional users?

I would highly appreciate your expert input on this. Thank you so much!

1 Like

Hello, Daniel. Thank you for your interest in using Auth0 as the Identity Solution for your SaaS product. Holly is currently out of office but, while she comes back, I have also raised your question in our internal channels. We’d get back to you with an answer as soon as possible :slight_smile:

2 Likes

Hello Dan,

Thank you for your reply! I just realized I provided a lot of details related to my SaaS project, except for the framework that the website will be run on. Just so that there’s no doubt about it, it’s Laravel 6. I know it should be pretty obvious, since my initial post belongs to the discussion thread on the Auth0/Laravel integration, but I thought I’d still point out the obvious nevertheless :blush:

Just for the record, I signed up for the yearly Developer planyesterday :star_struck:, can’t wait to be able to start building something awesome, especially in terms of safety and convenience for the users!

I will be looking forward to good news from you, Holly, or anyone else at Auth0 :star:

Thanks for suplementing that info @roenfeldt! :slight_smile:

1 Like

@dan-auth0 do you have any news and/or suggestions to point me into the right direction, in regards to integrating the Auth0 API into my Laravel-driven application? After almost one week of fruitless research that only resulted in countless failed attempts, I’m about to give up, becuase I simply can’t figure out how to adapt Holly’s solution to my Laravel setup.

To put things into a more clear perspective, my intention is to have Auth0’s API handle new users’ registrations, as well as existing users’ sign-ins, all with zero external redirection occurrence. In other words, the authentication/registration process must happen behind-the-scenes, as in, completely transparent to the user. That also implies the fact that the Laravel application must use its own, custom-built authentication form, as well as registration form.

But as I mentioned above, I feel completely clueless about where should I start. I totally understand that nobody is obligated to write code that magically works out-of-the-box for me, but I cannot stress how much I need to get this programatic registration/authentication logic working. Of course I’m not afraid to get some elbow grease once a solid starting point is provided. If there’s anyone willing to, and capable of helping me out, I’ll be forever in your debt!

1 Like

Hi Daniel! I’m back from vacation and catching up with this thread :slight_smile: Thank you for signing up! We can definitely try to help you out, but just want to clarify your use case to make sure I understand everything.

  1. In other words, the authentication/registration process must happen behind-the-scenes, as in, completely transparent to the user. That also implies the fact that the Laravel application must use its own, custom-built authentication form, as well as registration form.

For this one, are you saying you need to implement embedded login? That’s definitely possible, but it requires a fair bit of extra work beyond this tutorial. If the main concern is the login branding being confusing for your users, you can modify the login widget styles in your Auth0 dashboard. Click on “Universal login” in the sidebar and you’ll see some styling options there. You can customize it further by clicking the “Login” tab on that page.

  1. And another question: what do you think is better, should I rely solely on the Auth0’s database to store the members’ account information, or should I also save the users’ info in the application’s database?

I think this mostly depends on the amount of extra data you want to store. If it’s just a few extra attributes like you mentioned, you can store that information in the user_metadata. Just note that this data should be information that the user is allowed to update on their own. Something like the subscription tier should go into app_metadata or be stored in your own table under the (the way we did with the reservations).

  1. One final question: if I sign up for the “DEVELOPER” Auth0 annual plan, with the default 1,000 External Active Users, is it difficult to upgrade without any interruption in service, should my application require additional users?

You can upgrade straight from your dashboard with no interruption! Another thing to keep in mind with the plan is that the listed supported number of users is for active users. This means that if you have 500 people sign up initially, and then only 100 of them sign back into your app the following month, then you have 100 active users for that month. So hopefully the Developer plan will get you pretty far for now!

I worked on an application a couple of years ago that had 10,000+ users, but less than 1000 were active month to month, so I was able to stay on the lower level plan for a long time!

Let me know if any of this helps! We can definitely help you out more with the first question, just wanted to clarify that I understand your use case first :slight_smile:

Had a quick question I’m not seeing a nickname in my getUserInfo block? A guess is their a setting I need to turn on in Auth0 dashboard, or what if I want it to use user_name vs nickname? If im using \App\Repositories\CustomUserRepository::class vs \Auth0\Login\Repository\Auth0UserRepository::class in the AppServiceProvider file

Hey @justinnygaard6590! For the user that’s missing nickname, it should populate without any additional steps from the dashboard as long as you included profile in the scope (in the Auth0IndexController.php - login() function). Can you confirm that you have profile in there? And did it return it empty or not return a nickname field at all?

For the second part, this might be what you’re looking for: https://auth0.com/docs/quickstart/webapp/laravel/01-login#optional-custom-user-handling

We do have a username field, but you’d have to use the Management API to get/update that. I can give you guidance there if that’s the route you want to take.
https://auth0.com/docs/api/management/v2?_ga=2.246656012.960397302.1587421174-34415347.1581013203#!/Users/get_users_by_id

Please I am having this same issue. I have been stuck here for over hours. I used APP_URL=http://localhost:8000 but still not working showing this

Hi @jackieriel! Can you tell me what you have listed for “Allowed callback URLs” in your Auth0 dashboard? It would be on the Applications page.

@holly Here is the screenshot

@jackieriel Hmm can you try also adding the custom domain you’re running it on https://crudreservation.auth0.com/auth0/callback? You can keep localhost too if you use that sometimes, just separate them with a comma.

If you look at the URL from the first screenshot when you get the error, it should show you what it’s expecting as the redirect_uri. E.g. https://yourauth0domain.auth0.com/authorize?response_mode=query&scope=openid%20profile%20email&response_type=code&**redirect_uri=http%3A%2F%2Fhomestead.test%2Fauth0%2Fcallback**. So you can look there and that should be the URL that goes in “Allowed callback URLs”.

@holly Thanks. It works, I added “https://crudreservation.auth0.com/auth0/callback” to the callback urls

Awesome, glad you got it working! Sorry for the roadblock there :smiley_cat:

1 Like