The Problem
Recently, as a result of Stream's work on the stream_feed_flutter sample application, it became problematic to not have some kind of "mock” authentication system in place to better test the application. After all, what good is a social feed if there's only one person in it?
The stream_feed Dart package (upon which stream_feed_flutter is based) contains a function to generate user authentication tokens. However, this token generation function is only meant to be used server-side, and not on the client itself. That means we needed a server.
Note: At the time of writing, Stream is still working on some of the packages mentioned in this article. For example, the stream_feed_flutter package has not been released at the time of writing this article.
The Solution
Stream's Activity Feeds support a variety of different backend clients, but for the purposes of this demo, the stream_feed Dart package will work perfectly. It may not be a well-known fact, but you can use Dart to create web servers!
This article will take you through the process we used to create and deploy a simple Dart server to generate Stream user tokens.
Ready? Let’s get started!
Step One - Create the Initial Project
The first step is to create a Dart web server project:
- In your terminal, navigate to where you'd like to save your project.
- Run the following command:
$ dart create -t server-shelf stream_auth_generator
- Open the newly created project in your preferred IDE.
You should now see your server.dart
file, and it should look like this:
123456789101112131415161718192021222324252627282930313233import 'dart:io'; import 'package:shelf/shelf.dart'; import 'package:shelf/shelf_io.dart'; import 'package:shelf_router/shelf_router.dart'; // Configure routes. final _router = Router() ..get('/', _rootHandler) ..get('/echo/<message>', _echoHandler); Response _rootHandler(Request req) { return Response.ok('Hello, World!\\n'); } Response _echoHandler(Request request) { final message = params(request, 'message'); return Response.ok('$message\\n'); } void main(List<String> args) async { // Use any available host or container IP (usually `0.0.0.0`). final ip = InternetAddress.anyIPv4; // Configure a pipeline that logs requests. final _handler = Pipeline().addMiddleware(logRequests()).addHandler(_router); // For running in containers, we respect the PORT environment variable. final port = int.parse(Platform.environment['PORT'] ?? '8080'); final server = await serve(_handler, ip, port); print('Server listening on port ${server.port}'); }
Step Two - Create an Application in your Stream Dashboard
If you haven’t already, sign up for a free Stream account. Once you’ve signed up, create a project:
- Go to your Stream dashboard.
- Create a new project by clicking Create app.
- Take note of your key, secret, and appid.
Are you looking for a chat solution to integrate into your app? If you’re a qualifying startup, apply for a free Maker Account today! You’ll gain access to Stream’s Chat Startup Plan, Activity Feeds Growth Plan, and more.
Step Three - Set Your Environment Variables
In order to securely use your key, secret, and appid, you need to pass them into our program as runtime environment variables.
This is done via the --define
command. Add the following lines to your main
function, prior to the existing code, in order to receive these environment variables:
123const key = String.fromEnvironment('key'); const secret = String.fromEnvironment('secret'); const appId = String.fromEnvironment('appId');
At this point, you can run your server like so:
1$ dart run bin/server.dart --define=key=YOUR_KEY_HERE --define=secret=YOUR_SECRET_HERE --define=appId=YOUR_APPID_HERE
Optionally, you can create a run configuration in either VSCode or IntelliJ to handle this for you.
Step Four - Add Stream Feed to Your Server
Go to your pubspec.yaml
file and add the following under the dependencies section:
1stream_feed: ^latest_version
Note: At the time of writing, the latest version is
0.3.0
.
Run pub get
.
Back in server.dart
, add the following code below your environment variables:
12345678910var client = StreamFeedClient.connect( key, secret: secret, runner: Runner.server, appId: appId, options: StreamHttpClientOptions( location: Location.usEast, connectTimeout: Duration(seconds: 15), ), );
This instantiates a StreamFeedClient
that you can use for various Feeds operations. You will use it to generate your user tokens.
Step Five - Configure the Server to Return User Tokens
At the top of server.dart
, remove the _rootHandler
and _echoHandler
functions. Adjust your _router
so that it looks like this:
1final _router = Router();
Back in main
, add the following code underneath where the IP address is set:
12345_router.post('/v1/auth', (Request req) async { final payload = await req.readAsString(); final token = client.frontendToken(payload); return Response.ok(token.token); });
This code does the following:
- Sets up an endpoint called
/v1/auth
. - Accepts the request as a String.
- Creates a token using the
client
. - Returns an
ok
response containing the token.
Now, if you restart the server, you should be able to make a curl HTTP request in your terminal and receive a token back:
1$ curl -d "username=YOUR_USERNAME_HERE" -X POST <http://localhost:8080/v1/auth>
You should now have a working server that generates a Stream user token for any username that you pass to the server.
Step Six - Deploy to Google Cloud
At this point, you are ready to deploy your server to Google Cloud. To do so, follow the instructions below:
- Download and install the Google Cloud SDK (the link will give you pretty detailed installation instructions). If you don’t want to read the instructions, the short story is:
- Download and extract the SDK (make sure you download the right SDK for the OS you're working on.)
- Install the SDK using the
[install.sh](<http://install.sh>)
script as outlined in the instructions to ensure that the SDK gets added to yourPATH
.
- In the Google Cloud console on the web, create a new project for your server.
- In the terminal for your project, run
gcloud run deploy
per Google’s deployment instructions. When you are finished, you will see your live server’s service URL.
Congratulations! Now your server is deployed! Thanks for reading, and be sure to tweet us and let us know what you build with Dart on the server!