Create a JWT
*If you are a partner using Marketplace (legacy) please disregard JWT. JWT is only for existing partners using the Marketplace API. You can tell which API you're using by checking the URL. If your API URL is https://pointofsale.doordash.com, you're using the Marketplace (legacy) API.
Marketplace APIs are not yet generally available. Please record interest in early access here.
JSON Web Tokens (JWTs) are a token format for authentication used to communicate with DoorDash APIs. They allows two parties to communicate securely by signing the information. JWTs allow users to establish trust with the service without ever having to send a secret over the wire and creation of JWTs has language support in all common programming languages
This page covers the Marketplace API. If you're an existing customer using the Marketplace (legacy) API, a JWT Token is not necessary.
Using a JWT to authenticate with the API
In order to authenticate with the API, provide the JWT as a Bearer token in the Authentication header, as well as the auth-version
Authorization: Bearer [JWT]
auth-version: v2
User-Agent: [camelcase] provider_type/1.0
Anatomy of a JWT​
JWTs consist of three parts separated by periods which are:
- Header
- Payload
- Signature
The results is a token that looks like aaa.bbb.ccc
Header​
The header specifies the algorithm used to sign the token - HMAC SHA 265 (HS265) and the DoorDash JWT version (v1)
{
"alg": "HS256",
"typ": "JWT",
"dd-ver": "DD-JWT-V1"
}
The header is Base64url encoded and makes the first part of the JWT.
Payload​
The content of the token as a json object. This content can be trusted by the recipient.
Payload format
{
"aud": "doordash",
"iss": DEVELOPER ID,
"kid": KEY ID,
"iat": ISSUED AT,
"exp": EXPIRATION
}
aud - Audience. Always set to "doordash"
.
iss - Issuer. Set to the Developer ID (UUID format).
kid - Key ID. Set to the Key ID (UUID format) that was used to sign the JWT.
iat - Issued At. When the token was created. Formatted as seconds from the epoch. iat cannot be in the future.
exp - Expiration. When the token expires. Formatted as seconds from the epoch. exp has a maximum value of 30 minutes (1800 seconds) beyond the issued at time.
Example
{
"aud": "doordash",
"iss": "582e4f20-0f48-4bc2-99c2-e094675e2919",
"kid": "585698aa-2aa6-4bb4-8b3f-dd9d3f47dc28",
"iat": 1636463841,
"exp": 1636465641
}
The payload is Base64url encoded and makes the second part of the JWT.
Signature​
The signature is used to verify the content's authenticity. Only someone with the signing secret is able to produce the correct signature. The signature is computed through the HMAC SHA256 (HS256) algorithm.
The signature is Base64url encoded and makes the third part of the JWT.
Protecting your secret​
Treat you signing secret like a password. Put your secret into a secure store or vault to protect it from theft and misuse.
Creating a JWT​
Prerequisites​
Before getting started, ensure you have created and saved an access key from the Developer Portal.
To continue, you will need: developer_id, key_id and signing_secret
Install a JWT library​
Most programming languages provide support for creating JSON Web Tokens (JWTs) either directly in the language or as a package. Select your language and then follow the instructions to install the package, if needed.
- Node.js
- Python
- PHP
- Java
- Kotlin
- C#
Open a terminal and navigate to your project directory, then run:
npm install jsonwebtoken
Open a terminal and navigate to your project directory, then run:
pip3 install pyjwt
PHP supports JWTs without any additional packages; head to the next step!
Copy this snippet into your build.gradle file:
dependencies {
implementation("io.jsonwebtoken:jjwt-api:0.11.1")
implementation("io.jsonwebtoken:jjwt-impl:0.11.1")
implementation("io.jsonwebtoken:jjwt-jackson:0.11.1")
}
Copy this snippet into your build.gradle.kts
file:
dependencies {
implementation("io.jsonwebtoken:jjwt-api:0.11.5")
implementation("io.jsonwebtoken:jjwt-impl:0.11.5")
implementation("io.jsonwebtoken:jjwt-jackson:0.11.5")
}
To use these dependencies, you'll need to target at least version 11 of a JDK. For example, if targeting Amazon Corretto 17 then update build.gradle.kts
file section to:
kotlin {
jvmToolchain(17)
}
Open a terminal and navigate to your project directory, then run:
dotnet add package System.IdentityModel.Tokens.Jwt
Generate a JWT​
JWTs are created using an access key. Use these code snippets to generate a correctly-formatted JWT from your access key.
- Node.js
- Python
- PHP
- Java
- Kotlin
- C#
Copy the code snippet below into your project file. Replace PASTE_YOUR_ACCESS_KEY_HERE
with your access key.
const jwt = require('jsonwebtoken')
const accessKey = PASTE_YOUR_ACCESS_KEY_HERE
const data = {
aud: 'doordash',
iss: accessKey.developer_id,
kid: accessKey.key_id,
exp: Math.floor(Date.now() / 1000 + 300),
iat: Math.floor(Date.now() / 1000),
}
const headers = { algorithm: 'HS256', header: { 'dd-ver': 'DD-JWT-V1' } }
const token = jwt.sign(
data,
Buffer.from(accessKey.signing_secret, 'base64'),
headers,
)
console.log(token)
Then, test your code. In your terminal, run:
node app.js
If you were successful, you should see output like this:
Copy the code snippet below into your project file. Replace PASTE_YOUR_ACCESS_KEY_HERE
with your access key.
from os import access
import jwt.utils
import time
import math
accessKey = PASTE_YOUR_ACCESS_KEY_HERE
token = jwt.encode(
{
"aud": "doordash",
"iss": accessKey["developer_id"],
"kid": accessKey["key_id"],
"exp": str(math.floor(time.time() + 300)),
"iat": str(math.floor(time.time())),
},
jwt.utils.base64url_decode(accessKey["signing_secret"]),
algorithm="HS256",
headers={"dd-ver": "DD-JWT-V1"})
print(token)
Then, test your code. In your terminal, run:
python3 app.py
If you were successful, you should see output like this:
function base64UrlEncode(string $data): string
{
$base64Url = strtr(base64_encode($data), '+/', '-_');
return rtrim($base64Url, '=');
}
function base64UrlDecode(string $base64Url): string
{
return base64_decode(strtr($base64Url, '-_', '+/'));
}
$header = json_encode([
'alg' => 'HS256',
'typ' => 'JWT',
'dd-ver' => 'DD-JWT-V1'
]);
$payload = json_encode([
'aud' => 'doordash',
'iss' => '{developer_id}',
'kid' => '{key_id}',
'exp' => time() + 300,
'iat' => time()
]);
$base64UrlHeader = base64UrlEncode($header);
$base64UrlPayload = base64UrlEncode($payload);
$signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, base64UrlDecode({signing_secret}), true);
$base64UrlSignature = base64UrlEncode($signature);
$jwt = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.HashMap;
public class main {
public static void main(String[] args) {
Map<String, Object> claims = new HashMap<>();
// Replace the three constants below with the credentials generated from the DoorDash Developer portal
claims.put("iss", "{developer_id}");
claims.put("kid", "{key_id}");
byte[] keyBytes = Decoders.BASE64URL.decode("{signing_secret}");
claims.put("aud", "doordash");
// Set token expiry to be one minute
claims.put("exp", ZonedDateTime.now(ZoneOffset.UTC).plusMinutes(5).toEpochSecond());
claims.put("iat", ZonedDateTime.now(ZoneOffset.UTC).toEpochSecond());
Key key = Keys.hmacShaKeyFor(keyBytes);
String jwt = Jwts.builder()
.setHeaderParam("dd-ver", "DD-JWT-V1")
.setHeaderParam("typ", "JWT")
.setClaims(claims)
.signWith(key)
.compact();
System.out.println(jwt);
}
}
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.io.Decoders
import io.jsonwebtoken.security.Keys
import java.security.Key
import java.time.ZoneOffset
import java.time.ZonedDateTime
import kotlin.collections.HashMap
val claims = HashMap<String, Any?>();
claims["aud"] = "doordash";
claims["iss"] = "{developer_id}";
claims["kid"] = "{key_id}";
claims["exp"] = ZonedDateTime.now(ZoneOffset.UTC).plusMinutes(5).toEpochSecond()
claims["iat"] = ZonedDateTime.now(ZoneOffset.UTC).toEpochSecond();
val keyBytes = Decoders.BASE64URL.decode("{signing_secret}")
val key: Key = Keys.hmacShaKeyFor(keyBytes)
val jwt: String = Jwts.builder()
.setHeaderParam("dd-ver", "DD-JWT-V1")
.setHeaderParam("typ", "JWT")
.setClaims(claims)
.signWith(key)
.compact();
Copy the code snippet below into your project file. In the accessKey
dictionary, replace the placeholder values with values from your access key.
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
var accessKey = new Dictionary<string, string>{
{"developer_id", "PLACEHOLDER"},
{"key_id", "PLACEHOLDER"},
{"signing_secret", "PLACEHOLDER"}
};
var decodedSecret = Base64UrlEncoder.DecodeBytes(accessKey["signing_secret"]);
var securityKey = new SymmetricSecurityKey(decodedSecret);
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var header = new JwtHeader(credentials);
header["dd-ver"] = "DD-JWT-V1";
var payload = new JwtPayload(
issuer: accessKey["developer_id"],
audience: "doordash",
claims: new List<Claim> { new Claim("kid", accessKey["key_id"]) },
notBefore: null,
expires: System.DateTime.UtcNow.AddSeconds(300),
issuedAt: System.DateTime.UtcNow);
var securityToken = new JwtSecurityToken(header, payload);
var token = new JwtSecurityTokenHandler().WriteToken(securityToken);
Console.WriteLine(token);
Then, test your code. In your terminal, run:
dotnet run
If you were successful, you should see output like this: