JWT Token Generation Using AWS Lambda

Introduction

Here at BeamWallet we tend to prefer micro-service architecture approach as opposed to archaic monolithic thinking. Recently we came across a simple/common issue which is generating JWT Token to allow our servers to communicate between each other.

Since all of our systems live in private VPCs  and in the interest of the DRY principle we decided to build a centralised service that would handle all of this. We built the solution using AWS Lambda and also AWS API Gateway.

We have 2 different ways of deploying and for secret storing. 

AWS  Elastic Beanstalk with AWS Secret Manager

Our EBS applications are Java Spring backends which have all the passwords and keys stored in AWS Secret Manager.  On start up of each app all passwords are loaded from AWS Secret Manager and loaded into the System Properties.

Our naming convention for naming secrets stored in the Secret Manager is <system>/<environment>
Eg core/dev  or common/staging (where common has commonly used variables across all systems)

AWS ECS with Ansible

We deploy our other apps to ECS using ansible, where the secrets are stored in our Ansible Vault, and after the passwords are stored in ECS' Task definition as Environment Variables.

Our Solution (In Lambda)

Setting up IAM

Add the following roles

Screen Shot 2018-08-10 at 5.19.15 pm.png

Add the Lambda Function

Screen Shot 2018-08-10 at 5.22.18 pm.png

Configure the Lambda function

Set the handler to org.srini.awslambda.examples.generatejwt.GenerateJWTFunctionHandler::handleRequest

Screen Shot 2018-08-10 at 5.24.47 pm.png

Private Key Retrieval

As mentioned above we store our secrets in 2 different locations so we wanted our function to be smart enough to know where to get the private key from. We have a list which contains which service to get which key from.

The easiest one to get the secrets from was the AWS Secrets using the aws-java-sdk. We have all our private keys with the same name so the naming convention was really easy. 

String endpoint = "secretsmanager.eu-central-1.amazonaws.com";
AwsClientBuilder.EndpointConfiguration config = new AwsClientBuilder.EndpointConfiguration(endpoint, region);
AWSSecretsManagerClientBuilder clientBuilder = AWSSecretsManagerClientBuilder.standard();
clientBuilder.setEndpointConfiguration(config);
AWSSecretsManager client = clientBuilder.build();
GetSecretValueRequest request = new GetSecretValueRequest().withSecretId(service + "/" + environment);
String res = client.getSecretValue(request).getSecretString();
HashMap map = new Gson().fromJson(res, new HashMap<String, String>().getClass());
return map.get(AWS_SECRET_KEYWORD).toString();

The hardest step was  getting the private key from the ECS configuration. To access we needed retrieve the task definition from within the container definition which is inside the service. Again we were following the same naming conventions across all of our services which made this task much easier.

String privateKey = "";
AmazonECSClientBuilder clientBuilder = AmazonECSClientBuilder.standard();
clientBuilder.setRegion(region);
AmazonECS client = clientBuilder.build();
String commonName = environment + "-" + service;
List<Service> services = client.describeServices(new DescribeServicesRequest().withCluster(commonName).withServices(commonName)).getServices();
if (service.isEmpty()) {
    throw new IllegalArgumentException("No cluster/service is found with " + commonName);
}
// will always return 1 or 0
String taskDefinition = services.get(0).getTaskDefinition();
List<ContainerDefinition> containerDefinitions = client.describeTaskDefinition(new DescribeTaskDefinitionRequest().withTaskDefinition(taskDefinition)).getTaskDefinition().getContainerDefinitions();
if (containerDefinitions.isEmpty()) {
    throw new IllegalArgumentException("No container definitions is found with " + commonName);
}
// will always return 1 or 0
for (KeyValuePair keyPair : containerDefinitions.get(0).getEnvironment()) {
    if (keyPair.getName().equals(AWS_ECS_KEYWORD)) {
        privateKey = keyPair.getValue();
    }
}
return privateKey;

Key Generation

We are using the Java Security Library to generate the token, io.jsonwebtoken.jjwt to generate the JWT token, and using Lambda variables to set how long we want the time out to be. 

public class TokenGenerator {
    private final int DEFAULT_TIME_IN_MINUTES = 10;
    private final String timeInMinutes = System.getenv("TIME_IN_MINUTES");
    private final String TOKEN_TYPE = "typ";
    private final String RND = "rnd";

