Skip to content

Create a web portal driven by the YubiEnterprise API that allows your customers to order from your organization's inventory

License

Notifications You must be signed in to change notification settings

YubicoLabs/yed-self-service

Repository files navigation

Contributors Forks Stargazers Issues Apache-2.0


Logo

YED Self Service Portal

Create a web portal driven by the YubiEnterprise API that allows your customers to order from your organization's inventory
Explore the docs »

· Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Reference Architecture
  3. Built With
  4. Getting Started
  5. Configuring Your Deployment Environment
  6. About the Lambda Logic
  7. About the React App
  8. Next Steps
  9. FAQs and Common Issues
  10. Contributing
  11. License
  12. Contact

About The Project

YubiEnterprise Delivery is a cloud-based service that enables streamlined distribution of YubiKeys to end-users’ offices or residential addresses, both domestic and international.

While YubiEnterprise Delivery (YED) can be driven entirely through the pre-built console, it comes with an API that allows for the ability to extend the functionality. This will allow your organization's developers to integrate the API into custom solutions that further meet the requirements of your business.

This example will demonstrate an end-to-end solution demonstrating the ability to integrate the YED API into a web application that users in your enterprise (or beyond) could use to create YubiKey orders from your organizations inventory.

In this project you will

  • Stand up an environment in AWS to handle the server side operations for the YED API and for handling user authentication/authorization
  • Use the YED API to create, delete, edit, and retrieve shipments as well as verify a shipment address
  • Create a front end application for your end users to order a YubiKey that has been defaulted by your organization

Disclaimer - This project is not meant to act as a production ready solution for all organizations. It is meant to demonstrate a reference architecture for how the YED API can be integrated into a custom application.

(back to top)

Reference Architecture

Reference Architecture

Here is a description of each of the components above, and why they are included in this project

  1. YubiKey Ordering Web App - The client for your application which will allow your end users to create, manage, and track their personal shipment
  2. OpenID Connect Identity Provider - Used to establish the identity of your user. In this project it is currently used to pull the JWT token to authorize the user, and track their shipments anonymously in the database. It is expected that you will eventually use your organizations IdP - which you can extend to automatically pull user claims (email, name, address)
  3. API Gateway - Manages your API that your client will use to make calls to your backend service, which will relay orders to YED
  4. Order Management Service - This is the core of your backend logic - This is where you will configure how your app will handle user requests and send them to YED. It also provides a way to abstract away the YED API secret from the client
  5. Order Database - Used to track the relationship between a user and their shipment IDs
  6. YED API - Your organizations instance of YED
  7. Email / SMS Notification - An example is included that can send an email alert to an admin if the amount of inventory remaining falls under a specified threshold

Built With

(back to top)

Getting Started

This is an example of how you may give instructions on setting up your project locally. To get a local copy up and running follow these simple example steps.

Prerequisites

  • YubiEnterprise Delivery Instance
    • For an API key contact your organization's Yubico Owner or your Yubico sales contact
    • Ensure you also have the API URL for your instance of YED
  • AWS Account
    • The AWS CLI requires specific IAM permissions to perform various actions needed to deploy your application. Please ensure your AWS account has all the permissions listed in this guide
  • Install the AWS CLI v2
  • Install the AWS Amplify CLI
  • AWS SNS (Simple Notification Service) Instance
    • Amplify is unable to create the SNS resource required to send alerts for low inventory. Follow these instructions to create an SNS resource:
      1. Open AWS SNS
      2. In the section labeled "Topics" click Create Topic
      3. Name the topic inv-monitor - Keep the default settings
      4. Once created go to "Subscriptions"
      5. Set protocol to Email, and on Endpoint enter the email address of your YED Admin who will receive inventory alerts
      6. Ensure that you confirm the email in your inbox to begin to receive alerts from AWS SNS
    • You are now ready to send alerts through this application
    • Before you exit, be sure to note your SNS topics ARN, as it will be used during the deployment step below

Installation

  1. Clone the repo
    git clone [email protected]:YubicoLabs/yed-self-service.git
  2. Install NPM packages
    npm install

(back to top)

Configuring Your Deployment Environment

There are a few different options for creating your backend environment using Amplify. The following sections outline the steps for creating your environment. Below is an overview of the options

(back to top)

Automatically Configure Your Amplify Environment

amplifybutton

(back to top)

Using This Repository to Deploy Your Amplify Environment

