All Products
Search
Document Center

Drive and Photo Service:Integrate a JWT application

Last Updated:Mar 24, 2026

Authenticate a custom application with Drive and Photo Service (PDS) by using JSON Web Tokens (JWTs) to obtain an access token.

Overview

A JWT application is a custom application that uses JSON Web Token (JWT) for identity authentication. The JWT application signs data with a private key on its server side to produce a JWT string. This JWT string serves as a credential to access the PDS server, which validates it with the corresponding public key.

image

Use cases

  • Enterprise with an existing internal system: Your enterprise has an internal software system with its own account system. Users sign in through the internal login page and then access PDS features.

  • Enterprise with an existing login portal: Your enterprise has an independent account system and login portal. Combine the existing login portal with PDS to build a cloud storage system for your independent accounts.

Integration workflow

  1. Create a custom domain and a JWT application in the PDS console.

  2. Generate an RSA public-private key pair. Store the public key on the PDS server and the private key on the JWT application server.

  3. The JWT application server encodes the data, signs it with the private key to produce a JWT Assertion string, and sends the string to the PDS server.

  4. The PDS server validates the JWT Assertion with the public key and returns an access token. The JWT application server then uses this access token to call PDS APIs.

Prerequisites

Before you begin, ensure you have:

  • A PDS domain created in the PDS console.

  • A JWT application registered under that domain.

  • OpenSSL or another tool to generate RSA key pairs.

  • Node.js (if you plan to use the sample code in this guide).

Step 1: Configure keys

1.1 Create or select a domain

a1

1.2 Create or select an application

Open the domain details page. On the Applications tab, create or select an application.

k1

1.3 Set the public key

After you create or select an application, click Set Public Key.

k3

Generate a public-private key pair.k5

Important: After you generate the key pair, copy and save the private key immediately. The private key is displayed only once. Then click OK.

k4

Step 2: Obtain an access token

2.1 Generate the JWT string on the application server

Encode the data to sign and use the private key with the RS256 algorithm to generate a JWT string. The following Node.js example demonstrates this process:

const JWT = require('jsonwebtoken');

function signAssertion({ domain_id, client_id, user_id, privateKeyPEM }) {
  var now_sec = parseInt(Date.now() / 1000);
  var opt = {
    iss: client_id,
    sub: user_id,
    sub_type: "user",
    aud: domain_id,
    jti: Math.random().toString(36).substring(2),
    exp: now_sec + 60,
    // iat: current time in seconds
    // nbf: not before
    auto_create: false,
  };
  return JWT.sign(opt, privateKeyPEM, {
    algorithm: "RS256",
  });
}

JWT claim reference

Field

Required

Type

Description

iss

Yes

String

The application ID.

sub

Yes

String

The user ID or domain ID, depending on the sub_type value.

sub_type

Yes

String

The account type. Valid values: user -- sub is the user ID, and a standard user access token is issued. service -- sub is the domain ID, and a domain service account access token with super administrator privileges is issued.

aud

Yes

String

The domain ID.

jti

Yes

String

A unique identifier for the JWT, generated by the application. Length: 16-128 characters. Use a UUID.

exp

Yes

Integer

The JWT expiration time in Unix epoch seconds. The window between the effective time and expiration time must not exceed 15 minutes. To prevent clock skew between client and server, set this value to the current time plus 5 minutes.

iat

No

Integer

The issuance time in Unix epoch seconds. The token cannot be used before this time. Example: 1577682075.

nbf

No

Integer

The effective time in Unix epoch seconds. Defaults to the current time if not specified. The window between effective time and expiration time must not exceed 15 minutes. To prevent clock skew, set this value to the current time minus 5 minutes, or omit it.

auto_create

No

Boolean

Whether to automatically create the user if the user does not exist. Default: false.

For more information about JWT libraries and signing methods, see the JWT official website.

2.2 Exchange the JWT string for an access token

Call the Authorize operation to obtain an access token.

POST /v2/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&client_id=${APP_ID}&assertion=xxxxxxxxxx
Note

Set the request Content-Type to application/x-www-form-urlencoded. Place all request parameters in the request body.

Request parameters

Field

Required

Type

Description

grant_type

Yes

String

The authorization grant type. Set this to the string literal: urn:ietf:params:oauth:grant-type:jwt-bearer

client_id

Yes

String

The application ID.

assertion

Yes

String

The JWT string generated in Step 2.1.

Sample response

{
  "access_token": "eyJh****eQdnUTsEk4",
  "refresh_token": "kL***Lt",
  "expires_in": 7200,
  "token_type": "Bearer"
}

After the application server obtains the access token, return it to the application web client. Include the access token in all subsequent PDS API calls to access user resources.

2.3 Refresh the access token

A JWT-based access token is valid for 2 hours. After it expires, obtain a new one by using either of the following methods:

  • Re-generate: Repeat Steps 2.1 and 2.2 to generate a new access token.

  • Refresh (within 7 days): Call the Authorize operation with the refresh token to obtain a new access token. If more than 7 days have passed since expiration, repeat Steps 2.1 and 2.2 instead.

