This document describes how a custom application that uses JSON Web Token (JWT) can obtain an access token to access Drive and Photo Service (PDS).
JWT applications
A JWT application is a custom application that uses the JSON Web Token (JWT) mechanism for identity authentication.
The server of a JWT application can sign data with a private key to generate a JWT Assertion. This string serves as a credential to access the PDS server, which has been configured with the corresponding public key.

Use cases
-
Your organization has an internal software system with its own account system. You want users to sign in through your internal login page and then use PDS features.
-
Your organization has an independent account system and login portal. You want to combine your existing login portal with PDS to build a cloud storage system that uses your existing accounts.
Workflow overview
-
In the PDS console, create a custom domain and a JWT application.
-
Use the RSA algorithm to generate a public-private key pair. Save the public key on the PDS server and the private key on your JWT application server.
-
Your JWT application server encodes data and signs it with the private key to generate a JWT Assertion, then sends it to the PDS server.
-
The PDS server uses the public key to validate the JWT Assertion. Upon successful validation, it returns an access token to your JWT application server. Your server can then use the access token to call PDS APIs.
Procedure
Step 1: Configure keys
1.1 Create or select a domain
In the Drive and Photo Service console, on the Domain List page, click Create Domain. In the panel that opens, enter a Domain Name (for example, "Drive Demo") and a Description. Set Data Storage Mode to Standard Mode, toggle on the Enable Initial Drive switch, select Custom Size and set the Drive size (for example, 10 GB), and then click OK.
1.2 Create or select an application
Go to the domain details page and, on the Applications tab, create or select an application.
In the Create Application dialog box, for Application Access Method, select Access as Application. For Type, select Access with JWT Authentication. Enter an Application Name (for example, Demo Drive). For Permission Scope, select Custom and select the DRIVE.ALL, SHARE.ALL, FILE.ALL, USER.ALL, STORAGE.ALL, STORAGEFILE.LIST, ACCOUNT.ALL, and BATCH permissions. Click OK.
1.3 Set the public key
After creating or selecting an application, you must set its public key.
On the domain details page, select the Applications tab. In the My Applications section, find the target application and click Set Public Key in the Actions column.
In the dialog box that appears, click the No key pair? Click here to generate one link to generate a new key pair. Paste the generated public key into the Public Key PEM text box.
After you generate the key pair, copy the private key and save it in a secure location. Then, click OK.
Changes to the public key take effect within five minutes.
Step 2: Obtain an access token
2.1 Construct and sign JWT Assertion
On your application server, encode the payload data and sign it with your private key using the specified encryption algorithm to generate a JWT Assertion. The following Node.js code provides an example:
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: now_sec, // Issued At (current Unix time in seconds)
// nbf: '', // Not Before (Unix time in seconds)
auto_create: false,
};
return JWT.sign(opt, privateKeyPEM, {
algorithm: "RS256",
});
}
JWT payload claims
|
Parameter |
Required |
Type |
Description |
|
iss |
Yes |
String |
The app ID. |
|
sub |
Yes |
String |
The user ID or domain ID. The value depends on the |
|
sub_type (extended field) |
Yes |
String |
The account type. Valid values: |
|
aud |
Yes |
String |
The domain ID. |
|
jti |
Yes |
String |
A unique identifier for the JWT, generated by the application. The length must be 16 to 128 characters. We recommend using a UUID. |
|
exp |
Yes |
Integer |
The expiration time of the JWT, as a Unix timestamp in seconds. The time window between the |
|
iat |
No |
Integer |
The issuance time, as a Unix timestamp in seconds. The token cannot be used before this time. Example: |
|
nbf |
No |
Integer |
The "not before" time, as a Unix timestamp in seconds. If not specified, this defaults to the current time. The time window between |
|
auto_create (extended field) |
No |
Boolean |
Specifies whether to automatically create a user if the user does not exist. Default: |
For more information about JWT libraries and signing methods, see the official JWT website.
2.2 Get an access token
Call the Authorize operation to exchange the JWT Assertion for 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
Set the Content-Type header of the request to application/x-www-form-urlencoded. Place the request parameters in the request body.
Request parameters
|
Parameter |
Required |
Type |
Description |
|
grant_type |
Yes |
String |
The grant type. Set this to the string constant |
|
client_id |
Yes |
String |
The app ID. |
|
assertion |
Yes |
String |
The JWT Assertion generated in the previous step. |
Sample response
{
"access_token": "eyJh****eQdnUTsEk4",
"refresh_token": "kL***Lt",
"expires_in": 7200,
"token_type": "Bearer"
}
After your application server receives the access_token, it can return the token to the client-side application. The application can then include the access_token in API calls to access user resources in PDS.
2.3 Refresh the access token
An access_token obtained via the JWT flow is valid for 2 hours. After it expires, you can use the refresh_token to get a new access_token. The refresh_token is valid for 7 days. After it expires, you must repeat steps 2.1 and 2.2 to generate a completely new token. Alternatively, you can repeat steps 2.1 and 2.2 at any time to get a new access_token.
Call the Authorize operation to exchange the refresh_token for a new access_token:
POST /v2/oauth/token
Content-Type: application/x-www-form-urlencoded
client_id=${APP_ID}&refresh_token=${refresh_token}&grant_type=refresh_token&redirect_uri=${REDIRECT_URI}
|
Parameter |
Required |
Type |
Description |
|
client_id |
Yes |
String |
The app ID. |
|
refresh_token |
Yes |
String |
The |
|
grant_type |
Yes |
String |
The grant type. Set this to the string constant |
|
redirect_uri |
Yes |
String |
The callback URL that you specified when creating the application. |
Step 3: Use Basic UI (Optional)
If you do not want to develop your own UI and the official Basic UI meets your needs, you can use it directly.
Method 1: Open in a new window
Use window.open to open the Basic UI and pass the access token using 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 your server.
// result = {"access_token": ...}
win.postMessage({
code: 'token',
message: result
}, endpoint || '*')
window.removeEventListener('message', onMessage)
}
}
Method 2: Embed in custom login page
Embed Basic UI in a custom login page using an iframe.
To allow Basic UI to automatically refresh the token, configure the URL of the custom login page and the app ID of the JWT application in the system configuration.
Go to the Enterprise Settings > Advanced Customization page. Complete the configuration in the Custom Login and Logout section. You can also configure a Custom Logout Page URL. After configuration, logging out will automatically redirect users to the custom logout page and clear the login state.
When a user logs in, the custom login page is opened in an iframe instead of the default login page of the Basic UI.
After a successful login, pass the tokens to the host page using postMessage.

