Implement BiFrost in your app

When creating an app, you have the option to add BiFrost.

This tutorial will explain how to connect your module to BiFrost.

Once you do so, the module will be able to communicate with all of the other modules in your app over a core authentication layer. All of its endpoints will be exposed as part of a single API that BiFrost puts together from all of the modules’ endpoints. You also have the option to use BiFrost for managing permissions and users.

Note: We recommend reading through the BiFrost documentation before completing this tutorial.


There are no requirements for the language or framework used to code your module. It must only satisfy these conditions in order to connect to BiFrost:

  1. Your module must include a Dockerfile.
  2. Your module must follow the OpenAPI (Swagger) spec and expose a swagger.json file at the /docs endpoint.
  3. Your module must implement the Walhall CI/CD pipeline.
  4. Your module must use an OAuth2 library with support for JSON Web Tokens (JWTs). See the JWT authorization section for more information.
  5. At this time, your module must run on port 8080; in the future, you will be able to specify the container port in Walhall.

Implement JWT authorization

Next, you need to implement BiFrost’s authorization method.

About BiFrost authorization

For external requests to modules, BiFrost uses an OAuth2 flow to issue JSON Web Tokens (JWTs) signed with RS256.

Inside the container where the module is deployed, Walhall exposes BiFrost’s public key as the environment variable JWT_PUBLIC_KEY_RSA_BIFROST. The module must use this environment variable to decode requests from BiFrost.

BiFrost passes the JWT to the module in the Authorization HTTP header using the format JWT {token}. Example:

Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJiaWZyb3N0IiwiZXhwIjoxNTYwNjA0OTc2LCJpYXQiOjE1NjA1MTg1NzYsImNvcmVfdXNlcl91dWlkIjoiODJiZGI2YTMtMjExOS00MThmLThjMmQtY2FhYjdlYmI4OTc1Iiwib3JnYW5pemF0aW9uX3V1aWQiOiJiMjY1YmFkNS1iODEyLTRmNDItYjNlZS0zNDFlYmJiNzJjNmIiLCJzY29wZSI6InJlYWQgd3JpdGUiLCJ1c2VybmFtZSI6ImFkbWluIn0.CV8PafWuGDZSpWRI5wC6btO6cyt9udI9P5uLBdnHzVhbbIY-LH1o3qBgnRf0OAreUhRfl7zBTBMNO56pbyWeyg

Example using PyJwt

Here’s an example using the PyJwt library. It takes the encoded_jwt from the HTTP header and decodes it with the JWT_PUBLIC_KEY_RSA_BIFROST environment variable:

import jwt

jwt.decode(encoded_jwt, os.environ['JWT_PUBLIC_KEY_RSA_BIFROST'], algorithms=['RS256'])

The BiFrost JWT payload looks like this:

	"core_user_uuid": "fd76ce0c-d8be-4aa6-91ed-59e698f6af60",
	"exp": 1560472728,
	"iat": 1560436728,
	"iss": "bifrost",
	"organization_uuid": "70f0d039-e3d9-427e-b161-4e95dbd9e918",
	"scope": "read write",
	"username": "admin"
  • core_user_uuid: UUID of the CoreUser who initiated the request.
  • exp: Datetime when the token expires.
  • iat: Datetime when the token was issued.
  • iss: Issuer of the JWT. This will always be bifrost.
  • organization_uuid: UUID of the Organization that contains the CoreUser who initiated the request.
  • scope: Permission scopes granted in the request by BiFrost.
  • username: The username of the CoreUser who initiated the request.

Add module to your Walhall app and deploy

Now you have completed the minimum necessary configurations to make your module work with BiFrost. The last step is to add it to a Walhall app and deploy it.

See the Add custom module page for instructions on how to do so.

(Optional) Implement BiFrost permissions model

If you want to implement the BiFrost permissions model in your modules, then you need to create WorkflowLevels for each of your data models and implement them in the models. We recommend creating WorkflowLevel1s for all top-level data models in your module and WorkflowLevel2s for defining any nested data relationships.

See the BiFrost documentation for an example of how to implement WorkflowLevels in your data model.

Appendix: Reserved endpoint names

The following endpoint names are reserved by BiFrost and may not be implemented in your modules’ APIs:

  • /admin
  • /oauth
  • /health_check
  • /docs
  • /complete
  • /disconnect
  • /static
  • /graphql
  • /workflow
  • /core
  • /logicmodule
  • /user
  • /group
  • /milestone
  • /organization