Call the Authorize operation to refresh the access token:

POST /v2/oauth/token
Content-Type: application/x-www-form-urlencoded

client_id=${APPID}&refresh_token=${access_token}&grant_type=refresh_token&redirect_uri=${REDIRECT_URI}

Field

Required

Type

Description

client_id

Yes

String

The application ID.

refresh_token

Yes

String

The refresh token from the original token response.

grant_type

Yes

String

The authorization grant type. Set this to the string literal: refresh_token

redirect_uri

Yes

String

The callback URL specified when the application was created.

Step 3: Use Basic UI (optional)

If the official Basic UI meets your requirements and you do not need a custom UI, use Basic UI directly.

Method 1: Open Basic UI with window.open

Open the Basic UI with window.open and pass the access token through postMessage.

Sample code:

const endpoint = `https://${domain_id}.apps.aliyunpds.com`
const url = `${endpoint}/accesstoken?origin=${location.origin}`
var win = window.open(url)

window.addEventListener('message', onMessage, false)
async function onMessage(e) {
  if (e.data.code == 'token' && e.data.message == 'ready') {
    var result = await getToken(); // Obtain the access token from the server
    //result = {"access_token": ...}
    win.postMessage({
      code: 'token',
      message: result
    }, endpoint || '*')

    window.removeEventListener('message', onMessage)
  }
}

Method 2: Embed a custom login page in Basic UI

Basic UI embeds a custom login page through an iframe.

In the system configuration, set the URL of the custom login page and the JWT application ID. This allows Basic UI to auto-refresh the token.

image

When a user signs in, the iframe displays the custom login page instead of the default Basic UI login page.

After the user signs in successfully, pass the token to the parent page through postMessage:

image

if(parent!=self){
  let origin = ''
  parent.postMessage({
    code: 'token',
    message: {
       access_token: 'xxxx',
       refresh_token: 'xxxx',
       ...
    }
  }, endpoint || "*")
}

Appendix 1: Complete Node.js implementation

The following sample code demonstrates how to obtain and refresh an access token in a JWT application:

const fs = require('fs')
const JWT = require('jsonwebtoken');
const axios = require('axios')

const DOMAIN_ID = '' // Domain ID
const APP_ID = '' // Application ID
const USER_ID = '' // User UID
const PRIVATE_KEY_PEM = '' // Private key configured in Step 1.3
const PRE = `https://${domain_id}.api.aliyunpds.com`

async function init() {
  try {
    // Replace these variables with your actual values
    var params = {
      domain_id: DOMAIN_ID,
      client_id: APP_ID,
      user_id: USER_ID,
      privateKeyPEM: PRIVATE_KEY_PEM,
    };
    var assertion = signAssertion(params)
    var obj = await getToken(assertion)
    return obj.data
  } catch (e) {
    if (e.response) {
      console.log(e.response.status)
      console.log(e.response.headers)
      console.log(e.response.data)
    } else {
      console.error(e)
    }
  }
}

function signAssertion({ domain_id, client_id, user_id, privateKeyPEM }) {
  var now_sec = parseInt(Date.now()/1000)
  var opt = {
    iss: client_id,
    sub: user_id,
    sub_type: 'user',
    aud: domain_id,
    jti: Math.random().toString(36).substring(2),
    exp: now_sec + 300,
    // iat: current time in seconds
    // nbf: not before
    auto_create: true,
  };
  return JWT.sign(opt, privateKeyPEM, {
    algorithm: 'RS256'
  });
}

async function getToken(assertion) {
  return await axios({
    method: 'post',
    url: PRE + '/v2/oauth/token',
    // Set the Content-Type to application/x-www-form-urlencoded
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    // Place request parameters in the body
    data: params({
      grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
      client_id: APP_ID,
      assertion
    })
  })
}

async function refreshToken(refresh_token) {
  return await axios({
    method: 'post',
    url: PRE + '/v2/oauth/token',
    // Set the Content-Type to application/x-www-form-urlencoded
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    // Place request parameters in the body
    data: params({
      grant_type: 'refresh_token',
      client_id: APP_ID,
      refresh_token,
    })
  })
}

function params(m){
  const params = new URLSearchParams();
  for(var k in m){
     params.append(k, m[k]);
  }
  return params;
}

// Test call
;(async ()=>{
  let result = await init()
  console.log(result) // Returns a token object {access_token:...}. See Appendix 2 for the object structure.
  // After the access token expires
  refreshToken(result.refreshToken) // Returns a new token object {access_token:...}. See Appendix 2 for the object structure.
})();

Appendix 2: Token object structure

Sample data:

{
  "access_token": "eyJhbG.....g7M0p28",
  "refresh_token": "62f1acc.......9b781f3",
  "expires_in": 7200,
  "token_type": "Bearer"
}

For more information about the response parameters, see Obtain an access token.