Getting an IAM token for a service account
There are multiple ways to get an IAM token for the service account:
- Using the CLI (the easiest way).
- Using JSON Web Token. This method is good for automating your API operations.
- Using a virtual machine in Compute Cloud. This method is convenient for running apps on Yandex Cloud virtual machines.
- Using a function in Cloud Functions. This method is good for getting an IAM token from your function code.
The IAM token lifetime does not exceed 12 hours; however, we recommend requesting it more often, such as once per hour.
Get an IAM token using the CLI
Configure the CLI to work on behalf of a service account:
-
If you do not have the Yandex Cloud CLI yet, install and initialize it.
-
The folder specified in the CLI profile is used by default. You can specify a different folder using the
--folder-name
or--folder-id
parameters. -
Get a list of available service accounts in the default folder:
yc iam service-accounts list
Result:
+----------------------+----------+--------+ | ID | NAME | LABELS | +----------------------+----------+--------+ | ajeb9l33h6mu******** | my-robot | | +----------------------+----------+--------+
-
Create an authorized key for your service account and save it to the file:
yc iam key create --output <key_file_path> --service-account-name <service_account_name>
Where:
--output
: Path to the file for saving the authorized key in JSON format. This is a required parameter.--service-account-name
: Service account name.
For example:
yc iam key create --output key.json --service-account-name my-service-account
Result:
id: aje4lue48687******** service_account_id: ajeb9l33h6m******** created_at: "2024-08-01T11:58:52.313177213Z" key_algorithm: RSA_2048
For more information about the
yc iam key create
command, see the CLI reference. -
Create a profile to execute operations on behalf of the service account:
yc config profile create <profile_name>
-
Specify the authorized key of the service account in the profile configuration:
yc config set service-account-key <key_file_path>
Now you can get an IAM token for your service account:
yc iam create-token
Specify the received IAM token when accessing Yandex Cloud resources via the API. Provide the IAM token in the Authorization
header in the following format:
Authorization: Bearer <IAM_token>
Tip
You can use the profile you created to perform CLI operations under your service account.
Get an IAM token using a JWT
To get an IAM token, create a JSON Web Token
Getting started
- Find out the service account ID.
- Create the authorized keys required for generating a JWT. Save the public key ID.
1. To create a JWT
Create a JWT manually by following the instructions or use a library for your programming language.
Tip
On jwt.io
Generate the parts that make up a JWT:
header
: Base64Url-encoded JWT headers.payload
: Base64Url-encoded JWT Claims Set.signature
: Signature generated from parts of the header and payload.
To create a JWT, join all parts using a period as the delimiter:
header.payload.signature
1.1. Generating a header
A service account's JWT header must contain the following fields:
typ
: Token type, the value is alwaysJWT
.alg
: Encryption algorithm. The only supported algorithm is PS256 .kid
: ID of the public key obtained when creating authorized keys. The key must belong to the service account that the IAM token is requested for.
Example:
{
"typ": "JWT",
"alg": "PS256",
"kid": "lfkoe35hsk58********"
}
Save the result as a Base64Url-encoded string.
1.2. Generating a payload
A service account's JWT payload must contain the following fields:
iss
: ID of the service account whose key the JWT is signed with.aud
: Link by which an IAM token will be requested:https://iam.api.cloud.yandex.net/iam/v1/tokens
.iat
: JWT issue time in Unix timestamp format.exp
: JWT expiration time in Unix timestamp format. The expiration time must not exceed the issue time by more than one hour, i.e.,exp - iat ≤ 3600
.
Example:
{
"iss": "ajepg0mjt06s********",
"aud": "https://iam.api.cloud.yandex.net/iam/v1/tokens",
"iat": 1516239022,
"exp": 1516240822
}
Save the result as a Base64Url-encoded string.
1.3. Generating a signature
Create a signature using the private key obtained when creating authorized keys. For the signature, use a string consisting of the header and payload separated by a period (.
):
header.payload
The only supported algorithm is PS256
Save the result as a Base64Url-encoded string.
If you generate a token using jwt.io\n
in the key value must be replaced with line breaks.
Note
This code is provided as an example and uses third-party libraries. Yandex Cloud guarantees the code will only work properly with the specified versions of the libraries. You can also use any libraries of your choice to generate JWT tokens.
Example of creating a JWT using PyJWT
- Verified for Python 3.12.2 and PyJWT 2.8.0.
- The required data is read from the JSON file obtained when creating the authorized key.
Install the PyJWT
and cryptography
modules to use PS256
algorithm:
pip3 install PyJWT
pip3 install cryptography
import time
import jwt
import json
# Reading a private key from a JSON file
with open('<JSON_file_with_keys>', 'r') as f:
obj = f.read()
obj = json.loads(obj)
private_key = obj['private_key']
key_id = obj['id']
service_account_id = obj['service_account_id']
now = int(time.time())
payload = {
'aud': 'https://iam.api.cloud.yandex.net/iam/v1/tokens',
'iss': service_account_id,
'iat': now,
'exp': now + 3600
}
# JWT generation.
encoded_token = jwt.encode(
payload,
private_key,
algorithm='PS256',
headers={'kid': key_id}
)
#Writing a key to a file
with open('jwt_token.txt', 'w') as j:
j.write(encoded_token)
# Printing to console
print(encoded_token)
Note
This code is provided as an example and uses third-party libraries. Yandex Cloud guarantees the code will only work properly with the specified versions of the libraries. You can also use any libraries of your choice to generate JWT tokens.
Example of creating a JWT using the JJWT
- Verified for Java 21 and JJWT 0.12.5.
- The required data is read from the JSON file obtained when creating the authorized key.
package com.mycompany.java.jwt;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;
import java.util.Date;
public class JavaJwt {
@JsonIgnoreProperties(ignoreUnknown = true)
public static class KeyInfo {
public String id;
public String service_account_id;
public String private_key;
}
public static void main(String[] args) throws Exception {
String content = new String(Files.readAllBytes(Paths.get("<JSON_file_with_keys>")));
KeyInfo keyInfo = (new ObjectMapper()).readValue(content, KeyInfo.class);
String privateKeyString = keyInfo.private_key;
String serviceAccountId = keyInfo.service_account_id;
String keyId = keyInfo.id;
PemObject privateKeyPem;
try (PemReader reader = new PemReader(new StringReader(privateKeyString))) {
privateKeyPem = reader.readPemObject();
}
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyPem.getContent()));
Instant now = Instant.now();
// JWT generation.
String encodedToken = Jwts.builder()
.setHeaderParam("kid", keyId)
.setIssuer(serviceAccountId)
.setAudience("https://iam.api.cloud.yandex.net/iam/v1/tokens")
.setIssuedAt(Date.from(now))
.setExpiration(Date.from(now.plusSeconds(3600)))
.signWith(privateKey, SignatureAlgorithm.PS256)
.compact();
System.out.println(encodedToken);
}
}
Note
This code is provided as an example and uses third-party libraries. Yandex Cloud guarantees the code will only work properly with the specified versions of the libraries. You can also use any libraries of your choice to generate JWT tokens.
Example of creating a JWT using jose-jwt
- Verified for jose-jwt 5.0.0.
Net Framework / Net Core:
Verified for Net Framework 4.8.1 and Net Core 3.1.
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using Jose;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var serviceAccountId = "<service_account_ID>";
var keyId = "<public_key_ID>";
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var headers = new Dictionary<string, object>()
{
{ "kid", keyId }
};
var payload = new Dictionary<string, object>()
{
{ "aud", "https://iam.api.cloud.yandex.net/iam/v1/tokens" },
{ "iss", serviceAccountId },
{ "iat", now },
{ "exp", now + 3600 }
};
RsaPrivateCrtKeyParameters privateKeyParams;
using (var pemStream = File.OpenText("<private_key_file>"))
{
privateKeyParams = new PemReader(pemStream).ReadObject() as RsaPrivateCrtKeyParameters;
}
using (var rsa = RSA.Create())
{
rsa.ImportParameters(DotNetUtilities.ToRSAParameters(privateKeyParams));
string encodedToken = Jose.JWT.Encode(payload, rsa, JwsAlgorithm.PS256, headers);
}
}
}
}
.NET 5.0+:
Verified for NET 5.0, NET 6.0, NET 7.0, and NET 8.0.
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using Jose;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var serviceAccountId = "<service_account_ID>";
var keyId = "<public_key_ID>";
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var headers = new Dictionary<string, object>()
{
{ "kid", keyId }
};
var payload = new Dictionary<string, object>()
{
{ "aud", "https://iam.api.cloud.yandex.net/iam/v1/tokens" },
{ "iss", serviceAccountId },
{ "iat", now },
{ "exp", now + 3600 }
};
using (var rsa = RSA.Create())
{
rsa.ImportFromPem(File.ReadAllText("<private_key_file>").ToCharArray());
string encodedToken = Jose.JWT.Encode(payload, rsa, JwsAlgorithm.PS256, headers);
}
}
}
}
Note
This code is provided as an example and uses third-party libraries. Yandex Cloud guarantees the code will only work properly with the specified versions of the libraries. You can also use any libraries of your choice to generate JWT tokens.
Example of creating a JWT using golang-jwt
- Verified for Go1.22.1 and golang-jwt v5.
- The private key is read from the JSON file obtained when creating the authorized key.
Install the required packages:
install jwt v5
go get -u github.com/golang-jwt/jwt/v5
package main
import (
"crypto/rsa"
"encoding/json"
"log"
"os"
"time"
"github.com/golang-jwt/jwt/v5"
)
func main() {
// Getting a token
token := signedToken()
// Saving the token to a file
err := os.WriteFile("jwt_token.txt", []byte(token), 0644)
if err != nil {
log.Fatal(err)
}
// Printing the token to console
fmt.Println("Here is token:")
fmt.Println(token)
}
const (
keyID = "<public_key_ID>"
serviceAccountID = "<service_account_ID>"
keyFile = "<JSON_file_with_keys>"
)
// JWT generation.
func signedToken() string {
claims := jwt.RegisteredClaims{
Issuer: serviceAccountID,
ExpiresAt: jwt.NewNumericDate(time.Now().UTC().Add(1 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now().UTC()),
NotBefore: jwt.NewNumericDate(time.Now().UTC()),
Audience: []string{"https://iam.api.cloud.yandex.net/iam/v1/tokens"},
}
token := jwt.NewWithClaims(jwt.SigningMethodPS256, claims)
token.Header["kid"] = keyID
privateKey := loadPrivateKey()
signed, err := token.SignedString(privateKey)
if err != nil {
panic(err)
}
return signed
}
type keyFileStruct struct {
PrivateKey string `json:"private_key"`
}
func loadPrivateKey() *rsa.PrivateKey {
data, err := os.ReadFile(keyFile)
if err != nil {
panic(err)
}
var keyData keyFileStruct
if err := json.Unmarshal(data, &keyData); err != nil {
panic(err)
}
rsaPrivateKey, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(keyData.PrivateKey))
if err != nil {
panic(err)
}
return rsaPrivateKey
}
Note
This code is provided as an example and uses third-party libraries. Yandex Cloud guarantees the code will only work properly with the specified versions of the libraries. You can also use any libraries of your choice to generate JWT tokens.
Example of creating a JWT using node-jose
- Verified for Node.js v20.12.1 and node-jose 2.2.0.
- The required data is read from the JSON file obtained when creating the authorized key.
var jose = require('node-jose');
var fs = require('fs');
var json = JSON.parse(fs.readFileSync(require.resolve('<JSON_file_with_keys>')));
var key = json.private_key;
var serviceAccountId = json.service_account_id;
var keyId = json.id;
var now = Math.floor(new Date().getTime() / 1000);
var payload = {
aud: "https://iam.api.cloud.yandex.net/iam/v1/tokens",
iss: serviceAccountId,
iat: now,
exp: now + 3600
};
jose.JWK.asKey(key, 'pem', { kid: keyId, alg: 'PS256' })
.then(function (result) {
jose.JWS.createSign({ format: 'compact' }, result)
.update(JSON.stringify(payload))
.final()
.then(function (result) {
console.log(result);
});
});
Note
This code is provided as an example and uses third-party libraries. Yandex Cloud guarantees the code will only work properly with the specified versions of the libraries. You can also use any libraries of your choice to generate JWT tokens.
Example of creating a JWT using PHP JWT Framework
- Verified for PHP v8.3.4 and web-token/jwt-framework v3.3.5.
- Verified for PHP v7.4.33 and web-token/jwt-framework v2.2.11.
- The required data is read from the JSON file obtained when creating the authorized key.
require 'vendor/autoload.php';
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\KeyManagement\JWKFactory;
use Jose\Component\Signature\Algorithm\PS256;
use Jose\Component\Signature\JWSBuilder;
use Jose\Component\Signature\Serializer\CompactSerializer;
// Reading data from a file
$keyData = json_decode(file_get_contents("<JSON_file_with_keys>"), true);
$privateKeyPem = $keyData['private_key'];
$keyId = $keyData['id'];
$serviceAccountId = $keyData['service_account_id'];
// You need to delete header/metadata from the private key
if (strpos($privateKeyPem, "PLEASE DO NOT REMOVE THIS LINE!") === 0) {
$privateKeyPem = substr($privateKeyPem, strpos($privateKeyPem, "\n") + 1);
}
$jwk = JWKFactory::createFromKey(
$privateKeyPem,
null,
[
'alg' => 'PS256',
'use' => 'sig',
'kid' => $keyId,
]
);
$algorithmManager = new AlgorithmManager([new PS256()]);
$jwsBuilder = new JWSBuilder($algorithmManager);
$payload = json_encode([
'iss' => $serviceAccountId,
'aud' => "https://iam.api.cloud.yandex.net/iam/v1/tokens",
'iat' => time(),
'nbf' => time(),
'exp' => time() + 3600,
]);
$jws = $jwsBuilder
->create()
->withPayload($payload)
->addSignature($jwk, ['alg' => 'PS256', 'typ'=>'JWT', 'kid' => $keyId])
->build();
$serializer = new CompactSerializer();
$token = $serializer->serialize($jws, 0);
// Saving the token to a file
file_put_contents('jwt_token.txt', $token);
// Printing the token to console
echo "JWT Token: " . $token . PHP_EOL;
Note
This code is provided as an example and uses third-party libraries. Yandex Cloud guarantees the code will only work properly with the specified versions of the libraries. You can also use any libraries of your choice to generate JWT tokens.
Example of creating a JWT using jwt-cpp
- Verified for C++ 14 and jwt-cpp 0.7.0.
- The required data is read from the JSON file obtained when creating the authorized key.
#include <chrono>
#include <fstream>
#include <iterator>
#include "jwt-cpp/jwt.h"
int main()
{
std::ifstream key_file("<JSON_file_with_keys>");
std::string content((std::istreambuf_iterator<char>(key_file)),
(std::istreambuf_iterator<char>()));
picojson::value v;
std::string err = picojson::parse(v, content);
auto privateKey = v.get("private_key").to_str();
auto serviceAccountId = v.get("service_account_id").to_str();
auto keyId = v.get("id").to_str();
auto now = std::chrono::system_clock::now();
auto expires_at = now + std::chrono::hours(1);
picojson::array audience_array;
audience_array.push_back(picojson::value("https://iam.api.cloud.yandex.net/iam/v1/tokens"));
auto algorithm = jwt::algorithm::ps256(
"",
privateKey);
// JWT generation.
auto encoded_token = jwt::create()
.set_key_id(keyId)
.set_issuer(serviceAccountId)
.set_audience(audience_array)
.set_issued_at(now)
.set_expires_at(expires_at)
.sign(algorithm);
std::cout << encoded_token;
}
Note
This code is provided as an example and uses third-party libraries. Yandex Cloud guarantees the code will only work properly with the specified versions of the libraries. You can also use any libraries of your choice to generate JWT tokens.
Example of creating a JWT using ruby-jwt
- Verified for Ruby 3.2.3 and jwt 2.8.1.
- The required data is read from the JSON file obtained when creating the authorized key.
Install the jwt package:
gem install jwt
require 'jwt'
require 'json'
require 'time'
KEY_FILE = '<JSON_file_with_keys>'
KEY_DATA = JSON.parse(File.read(KEY_FILE))
KEY_ID = KEY_DATA['id']
SERVICE_ACCOUNT_ID = KEY_DATA['service_account_id']
def load_private_key
OpenSSL::PKey::RSA.new(KEY_DATA['private_key'])
rescue IOError, JSON::ParserError, OpenSSL::PKey::RSAError => e
raise "Failed to load or parse private key: #{e.message}"
end
def signed_token
payload = {
iss: SERVICE_ACCOUNT_ID,
exp: Time.now.to_i + 3600,
iat: Time.now.to_i,
nbf: Time.now.to_i,
aud: "https://iam.api.cloud.yandex.net/iam/v1/tokens"
}
header = {
kid: KEY_ID
}
private_key = load_private_key
JWT.encode(payload, private_key, 'PS256', header)
end
# Main execution
begin
token = signed_token
File.write('jwt_token.txt', token)
# Or, alternatively, print the token to the console
# puts "Here is the token:"
# puts token
rescue => e
puts "An error occurred: #{e.message}"
end
2. Exchange the JWT for an IAM token
When exchanging the JWT for an IAM token, make sure the following conditions are met:
- The service account and key specified in the JWT exist (they have not been deleted).
- The key belongs to the service account.
- The signature is valid.
To get an IAM token, use the create REST API method for the IamToken resource or the IamTokenService/CreateForServiceAccount gRPC API call.
Request example with cURL for the create
REST API method:
curl \
--request POST \
--header 'Content-Type: application/json' \
--data '{"jwt": "<JWT_token>"}' \
https://iam.api.cloud.yandex.net/iam/v1/tokens
Where <JWT_token>
is the JWT you got in the previous step.
Example of a JWT exchange for an IAM token:
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
)
func getIAMToken() string {
jot := signedToken()
fmt.Println(jot)
resp, err := http.Post(
"https://iam.api.cloud.yandex.net/iam/v1/tokens",
"application/json",
strings.NewReader(fmt.Sprintf(`{"jwt":"%s"}`, jot)),
)
if err != nil {
panic(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := ioutil.ReadAll(resp.Body)
panic(fmt.Sprintf("%s: %s", resp.Status, body))
}
var data struct {
IAMToken string `json:"iamToken"`
}
err = json.NewDecoder(resp.Body).Decode(&data)
if err != nil {
panic(err)
}
return data.IAMToken
}
Specify the received IAM token when accessing Yandex Cloud resources via the API. Provide the IAM token in the Authorization
header in the following format:
Authorization: Bearer <IAM_token>