if(parent!=self){
let origin = ''
parent.postMessage({
code: 'token',
message: {
access_token: 'xxxx',
refresh_token: 'xxxx',
...
}
}, endpoint || "*")
}
Appendix 1: Node.js code implementation
The following sample code shows how a JWT application can obtain and refresh an access_token.
const fs = require('fs')
const JWT = require('jsonwebtoken');
const axios = require('axios')
const DOMAIN_ID = '' // Your domain ID
const APP_ID = '' // Your application ID
const USER_ID = '' // The user ID
const PRIVATE_KEY_PEM = '' // The private key configured in Step 1.3
const PRE = `https://${DOMAIN_ID}.api.aliyunpds.com`
async function init() {
try {
// Replace the following 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: now_sec,
// nbf: '',
auto_create: true,
};
return JWT.sign(opt, privateKeyPEM, {
algorithm: 'RS256'
});
}
async function getToken(assertion) {
return await axios({
method: 'post',
url: PRE + '/v2/oauth/token',
// Note: Set the Content-Type header to application/x-www-form-urlencoded.
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
// Note: Place the request parameters in the request 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',
// Note: Set the Content-Type header to application/x-www-form-urlencoded.
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
// Note: Place the request parameters in the request 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 the functions.
;(async ()=>{
let result = await init()
console.log(result) // Returns a token object: {access_token:...}. For the object structure, see Appendix 2.
// After the access_token expires
refreshToken(result.refresh_token) // Returns a new token object: {access_token:...}. For the object structure, see Appendix 2.
})();
Appendix 2: Token object structure
Sample response:
{
"access_token": "eyJhbG.....g7M0p28",
"refresh_token": "62f1acc.......9b781f3",
"expires_in": 7200,
"token_type": "Bearer",
"..." : "..."
}
For more information about the parameters, see Obtain an access token.