•Published: Apr 28, 2020
Chimezie E.
Group chat can get a bit messy, especially if it’s public and anyone can join. Making a group chat invite-only can help manage the content of the group and the sanity of those in it, in addition to preventing spam users and bots.
In this tutorial, we’ll be building an invite-only chat room where only admin users can invite other users to join a chat room. Upon joining the chat room, users will be able to chat with other users in realtime.
The complete code for this tutorial is available on GitHub.
Prerequisites
To complete this tutorial, you'll need the following tech:
- PHP
- Node.js (preferably the latest – 13.x)
- Composer
- Yarn
- Laravel installer
- A Stream Chat Account
To follow along with this tutorial, a basic understanding of Laravel, Vue.js, and JavaScript would also be helpful.
Getting Our Stream Chat Keys
To use Stream Chat in our app, we need to grab our Stream Chat API keys. Stream Chat allows you to build a fully-functional chat app in hours, instead of weeks, or even months; we'll use it to build our simple example app in minutes! To get started log in to Stream or create an account. Upon successfully entering your credentials, you'll be delivered to your dashboard, where you can create a new app by clicking the Create App button:

Once that is done, you should see an API KEY and SECRET for your newly created application:

Take note of these keys as we’ll be needing them shortly.
Getting Started
We’ll be using the Laravel installer to create a new Laravel application. Run the following command to create a new Laravel application with authentication scaffolding:
Once that’s done, let’s install the npm dependencies:
Now, we can begin building out our application!
Building the Application
We’ll start by updating the users
table migration in our create_users_table.php
file, within database/migrations
, as shown below:
We updated the name
field to username
and added a new field called is_admin
, which will be used to determine if a user is an admin or not.
Let’s update the fillable fields in our User.php
file, in the app
directory, to have the username
field instead, as well:
Next, we’ll create an Invite
model:
In addition to creating an Invite
model, the command above will create a migration, as well as a controller for the model.
Open up the created migration and update the up
method in the create_invites_table.php
file, within database/migrations
, as shown below:
The fields are pretty straightforward; the accepted
field will be used to determine if an invite has been accepted or not.
Also, let’s mark the fields as fillable in Invite.php
, in the app
directory:
Before we run the migration, let’s set up our database. For the purpose of this tutorial, we’ll be using SQLite. Update DB_CONNECTION
inside .env
as below:
Because we are making use of SQLite, we can get rid of the other DB
environment variables.
By default, Laravel will look for a database.sqlite
file, so let’s create it:
Now, we can run the migration:
Before we move on to adding functionality to our application, let’s add our Stream keys to our .env
file:
Be sure to update "YOUR_STREAM_API_KEY" and "YOUR_STREAM_API_SECRET" to the values you grabbed from your Stream Chat dashboard.
Creating Channel and Admin Users
Now, let’s start building the group chat functionality. We’ll start by creating a new channel, which we’ll call "Chatroom
", and an admin user, to administer the group. We’ll be creating a console command to handle these. Run the command below to create a new console command:
This will create a new InitializeChannel.php
file inside app/Console/Commands
.
Since we’ll be making use of the Stream Chat PHP SDK, let’s install it:
With that installed, open up InitializeChannel.php
, located at app/Console/Commands
, and replace the contents with the following:
We define the signature of the command and give it a description. Inside the handle
method, we create an admin user
, then we create the user
on Stream as well, assigning the user an admin
role. Then, we create the channel
and make the newly created user
the creator of the channel
. Next, we add the user
as a member of the channel
. Lastly, we return a success message.
Now, we can run the channel:init
command:
Since we want users to join our group chat only by invitation, let’s remove the ability to register, which was added by Laravel authentication scaffolding. We can do that by updating web.php
, in the routes
directory, with the below:
Inviting Users
With the channel and admin users created, let’s add the functionality to invite users to our group chat. We’ll start by creating the routes. Add the code below inside web.php
:
Since we already have InviteController.php
, let’s open it up and add the following code in it:
Next, let’s create the view file. Inside the resources/views
directory, create a new invites
directory and create a create.blade.php
file inside it, then paste the following code in it:
The form has just one field, which is for capturing the email address to send an invitation to. Above the form, we have in place to display flash messages, if there are any:

