Tokens are accessible only when using the React and React Native SDKs with a valid partnerId. Partners integrating via EIP-6963 will not have access to user tokens.
When using Sophon Account, everytime a user authorizes an application connection our Account Server issues an access token using RS256 algorithm, with a secret private key. You can use this token to authenticate requests to our API, and if you don’t want to implement a custom SIWE flow, you can use the token on your own to make sure that the user is authenticated and owns the account.
import { useSophonToken } from '@sophon-labs/account-react-native';
General Implementation
export default function App() {
  const [token, setToken] = useState<SophonJWTToken | null>(null);
  const [loading, setLoading] = useState(false);
  const { getAccessToken } = useSophonToken();
  const updateAccessToken = useCallback(async () => {
    setLoading(true);
    const newToken = await getAccessToken();
    setToken(newToken);
    setLoading(false);
  }, [getAccessToken]);

  useEffect(() => {
    updateAccessToken();
  }, [updateAccessToken]);
  
  return (
    <div>
      <h1>My Token: {token?.value}</h1>
    </div>
  );
}

JWT Token Payload

We follow standard JWT RFC-7519, and add some more fields to give more context to the token.
aud
string
Audience for the JWT token. This claim shows what domain of the intended audience of the JWT. In this context, the audience is your partnerId.When processing and validating the token by yourself, the value of this field should match with your partnerId that we provided you.
iss
string
Issuer of the JWT token. This claim always shows auth.sophon.xyz generated and issued the JWT.
sub
string
Subject of the JWT token, representing the user’s smart wallet address.
iat
string
Timestamp when the JWT token was issued.
exp
string
Timestamp when the JWT token will expire. This is generally some hours after the token was issued.
scope
string
The scope of data granted by the user that allows us to share specific data with the application that the user is connecting to. Possible scopes are: email, twitter, gmail, discord and telegram. Multiple scopes could be provided and they are separated by a space.

Sending the Token

Once you got the token issued, you can send it during the calls to your API using the classic header Authorization: Bearer <token>. See how to do it with different frameworks:
import axios from 'axios';

export const callBackend = (token: string) => {
  const response = await axios.get(`${process.env.BACKEND_URL}/do-something`, {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });
  
  if (response.status !== 200) {
    throw new Error('Failed to call backend.');
  }

return response.data;
};

Decoding the JWT

When you have the token, it is useful to decode it for additional verification during your backend processing. Given that only Sophon can issue tokens, you can validate that the token you are receiving is valid, and it assert that the user owns the account. By using the JWKS standard, and having the public key we provide, you can decode by yourself, without having to making additional calls.

Decode Using Sophon Account SDK

To make things easier, we provide a SDK that can decode the token for you:
npm install @sophon-labs/account-api-sdk
Then, you can use it in your code:
import { SophonAPISDK } from "@sophon-labs/account-api-sdk";

const partnerId = "my-partner-id";
const sdk = SophonAPISDK("testnet", partnerId);
const decodedToken = sdk.auth.decodeJWT(token);

console.log(decodedToken); // { iss: 'xxxx', exp: nnnn, ... }

Decoding the token using JWKS libraries

One of the options is to use a JWKS library to decode the token. For example, using jsonwebtoken and jwks-rsa libraries:
import jwt, { JwtPayload } from "jsonwebtoken";
import { JwksClient } from "jwks-rsa";

const jwksUrl = `https://api.my.staging.sophon.xyz/.well-known/jwks.json`;
// https://api.my.sophon.xyz/.well-known/jwks.json for production

// The client should be initialized as
const client = new JwksClient({
  jwksUri: jwksUrl,
  rateLimit: true,
  cache: true,
  cacheMaxEntries: 5, // Maximum number of cached keys
  cacheMaxAge: 600000, // Cache duration in milliseconds (10 minutes in this case))}
});

const signingKey = await client.getSigningKey();
const publicKey = signingKey.getPublicKey();

const decodedToken: JwtPayload = jwt.verify(encodedJwt, publicKey, {
  ignoreExpiration: false,
}) as JwtPayload;

console.log(decodedToken); // { iss: 'xxxx', exp: nnnn, ... }