If the Amplify CLI detects an Amplify project in your directory, you only need to run a few commands to deploy and configure the environment. This option has less overhead than the Manual option.

  1. Ensure that you have cloned this repository - Open the terminal in the root of your project directory and run the following command
    amplify init
  2. Use the following values to initialize your Amplify environment
    • Do you want to use an existing environment? No
    • Environment Name: yeddev
    • Default Editor: Make your personal selection
    • Authentication Method: AWS Profile -> Select your personal profile
    • Give the terminal a moment to initialize the project, there are more prompts
    • Select Update Secret Values Now
      • Select yedselfsvcex
      • Update a secret
      • YED_API_TOKEN
      • Enter your API token from the YED console
      • Select 'I'm done' and perform the same steps for the resource yedselfserviceinv
      • yedselfserviceinv will also require a secret variable for the AWS SNS resource ARN - Please ensure you follow the steps in the prerequisites section to create your SNS service to get the ARN
    • Select I'm done
  3. All that is left is to publish your Amplify Env using the following command
    amplify push
    • In this step you will be prompted to add your environment variables. Ensure you add environment variables for the -
    • If your initial build fails, run the amplify push command another time
  4. Your website is ready to use, now run the following command (in localhost)
npm start
  1. If you wish to deploy the application to the web run
amplify publish

This will give you a public facing URL to test in a live environment

Caution - If you receive a 403 Error while attempting to open your application, please see this section below

(back to top)

About the Shipment Logic

This Lambda resource (yedselfserviceex) is where your backend logic to make shipments will reside - This is important as this is where your application will be calling directly to the YED API to create, manage, and get orders (and perform other operations like address validation).

The current application does not have a corresponding endpoint to every operation in YED. If additional functionality is required, use the code as a template for calling the other YED endpoints

Where is my lambada logic? - You don't need to go into the Lambda resource directly to edit your lambda, it can be done directly from your project. The Lambda index can be found in the directory amplify > backend > function > yedselfsvcex > src > index.js

On using Env and Secret Variables

At the top of the file there are some definitions that are generated based on configurations you have made using the Amplify CLI. If your code isn't working for some reason, make sure that you followed the same naming convention that was used.

How is the code structured

There are three tiers to the entire example

  • Definition of variables
  • Logic to call to YED or to Storage
  • exports.handler which acts as the "main" whenever this function is called

About exports.handler

As noted about it acts as the "main" of the application. It has four primary responsibilities

  • Gets the Secret Variables from the AWS SSM
  • Takes the JWT token passed by the user, and gets the user_sub. This will be used to identify the user
  • Switch/Case that reacts to the particular operation + path called by the user
  • Returns the response to the client

About the YED Calls

Every method essentially calls to the YED API in the same manner - The call is made and the data from the response is sent directly to the client.

There are some checks on top of some of the calls to check if the user has permission to CRUD to the shipment.

There is a 1:1 relationship between the operations + paths defined in exports,handler, and a method that calls to YED. There are a few helper methods if something needs to be done with the storage resource.

(back to top)

About the Inventory Alert

The second lambda function (yedselfserviceinv) introduces the functionality to alert an administrator if your YubiKey quantity falls below a specific threshold.

The current logic compares ALL the items of your inventory from a result of a GET /inventory API call. This lambda is also set to run once a day, and on each run will send alerts to a defined administrator indicating that there may be an item with low quantity in your YED inventory.

Where is my lambada logic? - You don't need to go into the Lambda resource directly to edit your lambda, it can be done directly from your project. The Lambda index can be found in the directory amplify > backend > function > yedselfserviceinv > src > index.js

On using Env and Secret Variables

At the top of the file there are some definitions that are generated based on configurations you have made using the Amplify CLI. If your code isn't working for some reason, make sure that you followed the same naming convention that was used.

About exports.handler

As noted about it acts as the "main" of the application. It has four primary responsibilities

  • Call to the YED API to get your full inventory
  • Determine which inventory items have a "low" quantity (threshold is determined by your business requirements)
  • Formats an email message based on the inventory amounts
  • Sends an email to AWS SNS with the message noted

Sample Email

Below is an example of an email sent by the AWS SNS service. If you do not initially receive this email after a test run, or timed trigger, please check your Spam folder.

Email Sample

(back to top)

About the React App

