Picket Docs
  • ๐Ÿ‘‹Welcome to Picket
  • Quick Start Guides
    • ๐Ÿš€Quick Start Guides
      • โš™๏ธStart Here: Setup
      • ๐Ÿ”Wallet Login
      • ๐Ÿช™Token Gating (Ethereum / EVM)
      • ๐ŸคบToken Gating (Solana)
      • ๐Ÿคนโ€โ™‚๏ธIncremental Token Gating
      • โ›”Restrict Access to Specific Wallets
      • ๐Ÿ”‘Working with Access Tokens
  • Reference
    • ๐ŸŽ“Concepts
      • ๐ŸŒŠAuth Flow
      • ๐Ÿ—ƒ๏ธConnect
      • โœ๏ธSignatures
      • ๐Ÿ”Authentication and Authorization
      • ๐ŸคนIncremental Authorization
      • ๐Ÿช™Access Tokens
      • ๐ŸงชTesting
      • โ‰๏ธErrors
      • โ›“๏ธSupported Blockchains
      • ๐ŸŒSupported Languages (Localization)
      • ๐ŸŽจModal Themes
      • ๐Ÿ’ฟOpen Source Web3 Client Libraries
    • ๐Ÿ“šLibraries and SDKs
      • Javascript Library - picket-js
      • React SDK - picket-react
      • Node.js Library - picket-node
      • Go Library - picket-go
      • Python Library - picket-python
    • ๐Ÿ”ฅIntegrations
      • ๐ŸŒˆPicket Authentication with RainbowKit
      • โšกSupabase
      • โ˜๏ธAmazon Cognito
      • ๐Ÿ›๏ธPicket Shopify App - Merchant Documentation
      • ๐Ÿ›’Picket BigCommerce App - Merchant Documentation
    • ๐Ÿ“–API Reference
      • Projects & API Keys
      • Auth
      • Chains
      • Wallets
      • Contracts
      • OAuth 2.0
  • ๐Ÿ•น๏ธTutorials
    • ๐ŸŒŽSign-In with Wallet (React)
    • ๐ŸฐToken Gated Photo Board (React)
    • ๐Ÿ”—Link a Wallet to a Web 2.0 Account
    • ๐ŸคIncremental Authorization (React)
Powered by GitBook
On this page
  • Anatomy of an Access Token
  • Get an Access Token
  • Use an Access Token
  • Validate an Access Token
  • Steps to Manually Validate an Access Token
  1. Reference
  2. Concepts

Access Tokens

Access tokens represent a secure and credible verification of wallet and/or token ownership that can be leveraged repeatedly without additional user interaction until expiration.

Anatomy of an Access Token

Access tokens represent a secure and credible verification of wallet and/or token ownership that can be leveraged repeatedly without additional user interaction until expiration.

{
    "walletAddress": "0xA548ac9c6f41B19175023B5f09c6E70f99cFeec8",
    "displayAddress": "ens.eth",
    "contractAddress": "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
    "tokenBalance": "0.1337",
    "iat": 1649191258,
    "ext": 1649191858,
    "iss": "picketapi.com",
    "sub": "ethereum:0xA548ac9c6f41B19175023B5f09c6E70f99cFeec8",
    "aud": "53e74bdf-6e6e-4f31-b0d1-ceda189a6a25",
    "tid": "58db4a26-fbc1-4c53-8741-5d39e25f54f5",
    "ver": 1
}
Atrribute
Description

chain

The blockchain for this token

walletAddress

The wallet address for this token

displayAddress

The ENS name for the wallet address if it exists; otherwise, the wallet address

contractAddress

The token contract address associated with this access token (Optional). This will only be part of the token if it is a requirement in the auth request

tokenBalance

The token balance held by the wallet address for the contract address at the time the token was issued (Optional). This will only be part of the token if it is a requirement in the auth request.

tokenIds

The token IDs address associated with this access token (Optional). This will only be part of the token if it is a requirement in the auth request.

iat

Issued at timestamp (UTC in seconds).

ext

Expiration timestamp (UTC in seconds). The default expiration is 12 hours.

iss

sub

The "subject" of the request. This field is populated with the blockchain associated with this token and the user's wallet address

aud

Identifies the project space. This field is populated with the Picket project ID

ver

The version of Picket API used to generate the token

tid

Unique token identifier

email

An auto-generated web3 email for the user based off their wallet address. There is no guarantee the user will check this inbox.

If you want an email for your users, you should collect it manually.

Get an Access Token

Access tokens are returned after a successful auth flow, which is usually initiated by picket.login. An access token is valid until its expiration timestamp (exp). Once an access token expires, the user will have to re-login to get a new one.

Remember, an access token is a secret. Never share an access token with anyone!

Once a user is logged in, you'll get their access token as part of the response from picket.login. If you are using a Picket client-side SDK, the user's access token will be saved to the browser's local storage and can be access as part of the SDK's auth state.

Examples

Get the access token from the auth state once the user is logged in