Let’s move on to adding the implementation for processing the form. Add the following code to the top of InviteController.php
:
First, we get an invite
matching the submitted email address. If an invite
already exists for the email address, we flash an appropriate message depending on whether the invite
as been accepted or not. If no invite
was found, we create one for the email address, then send an email with the invitation link.
For this tutorial, we won’t be setting up a mail driver. Instead, we’ll log the mail to a file. Let’s set the MAIL_MAILER
to "log
" inside .env
as shown below:
$ MAIL_MAILER=log
Now, if we try sending an invite, it should be logged inside storage/logs/laravel.log
and look something like the below:
I’m using Laravel Valet, hence my URL:
http://stream-invite-only-group-chat.test
Let’s add a link to access the invite users page. We’ll add it in the navbar (app.blade.php
) immediately after the @else
:
While we are here, let’s update the navbar to show the user’s username instead of the name:
With these changes, your navbar should look like the below:

Joining Group Chat through Invitation Link
Once a user is sent an invitation, the user can click on the link in the email to join the group chat. To make this possible, add the following code inside web.php
:
Next, add the following code inside InviteController.php
:
First, we retrieve the invite
matching the token
, if it exists. If the invitation has been accepted, we simply redirect the user to the home
route. Otherwise, we render the "register" view
and pass along the invite
.
The register
view is already in place; we just need to update it slightly. Replace the name
and email
fields in resources/views/auth/register.blade.php
as below:
We made the email
field read-only and set the value to the email address on the invite.

We’ll still make use of the default Laravel RegisterController
, at app/Http/Controllers/Auth/
, to handle registration. Open it up and update validator
and create
methods to make use of username
instead of name
like below:
Still inside RegisterController.php
, add the following code to the very top:
Once a user registers successfully, the registered
method is called. Inside this method is the perfect place to mark the invite
as accepted
, create the user
on Stream, and, finally, add the user
to the "Chatroom" channel
.
Generating an Authentication Token
Let’s add the functionality for generating an authentication token, which Stream Chat will use to authenticate a user.
First, let’s create the endpoint inside routes/api.php
:
Next, create a TokenController
:
and add the following to it:
This generates a token using the user’s username
as the ID.
Adding Chat Functionality
With the backend functionality in place, let’s move on to adding the chat functionality. We are going to rename ExampleComponent.vue
, inside the resource/js
directory, to "ChatRoom.vue
" and update its reference inside resources/js/app.js
as below:
Now, replace the content of the ChatRoom
component with the following:
The template
is made up of two parts: the member
s list and the chat itself. We generate a token
for the authenticated user, then we use the token
to instantiate the Stream Chat client. We also initialize the channel
and watch for activities on the channel
, which allows us to know when a new message
is sent on the channel
as well when new user
s join the channel
. Lastly, we have the functionality for sending a new message
.
For a guide that covers these in detail, check out my previous tutorial.
Now, let’s install the Stream Chat JavaScript SDK:
Next, let’s make use of the ChatRoom
component. Update home.blade.php
as shown below:
The ChatRoom
component accepts the authenticated user
as props, which we are passing in.

Securing Our Application
Remember we said only an admin user can invite users to join our chatroom? But, as it stands, anybody can do this, even if they're not logged in. Let’s change that! Laravel provides an Authenticate
middleware, by default, which we can use to enforce access to only authenticated users. We’ll create another middleware for enforcing an authenticated user is an admin.
Run the command below to create an Admin
middleware:
and update the handle
method as shown below:
Here, we are simply redirecting the authenticated user
to the home
route if the user
is not an admin. If they are an admin, we allow the user
to access the requested page.
Before we can make use of the middleware, we need to register it. We’ll register it as a route middleware by adding it inside the $routeMiddleware
array, in app/Http/Kernel.php
, like so:
Now, we can make use of the middleware inside web.php
using the admin
key/identifier:
Now, not only does a user have to be authenticated to access these routes, but they must also be an admin!
Wrapping Up
In this tutorial, we have seen how to build an invite-only group chat using Laravel, Vue.js, and Stream Chat. We created multiple pages and authentication layers to our simple chat, but there is so much more you can do! To learn more about Stream Chat and its exciting features, check out the docs!
Thanks for reading, and happy coding!