    public String generateToken(String secretKey, String subject) throws NoSuchAlgorithmException, InvalidKeySpecException {
        int TIME_IN_MINUTES = DEFAULT_TIME_IN_MINUTES;
        if (!com.amazonaws.util.StringUtils.isNullOrEmpty(timeInMinutes)) {
            TIME_IN_MINUTES = Integer.parseInt(timeInMinutes);
        }
        String jwtToken = "";
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(secretKey)));
        jwtToken = Jwts.builder()
                .claim(TOKEN_TYPE, "service")
                .claim(RND, Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()))
                .setSubject(subject)
                .setIssuedAt(new Date())
                .setExpiration(Date.from(LocalDateTime.now().plusMinutes(TIME_IN_MINUTES).atZone(ZoneId.systemDefault()).toInstant()))
                .signWith(SignatureAlgorithm.RS512, privateKey)
                .compact();
        return jwtToken;
    }
}

API Gateway

The api gateway was used just as a very simple means to ensure we were able to build/develop and also would be able to use on all environments. To set up the API Gateway

Step 1: Create API

Screen Shot 2018-08-10 at 4.33.02 pm.png

Step 2: Link to Lambda

 

Screen Shot 2018-08-10 at 4.33.45 pm.png

Step 3: Deploy the API

Screen Shot 2018-08-10 at 5.13.00 pm.png

They came, they saw, they Beamed

This year, Beam became the first app to let UAE pay for fuel from their car. 12 milion litres later, here’s a little throwback to our Beam pioneers.

Based in Dubai, Maureen, Brenda, Hadi and Ahmed were the first in UAE to trial Beam at ENOC in July this year. Watch what they had to say or read the interview below.

 

Maureen

 

It was all too easy. It was actually a little strange. Because I have the habit of having to get out of the car and pay. I wouldn’t mind pumping my own gas but it was extremely easy. I can never imagine using my credit card again to pay for gas.

 

“It was all too easy. It was actually a little strange.”

 

Brenda

It’s actually been a great experience. It’s very easy and convenient to use, and hassle-free because I don’t have to get out of the car. It’s just easy, just press the button and it automatically detects how much you owe, and you pay via the app and you’re on your way. It’s very quick, easy and hassle-free.

 

“Just press the button… and you’re on your way”

 

Ahmed

 

The experience was really good. It was really fast. I didn’t have to get out of my car. I didn’t have to hand over my credit card. I just had to take my phone out, use Beam, and it was fast.

 

“I didn’t have to get out of my car. I didn’t have to hand over my credit card.”

 

Hadi

 

It’s an amazing experience because I always wanted to pay with credit card at the gas station. I couldn’t earlier because there was an extra charge. And when it was available, you always had to step out of the car to pay with the PIN because the machines were not mobile.

 

Now I can sit in the car, pay with Beam, enjoy the rewards and not have to step out of the car especially with the hot weather.

 

“It’s an amazing experience… Now I can sit in the car, pay with Beam, and enjoy the rewards.”

 

Related posts

Like what you see? Beam at ENOC today to win fuel for a year: www.winfuel.ae

Mitch Williams won fuel for a year in October. See what he had to say here.

 

 

The story behind Beam at ENOC

They say Rome wasn’t built in a day. This year, Beam became the first app to let UAE pay for fuel from their car. The path was not without challenges. Our product team gives us a behind-the-scenes look at the journey to creating a world-first.

 

Where did the idea come from?

Testing in the lab   

Testing in the lab

 

ENOC approached us to do a pilot in late 2015. Their goal was to let UAE residents be the first in the world to pay with their phones at the pump.

 

How did Beam execute this?

It was a long journey due to the nature of the petrol station infrastructure. We had to do a lot of cross border testing of the solution step by step between Sydney (where our product team is based) and Dubai.

 

What challenges did Beam face?

The primary challenge was designing a solution where the series of events (sessions) between Beam and ENOC's systems are managed seamlessly without the user feeling all the steps involved. From the time the customer arrives at the petrol station to payment, the number of scenarios that could go wrong was quite high.

 

ENOC’s goal was to let UAE residents be the first in the world to pay with their phone at the pump.”

 

What issues did the team solve in the process?

We solved:

  • The network connectivity issues between Beam's (cloud based) and ENOC's (closed network/VPN) systems .

  • The mapping out of events between Beam and ENOC's systems accurately and reliably. One of our developers said this felt like "stacking peas with a boxing glove".

  • Real life scenarios that could not be encountered in a lab environment. We continuously monitored the logs for such scenarios and proactively addressed them on a daily basis.

 

“Instead of providing the same payment method at all places, we optimise the experience based on the environment you are in.”

 

What are the key achievements with this particular solution?

We created a world-first experience in the UAE and the growth rate was beyond our expectations. We have 50K Beamers transacting at ENOC, 12 million litres of fuel pumped, and 210k tanks filled so far and this is growing as we speak.

 

“One of our developers said this felt like stacking peas with a boxing glove.”

 

Why is this solution unique?

This solution is unique because:

  • We use BLE beacons at the pump to make the pump selection easy through the app

  • Instead of providing the same payment method at all places, we optimise the experience based on the environment you are in.

  • Beam is a wallet you can use at over 2,600 stores in the UAE not just at ENOC stations, which makes it convenient for our customers.

 

      “The growth rate was beyond our expectations.”

The first Beamers to test the fuel experience

The first Beamers to test the fuel experience

What does this mean for the future of Beam?

  • We’ve always believed that the payment experience should be optimised based on the environment instead of giving customers one-size-fits-all solutions.

  • Our experience at ENOC proved that you can alter the way we pay to make it easier for the customers, and when you do this, people will switch to pay with Beam.

 

“Beam is a wallet you can use at over 2,600 stores in the UAE, not just at ENOC stations.”

 

What does this mean for the future of Beam? (cont…)

  • We will continue to improve our current experiences at ENOC, restaurants (tipping, splitting bills etc.) and tap to pay at the checkout.

  • We are continually on the lookout for new opportunities where we can make the payment method easier and more convenient for our customers.

  • Our long term vision is that payments should be an entirely seamless and rewarding experience for buyers and sellers.

 

“The payment experience should be optimised based on the environment instead of giving customers one-size-fits-all solutions.”

 

Related posts

Like what you see? Beam at ENOC today to win fuel for a year: www.winfuel.ae

Maureen, Brenda, Hadi and Ahmed were the pioneers of the Beam at ENOC experience.

See what they had to say here.

 

 

Visualising Invite a Friend

We love Beam. We want our customers to love Beam. We want them to tell their friends how much they love Beam and we want their friends to love Beam. Like many other sites and services on the web we encourage this with a refer a friend program.

The Beam referral program works in the usual way: You have a code. You give your code to a friend. They sign up with it and Beam says thank you by giving you both some cash to spend.

These sort of rewards are open to abuse although the incidence of this is rare. We have fraud detection and protection methods in place but one of the best ways to check on these is to expose the data and get a feel for it. So we started out visualising our refer a friend network. What we found was so cool that we just have to share it:

It looks almost organic. Like the view through a microscope. You have to zoom in for the best effect.

Surprisingly nobody on our team can recall ever seeing an invite a friend network presented like this. Hopefully you find it as engrossing as we do.

To answer the common questions:

  1. Yes this is a small sample of data, there is too much to practically display at once, but the individual networks are complete.
  2. The arrows point from the inviter to the invitee.
  3. The visualisation is built using http://visjs.org/

I have measured out my life In coffee spoons

“I have measured out my life in coffee spoons” wrote T. S. Eliot in The Love Song of J. Alfred Prufrock a poem ostensibly about time and not much at all about coffee. Whereas here we have a heatmap showing time and space and very much about coffee. It plots coffee purchases made with Beam against where the purchase was made vs the time of day and it clearly shows that Dubai wakes up with coffee on it’s mind and it wakes up at 7am. It also shows that all that coffee is having some effect because the caffeination doesn’t stop for the rest of the day.

 

We hope all that coffee is helping people to meet and talk and fall in love and create masterpieces and we hope that you enjoy this bit of visualisation eye candy.

The Beam Engineering Team will leave you with another coffee quote by the late great Terry Pratchett “Coffee is a way of stealing time that should by rights belong to your older self.”