const { accessToken } = await picket.authState()
const { authState: { accessToken } } = usePicket();

Use an Access Token

curl my-offchain-nft-api.com -H 'Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXRBZGRyZXNzIjoiMHhBNTQ4YWM5YzZmNDFCMTkxNzUwMjNCNWYwOWM2RTcwZjk5Y0ZlZWM4IiwiY29udHJhY3RBZGRyZXNzIjoiMHhiYzRjYTBlZGE3NjQ3YThhYjdjMjA2MWMyZTExOGExOGE5MzZmMTNkIiwibnVtVG9rZW5zIjoiMC4xMzM3IiwibmJmIjoxNjQ5MTkxMjU4LCJpYXQiOjE2NDkxOTEyNTgsImV4dCI6MTY0OTE5MTg1OCwiaXNzIjoicGlja2V0YXBpLmNvbSIsInN1YiI6ImV0aGVyZXVtL21haW5uZXQ6MHhBNTQ4YWM5YzZmNDFCMTkxNzUwMjNCNWYwOWM2RTcwZjk5Y0ZlZWM4IiwiYXVkIjoiNTNlNzRiZGYtNmU2ZS00ZjMxLWIwZDEtY2VkYTE4OWE2YTI1IiwidGlkIjoiNThkYjRhMjYtZmJjMS00YzUzLTg3NDEtNWQzOWUyNWY1NGY1IiwidmVyIjoxfQ.nI6E5yzn3gHvw7ego37A_PkoLOLfkdrIPCjYi3XVMC6zTPSjD8-aZOB-auIW92Rgsf_NggAGiT2XXRTaEq_8hA'
const accessToken = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXRBZGRyZXNzIjoiMHhBNTQ4YWM5YzZmNDFCMTkxNzUwMjNCNWYwOWM2RTcwZjk5Y0ZlZWM4IiwiY29udHJhY3RBZGRyZXNzIjoiMHhiYzRjYTBlZGE3NjQ3YThhYjdjMjA2MWMyZTExOGExOGE5MzZmMTNkIiwibnVtVG9rZW5zIjoiMC4xMzM3IiwibmJmIjoxNjQ5MTkxMjU4LCJpYXQiOjE2NDkxOTEyNTgsImV4dCI6MTY0OTE5MTg1OCwiaXNzIjoicGlja2V0YXBpLmNvbSIsInN1YiI6ImV0aGVyZXVtL21haW5uZXQ6MHhBNTQ4YWM5YzZmNDFCMTkxNzUwMjNCNWYwOWM2RTcwZjk5Y0ZlZWM4IiwiYXVkIjoiNTNlNzRiZGYtNmU2ZS00ZjMxLWIwZDEtY2VkYTE4OWE2YTI1IiwidGlkIjoiNThkYjRhMjYtZmJjMS00YzUzLTg3NDEtNWQzOWUyNWY1NGY1IiwidmVyIjoxfQ.nI6E5yzn3gHvw7ego37A_PkoLOLfkdrIPCjYi3XVMC6zTPSjD8-aZOB-auIW92Rgsf_NggAGiT2XXRTaEq_8hA";

await fetch("my-offchain-nft-api.com", {
    method: "GET",
    headers: {
        Authorization: `Bearer ${accessToken}`
    }
});

Validate an Access Token

The simplest way to validate an access token is to leverage Picket's /auth/validate endpoint; however, you can also validate access token manually.

import Picket from "@picketapi/picket-node";

const picket = new Picket("YOUR_PROJECT_SECRET_KEY");

const accessToken = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXRBZGRyZXNzIjoiMHhBNTQ4YWM5YzZmNDFCMTkxNzUwMjNCNWYwOWM2RTcwZjk5Y0ZlZWM4IiwiY29udHJhY3RBZGRyZXNzIjoiMHhiYzRjYTBlZGE3NjQ3YThhYjdjMjA2MWMyZTExOGExOGE5MzZmMTNkIiwibnVtVG9rZW5zIjoiMC4xMzM3IiwibmJmIjoxNjQ5MTkxMjU4LCJpYXQiOjE2NDkxOTEyNTgsImV4dCI6MTY0OTE5MTg1OCwiaXNzIjoicGlja2V0YXBpLmNvbSIsInN1YiI6ImV0aGVyZXVtL21haW5uZXQ6MHhBNTQ4YWM5YzZmNDFCMTkxNzUwMjNCNWYwOWM2RTcwZjk5Y0ZlZWM4IiwiYXVkIjoiNTNlNzRiZGYtNmU2ZS00ZjMxLWIwZDEtY2VkYTE4OWE2YTI1IiwidGlkIjoiNThkYjRhMjYtZmJjMS00YzUzLTg3NDEtNWQzOWUyNWY1NGY1IiwidmVyIjoxfQ.nI6E5yzn3gHvw7ego37A_PkoLOLfkdrIPCjYi3XVMC6zTPSjD8-aZOB-auIW92Rgsf_NggAGiT2XXRTaEq_8hA";

