Skip to main content

Validate ID tokens

Overview

This guide explains how to verify the validity of ID tokens issued by Mavis ID.

When a user grants authorization to a client app, Mavis ID responds with an ID token containing user information.

The ID token is a JSON Web Token (JWT) that contains the user’s information and is signed by Sky Mavis.

After receiving the ID token, you need to verify its authenticity to ensure that the user is who they claim to be. This involves sending the ID token to your backend server. Once verified, your backend server can issue an access token, allowing the user to interact with your backend server securely.

Steps

Step 1. Obtain the public keys

Use Sky Mavis's public keys to verify the ID token's signature. The keys are located at https://id.skymavis.com/.well-known/jwks.json.

By default, the signing key is rotated every 6 weeks. This means you need to programmatically or manually update your keys as they rotate. The previous keys remain valid for 7 days after rotation to allow time for you to make the update.

The following example shows two public keys: the current key used to sign all new tokens, and the previous key that has been rotated out. The example is a JSON Web Key Set (JWKS) object that contains a keys array of JWK keys. Each key contains the key type (kty), the key use (use), the key ID (kid), the curve (crv), and the x and y coordinates of the public key.

{
"keys": [
{
"kty": "EC",
"use": "sig",
"kid": "018e085d-353d-73ac-8006-c43f376631f1",
"crv": "P-256",
"x": "9rB5mWnYHdobqkn8wYG4BzM7-uC5-QOokatjct3DQU8",
"y": "cECJGhKRW__VSuYS7jxtnMDArwkrHff_P9B8xHMMhYI"
},
{
"kty": "EC",
"use": "sig",
"kid": "018e085d-2e3f-7474-8007-21c0408ba33e",
"crv": "P-256",
"x": "CGlCzoxUjGUoGnryNnmzwzyLgzqwxaSrieb0ufxliiw",
"y": "pK3QizTfodV9CFGnV-hC9dLEzBw6Gp7zldWbMWPqbog"
}
]
}

Step 2. Verify the ID token

Verify manually

To verify a JWT (JSON Web Token) token manually, follow these steps:

  1. Copy the JWT token from the Mavis ID response.
  2. Visit JSON Web Token Verifier.
  3. Paste the JWT token into the Enter JWT field.
  4. Paste the URL of the JWKs endpoint (https://id.skymavis.com/.well-known/jwks.json) into the Enter jwks endpoint or issuer domain field.
  5. Review the decoded token to ensure it contains the expected user information.

Verify programmatically

  1. Get the client ID for your app from the Developer Console: go to the Developer Console, select your app, then select ID Service in the list of products. Look for the client ID in the Client credentials section.
  1. Use the following code snippets:
package main

import (
"context"
"encoding/json"
"fmt"
"net/http"

"github.com/coreos/go-oidc/v3/oidc"
)

var (
issuer = "https://id.skymavis.com"
// Example client ID
clientID = "52b85454-dd6f-4b0f-8d7a-9e30a33e387e"
certsURL = "https://id.skymavis.com/.well-known/jwks.json"

// The Application Audience (AUD) tag for your application

config = &oidc.Config{
ClientID: clientID,
}

keySet = oidc.NewRemoteKeySet(context.TODO(), certsURL)
verifier = oidc.NewVerifier(issuer, keySet, config)
)

// AuthMavisIDRequest represents the request body for authentication with Sky Mavis
type AuthMavisIDRequest struct {
IDToken string `json:"id_token"`
}

// AuthMavisIDResponse body for auth with Sky Mavis
type AuthMavisIDResponse struct {
AccessToken string `json:"access_token"`
// Other information
}

// AuthMavisID is a handler to verify a Mavis ID token and issue an access token
func AuthMavisID(w http.ResponseWriter, r *http.Request) {

req := &AuthMavisIDRequest{}

if err := json.NewDecoder(r.Body).Decode(req); err != nil {
http.Error(w, "malformed request body", 400)
return
}

// Verify the ID token
id, err := verifier.Verify(r.Context(), req.IDToken)
if err != nil {
http.Error(w, fmt.Sprintf("ID token is not valid: %s", err.Error()), 400)
return
}

// Perform verification and issue an access token for id.Subject
json.NewEncoder(w).Encode(&AuthMavisIDResponse{
AccessToken: "Access token for " + id.Subject,
})
}

func main() {
http.HandleFunc("POST /auth/mavis-id", AuthMavisID)
http.ListenAndServe(":3000", nil)
}

Step 3. Issue an access token

After verifying the ID token, issue an access token to the user. The access token allows the user to interact with your backend server.

See also

ID Token and Access Token: What's the Difference? (auth0.com)