Skip to main content

Verifying Privy Auth tokens with external libraries

When your backend receives a request, we recommends using Privy's server-auth SDK for NodeJS to verify Privy auth tokens sent from your frontend.

Depending on your backend's setup, however, you might choose to use an external library to verify Privy Auth tokens. Below are some code examples for how you should verify Privy Auth tokens in various programming languages & frameworks.

info

Don't see your language/framework, or still have questions? Shoot us an email at [email protected] with more info about your setup! We're here to help.

JavaScript/TypeScript

Using jose

First, extract the token from the request's authorization header:

const authToken = await (req.headers.authorization).replace('Bearer ', '')

Next, load your Privy public key using jose.importSPKI:

const verificationKey = await jose.importSPKI(/* your Privy public key from the console */, 'ES256');

Lastly, using jose.jwtVerify, verify that the JWT is valid and was issued by Privy!

try {
const payload = await jose.jwtVerify(authToken, verificationKey, {
issuer: 'privy.io',
audience: /* your Privy App ID */
});
console.log(payload);
} catch (error) {
console.log(`JWT failed to verify with error ${error}.`);
}

If the JWT is valid, you can extract the JWT's claims from the payload. For example, you can use payload.sub to get the user's Privy DID.

If the JWT is invalid, this method will throw an error.

Using jsonwebtoken

First, extract the token from the request's authorization header:

const authToken = await (req.headers.authorization).replace('Bearer ', '')

Next, load your Privy public key as a string.

const verificationKey = (/* your Privy public key from the console */).replace(/\\n/g, '\n');

The replace operation above ensures that any instances of '\n' in the stringified public key are replaced with actual newlines, per the PEM-encoded format.

Lastly, verify the JWT using jwt.verify:

try {
const decoded = jwt.verify(authToken, verificationKey, {
issuer: 'privy.io',
audience: /* your Privy App ID */
});
console.log(decoded);
} catch (error) {
console.log(`JWT failed to verify with error ${error}.`);
}

If the JWT is valid, you can extract the JWT's claims from decoded. For example, you can use decoded.sub to get the user's Privy DID.

If the JWT is invalid, this method will throw an error.

Go

Using golang-jwt

First, extract the token from the request's authorization header:

header := request.Header.Get("Authorization")
authToken := strings.Replace(header, "Bearer ", "", 1)

Next, load your Privy public key and app ID as strings:

verificationKey := "your-privy-public-key"
appId := "your-privy-app-id"

Lastly, parse the claims from the JWT and verify that they are valid:

// Defining a Go type for Privy JWTs
type PrivyClaims struct {
AppId string `json:"aud,omitempty"`
Expiration uint64 `json:"exp,omitempty"`
Issuer string `json:"iss,omitempty"`
UserId string `json:"sub,omitempty"`
}

// This method will be used to check the token's claims later
func (c *PrivyClaims) Valid() error {
if c.AppId != appId {
return errors.New("Aud claim must be your Privy App ID.")
}
if c.Issuer != "privy.io" {
return errors.New("Iss claim must be 'privy.io'")
}
if c.Expiration < uint64(time.Now().Unix()) {
return errors.New("Token is expired.");
}

return nil
}

// This method will be used to load the verification key in the required format later
func keyFunc(token *jwt.Token) (interface{}, error) {
if token.Method.Alg() != privyJWTAlgorithm {
return nil, fmt.Errorf("Unexpected JWT signing method=%v", token.Header["alg"])
}
// https://pkg.go.dev/github.com/dgrijalva/jwt-go#ParseECPublicKeyFromPEM
return jwt.ParseECPublicKeyFromPEM([]byte(verificationKey)), nil
}

// Check the JWT signature and decode claims
// https://pkg.go.dev/github.com/dgrijalva/jwt-go#ParseWithClaims
token, err := jwt.ParseWithClaims(authToken, &PrivyClaims{}, keyFunc)
if err != nil {
fmt.Println("JWT signature is invalid.")
}

// Parse the JWT claims into our custom struct
privyClaim, ok := token.Claims.(*PrivyClaims)
if !ok {
fmt.Println("JWT does not have all the necessary claims.")
}

// Check the JWT claims
err := Valid(privyClaim);
if err {
fmt.Printf("JWT claims are invalid, with error=%v.", err);
fmt.Println();
} else {
fmt.Println("JWT is valid.")
fmt.Printf("%v", claims)
}

Python

Using pyjwt

First, extract the token from the request's authorization header:

authToken = (request.headers.get('Authorization')).replace('Bearer ', '')

Next, load your Privy public key and app ID as variables:

verificationKey = 'your-privy-public-key'
appId = 'your-privy-app-id'

Lastly, verify that your JWT is valid:

try:
decoded = jwt.decode(authToken, verificationKey, issuer='privy.io', audience=appId, algorithms=['ES256'])
print(decoded)
except:
print("Token verification failed")

If the JWT is valid, you can extract the JWT's claims from the decoded object. For example, you can use decoded['sub'] to get the user's Privy DID.

If the JWT is invalid, this method will throw an error.