try {
  // optionally include token ownership requirements as the second parameter
  const decodedAccessToken = await picket.validate(accessToken)
} catch (err) {
  console.error("invalid access token:", err);
}
import { Buffer } from "buffer";
// if using node >= 17.5, fetch is included and globally available
// else, install node-fetch
import fetch from "node-fetch";

const base64SecretKey = Buffer.from("YOUR_PROJECT_SECRET_KEY").toString("base64");

const accessToken = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXRBZGRyZXNzIjoiMHhBNTQ4YWM5YzZmNDFCMTkxNzUwMjNCNWYwOWM2RTcwZjk5Y0ZlZWM4IiwiY29udHJhY3RBZGRyZXNzIjoiMHhiYzRjYTBlZGE3NjQ3YThhYjdjMjA2MWMyZTExOGExOGE5MzZmMTNkIiwibnVtVG9rZW5zIjoiMC4xMzM3IiwibmJmIjoxNjQ5MTkxMjU4LCJpYXQiOjE2NDkxOTEyNTgsImV4dCI6MTY0OTE5MTg1OCwiaXNzIjoicGlja2V0YXBpLmNvbSIsInN1YiI6ImV0aGVyZXVtL21haW5uZXQ6MHhBNTQ4YWM5YzZmNDFCMTkxNzUwMjNCNWYwOWM2RTcwZjk5Y0ZlZWM4IiwiYXVkIjoiNTNlNzRiZGYtNmU2ZS00ZjMxLWIwZDEtY2VkYTE4OWE2YTI1IiwidGlkIjoiNThkYjRhMjYtZmJjMS00YzUzLTg3NDEtNWQzOWUyNWY1NGY1IiwidmVyIjoxfQ.nI6E5yzn3gHvw7ego37A_PkoLOLfkdrIPCjYi3XVMC6zTPSjD8-aZOB-auIW92Rgsf_NggAGiT2XXRTaEq_8hA";

const resp = await fetch("https://picketapi.com/api/v1/auth/validate", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        Authorization: `Basic ${base64SecretKey}`,
    },
    data: JSON.stringify({
        accessToken,
        // optionally include  token ownership requirements
        // requirements: {}
    })
});

// invalid acccess token
if (resp.status !== 200) {
    // do something
    console.error("invalid access token!");
}

// else use decoded JWT data 
const { walletAddress } = await resp.json();

console.log("valid access token for wallet address", walletAddress);

Steps to Manually Validate an Access Token

This section gets into the weeds for those who want it. For the easiest and fastest way to validate JWTs, we recommend using our validate endpoint to validate JWTs server-side which handles this all for you in a single api call.

1. Perform standard JWT validation

The process for validating any JWT is as follows

  1. Check the JWT is well-formed. This can be done without knowing the encryption method or signing key

  2. Check the standard claims

    1. The issuer iss equals picketapi.com

    2. Check that the JWT hasn't expired. The expiration time exp must be later than (>) the current unix timestamp

2. Verify the audience (aud) claim

Once you performed the standard JWT validation, you'll have the decoded JWT. With the decoded JWT, you'll want to verify that the aud equals your Picket project ID. This prevents other people from using a different an access token from another Picket-powered application.

// replace with a real ID
const PICKET_PROJECT_ID = "53e74bdf-6e6e-4f31-b0d1-ceda189a6a25";

const checkClaims = (jwt) => {
  // deconstruction can be done in parameter declaration, 
  // moved here for readability
  const { iss, aud } = jwt;
  // check both fields exist
  if (!(iss && aud)) return false;
  
  return iss === "picketapi.com" && aud === PICKET_PROJECT_ID;
}

3. (Optional) Verify token ownership requirements

If this is a token-gated API, you'll need to verify the access token meets the requirements.

import BigNumber from "bignumber.js";

const isBAYCOwner = (jwt) => {
   const { contractAddress, numTokens } = jwt;

   // check both fields exist
   if (!(contractAddress && numTokens)) return false;
   
   return (
      // Bored Ape Yacht Club contract address
      contractAddress === "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d" 
      // remember numTokens is a string!
      && BigNumber(numTokens).isGreaterThan(0) );
} 

PreviousIncremental AuthorizationNextTesting

Last updated 2 years ago

The issuer, or signer. This will always be Picket's API ()

Access tokens are used in JWT-based authentication to allow an application to access an API. To include an access token (JWT) in a request, send it as a in the .

Once a backend receives an access token in the authorization header, it should parse the header and . After validating, the backend can trust that the request came from the associated wallet address!

Check the signature. This requires fetching the corresponding public key from Pickets' JSON Web Keys (JWKs) endpoint ().

For more details on how to do this, we recommend on this standard process.

๐ŸŽ“
๐Ÿช™
Bearer Token
HTTP Authorization header
/.well-known/jwks.json
Auth0's documentation
validate the access token
https://picketapi.com