There are a few things that should be noted about the React App itself - While this tutorial is more focused on the big picture architecture, it is important to know how the front end is interacting with the backend to fully understand how YED is being used.

Src > Pages > Order

This is where you will find the majority of the logic needed for this application

  • Components - If you are familiar with React you will expect to find the various high level pages in this area, the components will be broken down in more detail shortly
  • Routes - These are the routes that are specific to the order form. This project has one major route schema in the high level app (Order route). Within this folders route folder you will find the definitions for how the routes are configured for each form step
  • Store - This will be extremely to understand, so be sure you peek under the hood. This is the area that will persist data through a users experience. This allows a user to jump between form stages, as well as being used by the app to determine what the user is trying to do in the form (create or edit)

Src > Pages > Components

In this section we will walk through what each component is responsible for, and some details to note - For further detail please go into the component and read the comment details

  • address - This is the form component that allows the user to input their shipping information. This is primarily built using Formik. There are some items in here that allow you to control the form schema such as field lengths. This component is not used directly by the flow, instead it is built into the delivery component
  • confirmation - This is the page where the user gets an overview of their order before they submit it. There is logic in this page that switches the context between a user creating a new order, or editing an existing order
  • delivery - This is where the user performs two actions: Sets their shipping information, and ensures that their shipping address is valid. Once a user fills out the form they submit the form, but instead of routing to the next page, the form calls to the YED API's /validate-address endpoint to ensure that Yubico can deliver to the address. If the address is not valid the shipment errors are returned back to the user to make the corrections, they will need to validate the address again before continuing.
  • key-default - This page is just a loading screen that calls to the backend using the /defaultinventory logic. This essentially preselects a key for your user, and moves them to the Delivery Component. Every component has a check, if a key has not been set, the user will be redirected to this component for a key to be chosen for them. You can extend this component to act as a catalog for your user to select the key they want
  • order-history - This shows all of a users personal orders. If a order is below shipping state 10, then they will be able to edit and delete the order. Otherwise the buttons will disappear. When tracking information becomes available it will be displayed to the user
  • order-stepper - This controls the form stepper you see at the top of the flow. It highlights what stage the user is in. Links were added to the delivery and order history step to allow a user to quickly create a new order, or see their previous order

Inventory Config

In the code you may see references to inv-config. This was created to help your organization easily manage details that you want to use for your catalog. You can set your own custom image to be displayed, and your own custom description to guide your users into selecting the correct key. For this example there is only information about the YubiKey 5Ci, but you can follow the same schema for other keys (this is based on your requirements)

Translations

You might notice that the rendering components don't contain any actual words, but instead are filled with items that look like {t["something"]}. This is used to act as an easy way to consistently configure different languages in your application. The English values can be found in public > i18n > en-US.json

(back to top)

Next Steps

Because this application is meant to act as a demo, there are a few items that need to be considered to make your deployment "production ready".

Policies to prevent abuse

his application will allow a user to order as many keys as they desire. Additional logic will need to be built in to limit the number of orders based on your requirements

Configuration based on your security requirements

This includes swapping the system out to use your identity provider, secrets management in AWS Lambda, and other controls used by your organization

Auto-filling information

You can extend this application to allow it to automatically pull user claims through an ID token, or a user service

Selectable Security Key

Right now the application will default to the Yubikey 5Ci. You can extend this application’s flow to allow a user to select a key based on your YED inventory

People and Process Impacts to Customer Service

If your application is purposed for external end users then your internal CX team needs to be prepared to handle YED/YubiKey specific inquiries. Either an internal team should be established and trained to handle these items OR you can determine if Yubico Professional Services is the preferred option.

Multi-Region PO support

The current demo is configured for a single region PO. You will need to use the proper API token for the user’s region, e.g. North America / Canada is one region, EMEA is a different region and each have their own associated API token.

More information can be found here

(back to top)

FAQs and Common Issues

Cancelling my Test Order

It should be noted that orders made through the YED API are made directly on your production inventory. YED does not currently support "sandbox" environments with fake data/inventory. During testing and development it is crucial that you not only delete orders directly from this application, but you must login to the YED Console to verify the order was removed, and to delete any lingering test shipments - Otherwise, your order will be processed and a key from your inventory will be shipped.

Orders are not processed for shipment until 3AM PST - So ensure your developers/testers are instructed to delete their shipments prior to closing their work day. This time is centrally configured across YED and cannot be edited.

