Authorization is one of the essential parts of any iOS application. Once a user is logged in, it's your authorization scheme that will make sure users can't interact with your app in ways they're not allowed to. Without a robust authorization scheme, hackers could easily access sensitive user data and engage in other damaging activities such as scamming.
Thankfully, the widespread use and standardization of JWT (JSON Web Tokens) have made robust and cryptographically secure authorization more straightforward to achieve.
In this article, we'll use Stream Chat as an example service to authorize our users for using Swift Lambda to generate JWTs. You can then use the JWT for interacting with the Stream Chat service via the REST API or by configuring the iOS Chat SDK.
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
After authenticating with a login and password or another method, the user receives a JWT. After authentication, the user will attach this JWT to every request as a way of proving their identity and permission to access a particular resource. This JWT was signed by your server during authentication using a secret key and is verified in subsequent requests.
Since JWTs should be generated and verified server-side, we can set up an AWS Lambda written in Swift to do that job. You can choose an alternative method and language, but the next steps will be different. By the end, we'll have an HTTP endpoint that outputs a JWT for a specific user id to access Stream's chat service.
To generate a JWT, we'll use Kitura's Swift-JWT package, which takes care of the heavy lifting of building a JWT.
To install it, open your Swift Lambda's
Package.swift in its root folder and add
.package(name: "SwiftJWT", url: "https://github.com/Kitura/Swift-JWT.git", from: "3.6.2") to the package's dependency list. Also, add
"SwiftJWT" to the Lambda target's dependency list. By the end, your Package.swift will look similar to the one below.
Swift-JWT depends on the OpenSSL library to perform cryptographic operations. To install it, add
RUN yum -y install openssl-devel to your Swift Lambda's Dockerfile which can be found in its root folder. The Dockerfile should look similar to the one below.
Finally, we'll need our endpoint to accept
POST requests, since we'll send credentials in the request body. To do that, change the Swift Lambda's
serverless.yml line from
method: get to
method: post. It will look similar to the snippet below.
After you're done configuring your Swift Lambda, we can start writing code in
Sources/Lambda/main.swift. The code we need will parse a POST request and extract the
user_id field from its JSON body. After that, it will generate a JWT for that user id and return it.
We'll implement the
generateJWT(for userId: String) function in the next steps.
To generate a JWT, we'll use SwiftJWT. First, we need to declare a struct conforming to the
Claims protocol with a
user_id property of type
String. That's the only claim required by Stream. After that, we create a JWT object with the user_id claim and sign it using your Stream secret.
Note: Before you generate a JWT, it's essential to verify the request with some form of authentication such as a password and return
401 Unauthorized if it's wrong.
The main advantage of using Swift Lambda is that it's possible to iterate fast with it. After writing the JWT code, just run the
./Scripts/deploy.sh script again and wait a few seconds.
To test the endpoint and get a JWT, you can use the following curl command in your terminal. Don't forget to replace the URL with the one you got in the deploy step and change the user id if you want to.
After running that command, you should get a valid JWT. If it has a
% at the end, ignore it.
Congratulations! You've generated a valid JWT for interacting with the Stream Chat service via the REST API or by configuring the iOS Chat SDK. This logic can be adapted to work with other JWT-based services such as Auth0 and Dolby.io. To find out what else you can build with Swift on AWS Lambda, check out the Swift Lambda repository on GitHub.