Manage Token
Use a Token to generate a Personal Access Token (PAT) or a machine user to connect and perform operations to the Affinidi services on your behalf. Using PAT, you can automate specific tasks within your application and access multiple projects if granted by the user.
How does PAT authentication works
Personal Access Token (PAT) is like a machine user that acts on your behalf to the Affinidi services. You can use the PAT to authenticate to the Affinidi services and automate specific tasks within your application. A Personal Access Token (PAT) lives outside of Projects, meaning PAT can access multiple projects once granted by the user.
PATs use asymmetric keys where you are responsible of creating and maintaining the key pair. Please read about more about how to use Personal Access Tokens (PAT) and create the keys here.
Use IAM (Policy) service of Affinidi to grant access and restrict the actions that PAT can perform on your projects.
flowchart TB subgraph Affinidi CLI user_token["1.1. Developer login to Affinidi"] create_project["1.2. Create a project"] project_access["1.3. Set an active project"] create_token["2.2. Create a token"] add_token_project["2.3. Add token to a project"] set_policies["2.4. Set policies for token"] user_token --> create_project create_project --> project_access user_token --> create_token create_token --> add_token_project project_access --> add_token_project add_token_project --> set_policies end subgraph Application direction TB sign_jwt["3.1. Sign JWT"] delegate_token["3.2. Create a delegate token"] call_project_api["3.3. Call Affinidi services"] sign_jwt --> delegate_token delegate_token --> call_project_api end create_keys["2.1. Create a key pair"] create_keys -. "publicKey PEM" .-> create_token create_keys -. "privateKey" .-> sign_jwt set_policies -. "granted access to" .-> call_project_api
Command References
affinidi token
Use these commands for Personal Access Token (PAT) management
affinidi token create-token
Creates a Personal Access Token (PAT)
USAGE
affinidi token create-token [--json] [--no-color] [--no-input] [-n [value]] [-k [value]] [-f [value]] [-a RS256|RS512|ES256|ES512] [-w] [-p [value]]
FLAGS
-a, --algorithm=[option]
[default: RS256] The specific cryptographic algorithm used with the key [options: RS256|RS512|ES256|ES512]
-f, --public-key-file=[value]
Location of the public key PEM file
-k, --key-id=[value]
Identifier of the key (kid)
-n, --name=[value]
Name of the Personal Access Token, at least 8 chars long
-p, --passphrase=[value]
Passphrase for generation of private public key pair
-w, --with-permissions
Create ready-to-use PAT with auto-generated private public key pair and set its access policies
GLOBAL FLAGS
--json
Format output as json.
--no-color
Disables color in the output. If you have trouble distinguishing colors, consider using this flag.
--no-input
Disables all the interactive prompts
EXAMPLES
affinidi token create-token -n MyNewToken -w -p top-secret
affinidi token create-token --name MyNewToken --with-permissions --passphrase top-secret
affinidi token create-token -n MyNewToken -k MyKeyID -f publicKey.pem
affinidi token create-token --name "My new token" --key-id MyKeyID --public-key-file publicKey.pem --algorithm RS256
affinidi token delete-token
Deletes a Personal Access Token (PAT)
USAGE
affinidi token delete-token [--json] [--no-color] [--no-input] [-i [value]]
FLAGS
-i, --token-id=[value]
ID of the Personal Access Token
GLOBAL FLAGS
--json
Format output as json.
--no-color
Disables color in the output. If you have trouble distinguishing colors, consider using this flag.
--no-input
Disables all the interactive prompts
EXAMPLES
affinidi token delete-token -i [uuid]
affinidi token delete-token --token-id [uuid]
affinidi token get-token
Gets the details of a Personal Access Token (PAT)
USAGE
affinidi token get-token [--json] [--no-color] [--no-input] [-i [value]]
FLAGS
-i, --token-id=[value]
ID of the Personal Access Token
GLOBAL FLAGS
--json
Format output as json.
--no-color
Disables color in the output. If you have trouble distinguishing colors, consider using this flag.
--no-input
Disables all the interactive prompts
EXAMPLES
affinidi token get-token -i [uuid]
affinidi token get-token --token-id [uuid]
affinidi token list-tokens
Lists your Personal Access Tokens (PATs)
USAGE
affinidi token list-tokens [--json] [--no-color] [--no-input]
GLOBAL FLAGS
--json
Format output as json.
--no-color
Disables color in the output. If you have trouble distinguishing colors, consider using this flag.
--no-input
Disables all the interactive prompts
EXAMPLES
affinidi token list-tokens
affinidi token update-token
Updates a Personal Access Token (PAT)
USAGE
affinidi token update-token [--json] [--no-color] [--no-input] [-i [value]] [-n [value]] [-k [value]] [-f [value]] [--algorithm RS256|RS512|ES256|ES512]
FLAGS
-f, --public-key-file=[value]
Location of the public key PEM file
-i, --token-id=[value]
ID of the Personal Access Token
-k, --key-id=[value]
Identifier of the key (kid)
-n, --name=[value]
Name of the Personal Access Token, at least 8 chars long
--algorithm=[option]
[default: RS256] The specific cryptographic algorithm used with the key [options: RS256|RS512|ES256|ES512]
GLOBAL FLAGS
--json
Format output as json.
--no-color
Disables color in the output. If you have trouble distinguishing colors, consider using this flag.
--no-input
Disables all the interactive prompts
EXAMPLES
affinidi token update-token -i [uuid] -n MyNewToken -k MyKeyID -f publicKey.pem
affinidi token update-token --token-id [uuid] --name "My new token" --key-id "My key ID" --public-key-file publicKey.pem --algorithm RS256
Setting up your PAT keys
To create and use your Personal Access Token you will require a key-pair. You can either create it yourself or rely on a cloud provider to securely manage your keys, such as AWS KMS, GCP’s Cloud KMS or Azure Key Vault
Create a Key-Pair
To create a key-pair, open your command prompt (Windows) / command line (Linux/Mac OS) and run the command below using either of the following tools:
Important
Upon executing the command, the tool prompts you to provide a passphrase. It is recommended to set a passphrase for an additional layer of security. Remember your passphrase as it will be required later.Create a Public Key in PEM Format
After creating your key-pair, you must create the public key in Privacy Enhanced Mail (PEM) format. To do this, run the command below using either of the following tools:
The public-key.pem is the public key file in PEM format, which you use as the input to create the token using Affinidi CLI.
Personal Access Token Usage
You can use Personal Access Token (PAT) to automate a specific task on your project. In this scenario, we will use PAT to automate the creation of Login Configuration and automatically rotate client credentials configured on your application for better security.
Before you begin
- Set up Affinidi Vault account. Follow the guide below if you haven’t set it up yet.
- Install the Affinidi CLI. Follow the guide below if you haven’t installed yet.
- Login to the Affinidi CLI.
affinidi start
- Optionally, if you have multiple projects and you want to create the Personal Access Token (PAT) on a specific project, execute the following command:
Find the Project ID for the Project you want to switch:
affinidi project list-projects
Switch to the Project where you want to create the Personal Access Token (PAT):
affinidi project select-project \
--project-id="<PROJECT_ID>"
Create a Personal Access Token
Create a Key-pair by following these steps.
Create a Personal Access Token (PAT) using CLI:
affinidi token create-token --name="App Rotate Client" --key-id="AppRotateClient" --public-key-file="public-key.pem"
- After creating the Personal Access Token (PAT), we must add the PAT to the current active project and create a policy. To do this, execute the following command:
affinidi iam add-principal -i <TOKEN_ID> -t token
- After adding the PAT to the current active project, get the created policy and save it into a file. To do this, execute the following command:
affinidi iam get-policies -i <TOKEN_ID> -t token > policy.json
- Open the policy.json file and update the
action
andresource
with full access by setting*
.
Sample updated policy:
{
"version": "2022-12-15",
"statement": [
{
"principal": [
"ari:iam::d085c5a5-5765-4d8f-b00e-398f0916a161:token/4b14f758-d725-47bc-865a-6e176581edba"
],
"action": [
"*"
],
"resource": [
"*"
],
"effect": "Allow"
}
]
}
Learn more on how to define policy here.
- After updating the policy file, we will update the policy assigned to the Personal Access Token (PAT) we have created. To do this, execute the following command:
affinidi iam update-policies -i <TOKEN_ID> -t token -f policy.json
Automate tasks and delegate token
After creating and granting access to your Personal Access Token (PAT), it’s time to set up your application to delegate tokens and call Affinidi services programmatically.
- To create a delegate token, we will sign the JSON Web Token (JWT) with the private key we generated previously.
function signJWT(privateKey, algorithm, passphrase, keyId, tokenId) {
const issueTimeSeconds = Math.floor(new Date().getTime() / 1000)
const payload = {
iss: tokenId,
sub: tokenId,
aud: 'https://apse1.auth.developer.affinidi.io/auth/oauth2/token',
jti: new Date().toString() + Math.random(),
exp: issueTimeSeconds + 5 * 60,
iat: issueTimeSeconds,
}
const secret = { key: privateKey, passphrase }
const options = { algorithm: algorithm, keyid: keyId }
return jwt.sign(payload, secret, options)
}
- After signing the JWT, we will exchange it with the User Scoped Token. The
User Scoped Token
is used to call the Project APIs and exchange them with theProject Scoped Token
to access the resources within the Project.
async function getUserToken(tokenId, signedJWT) {
const formData = qs.stringify({
grant_type: 'client_credentials',
scope: 'openid',
client_assertion_type:
'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
client_assertion: signedJWT,
client_id: tokenId,
})
const response = await fetch(
'https://apse1.auth.developer.affinidi.io/auth/oauth2/token',
{
method: 'POST',
body: formData,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
},
)
if (response.status !== 200) throw new Error('Could not get user token')
return response.json()
}
- After generating the User Scoped Token, we will use it to generate the Project Scoped Token to access resources within the projects, such as Login Configuration.
async function getProjectToken(projectId, userScopeToken) {
const response = await fetch('https://apse1.api.affinidi.io/iam/v1/sts/create-project-scoped-token',
{
method: 'POST',
body: JSON.stringify({ projectId }),
headers: {
Authorization: `Bearer ${userScopeToken}`,
'Content-Type': 'application/json',
},
},
)
if (response.status !== 200) throw new Error('Could not get project token')
return response.json()
}
Below is the complete snippet of the code to generate access tokens to access Affinidi services.
import jwt from 'jsonwebtoken'
import qs from 'qs'
// Parameters required to sign JWT
const PRIVATE_KEY = process.env.PRIVATE_KEY
const ALGORITHM = process.env.ALGORITHM
const PASSPHRASE = process.env.PASSPHRASE
const KEY_ID = process.env.KEY_ID
// Parameter required to sign JWT and get User Scoped Token
const TOKEN_ID = process.env.TOKEN_ID
// Parameter required to get Project Scoped Token
const PROJECT_ID = process.env.PROJECT_ID
function signJWT(privateKey, algorithm, passphrase, keyId, tokenId) {
const issueTimeSeconds = Math.floor(new Date().getTime() / 1000)
const payload = {
iss: tokenId,
sub: tokenId,
aud: 'https://apse1.auth.developer.affinidi.io/auth/oauth2/token',
jti: new Date().toString() + Math.random(),
exp: issueTimeSeconds + 5 * 60,
iat: issueTimeSeconds,
}
const secret = { key: privateKey, passphrase }
const options = { algorithm: algorithm, keyid: keyId }
return jwt.sign(payload, secret, options)
}
async function getUserToken(tokenId, signedJWT) {
const formData = qs.stringify({
grant_type: 'client_credentials',
scope: 'openid',
client_assertion_type:
'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
client_assertion: signedJWT,
client_id: tokenId,
})
const response = await fetch(
'https://apse1.auth.developer.affinidi.io/auth/oauth2/token',
{
method: 'POST',
body: formData,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
},
)
if (response.status !== 200) throw new Error('Could not get user token')
return response.json()
}
async function getProjectToken(projectId, userScopeToken) {
const response = await fetch('https://apse1.api.affinidi.io/iam/v1/sts/create-project-scoped-token',
{
method: 'POST',
body: JSON.stringify({ projectId }),
headers: {
Authorization: `Bearer ${userScopeToken}`,
'Content-Type': 'application/json',
},
},
)
if (response.status !== 200) throw new Error('Could not get project token')
return response.json()
}
const signedJWT = signJWT(PRIVATE_KEY, ALGORITHM, PASSPHRASE, KEY_ID, TOKEN_ID)
const userScopeToken = (await getUserToken(TOKEN_ID, signedJWT)).access_token
const projectScopeToken = (await getProjectToken(PROJECT_ID, userScopeToken)).accessToken
- After generating the
Project Scoped Token
, we call the Login Configuration API to generate a Login Configuration.
const response = await fetch('https://apse1.api.affinidi.io/vpa/v1/login/configurations',
{
method: 'POST',
body: JSON.stringify({
"name": "Login Config Name",
"redirectUris": [
"http://localhost:3000/callback"
]
}),
headers: {
Authorization: `Bearer ${projectScopeToken}`,
'Content-Type': 'application/json',
},
},
)
if (response.status !== 200) throw new Error('Could not get project token')
const configuration = await response.json()
With Personal Access Token (PAT), you can automate the creation of Login Configuration and automatically rotate the client credentials used by your application regularly to provide better security to your application users.
Glad to hear it! Please tell us how we can improve more.
Sorry to hear that. Please tell us how we can improve.
Thank you for sharing your feedback so we can improve your experience.