My Initial Build Failed

It's been noted that the initial build will occasionally fail if a secret value was not provided to the service. If you get an error on your initial run, try running the amplify push command one more time. If the issue persists then please open an Issue on this repository so that the cause can be investigated.

I'm Getting a 403 Error After I Publish my Application

Occasionally after a deployment you may receive a 403 Error (Access Denied) when attempting to use your application.

If this occurs, please follow the steps below

  1. In AWS go to the Amplify Portal - Then find your Amplify App
  2. In the settings panel on the side, choose Rewrites and redirects
  3. Click on the Edit button
  4. Create a new rule with the following criteria
  5. Click Save
  6. Test your application

Multi-Region Purchase Orders / Organizations

If organizations are shipping keys to both the US/Canada and to EMEA, two API tokens are required, as both regions are treated as different organizations.

A user will not be able to perform operations in a EU YED instance while logged in to their US/CAN instance (the same is true of the inverse).

Before implementing a solution you should consider how many YED organizations your company will be utilizing, and how to guide your users to the appropriate portal with the correct API key for their region.

This site will be updated in the future with Multi-Region PO Support.

More information on this can be found here

aws-exports.js file missing

This will occur if you initiated your environment, but did not push/publish - Make sure you call

amplify push

or

amplify publish

aws.exports.js should automatically be generated

My API calls to YED are failing

There might be two reasons for this - You might not have configured your API secret, or your YED API URL is incorrect. See this section on configuring your Environment and Secret Variables

When I create an account, I get an error noting "User Pool does not exist"

If you receive an error indicating that a user pool does not exist (when creating an account or logging in), ensure that you go to your aws-exports.js file in your src folder. Validate that the cognito identifiers match the identifiers in the AWS Console

I made a change to my API using amplify update API and now everything is broken

This is going to be your most annoying error, I would suggest not tweaking the API very often, but if it needs to be done then ensure you do the following steps

First off, what is happening? Every time you make a local change to the API, an automatically created file is altered in amplify > backend > api > yedselfsvcex > yedselfsvcex-cloudformation-template.json

There are special configurations in this file that allow the resource to talk to Cognito, that seem to be overridden every time the API is updated. Luckily the template that we have provided will create the API resource, with the needed parameters to take in Auth values, but again these get overridden.

To troubleshoot ensure the following are in the file listed above

"Parameters": {
    ...
    "AuthCognitoUserPoolId": {
          "Type": "String",
          "Description": "The id of an existing User Pool to connect. If this is changed, a user pool will not be created for you.",
          "Default": "NONE"
        }
}
...
"Resources": {
    "paths": {
        "/your-new-path": {
            ...
            "parameters": [
                ...,
                {
                    "name": "Authorization",
                    "in": "header",
                    "required": false,
                    "type": "string"
                }
            ],
            "security": [
                {
                "Cognito": []
                }
            ],
            ...
        },
        "/your-new-path/{proxy+}": {
            ...
            "parameters": [
                ...,
                {
                    "name": "Authorization",
                    "in": "header",
                    "required": false,
                    "type": "string"
                }
            ],
            "security": [
                {
                "Cognito": []
                }
            ],
        },
    },
    "securityDefinitions": {
        "Cognito": {
            "type": "apiKey",
            "name": "Authorization",
            "in": "header",
            "x-amazon-apigateway-authtype": "cognito_user_pools",
            "x-amazon-apigateway-authorizer": {
            "type": "cognito_user_pools",
            "providerARNs": [
                {
                "Fn::Join": [
                    "",
                    [
                    "arn:aws:cognito-idp:",
                    {
                        "Ref": "AWS::Region"
                    },
                    ":",
                    {
                        "Ref": "AWS::AccountId"
                    },
                    ":userpool/",
                    {
                        "Ref": "AuthCognitoUserPoolId"
                    }
                    ]
                ]
                }
            ]
            }
        }
        },
}

If you ever get lost, or want to revert back to before you made a breaking change then come back to this file, and replace it with your changes.

(back to top)

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

License

Distributed under the Apache-2.0 License. See LICENSE for more information.

(back to top)

Contact

Yubico Developer Program

Project Link: https://github.com/YubicoLabs/yed-self-service

(back to top)

About

Create a web portal driven by the YubiEnterprise API that allows your customers to order from your organization's inventory

Resources

License

Stars

Watchers

Forks