Zig Requires Chilkat v11.5.0+
Zig
Box: Get a Service Account Token with JWT
See more Box Examples
Use the encrypted private key in a Box application configuration file to sign a short-lived assertion and exchange it for an access token. Configure and authorize a JWT Server app first. The enterprise subject obtains the service-account token.
See the Box API guide for setup and the complete workflow.
Chilkat Zig Downloads
const std = @import("std");
const chilkat = @import("chilkat");
pub fn main(init: std.process.Init) !void {
const alloc = init.arena.allocator();
var success: bool = false;
// Requires Chilkat 11.5.0 or later and a previously unlocked Chilkat bundle.
// See Global Unlock Sample.
// Guide: Box API Guide.
success = false;
const config = try chilkat.JsonObject.init();
defer config.deinit();
success = if (config.loadFile("qa_data/tokens/box_jwt_config.json")) true else |_| false;
if (!success) {
std.debug.print("{s}\n", .{try config.getLastErrorText(alloc)});
return;
}
const key = try chilkat.PrivateKey.init();
defer key.deinit();
success = if (key.loadEncryptedPem(try config.stringOf(alloc, "boxAppSettings.appAuth.privateKey"), try config.stringOf(alloc, "boxAppSettings.appAuth.passphrase"))) true else |_| false;
if (!success) {
std.debug.print("{s}\n", .{try key.getLastErrorText(alloc)});
return;
}
const header = try chilkat.JsonObject.init();
defer header.deinit();
header.updateString("alg", "RS256") catch {};
header.updateString("typ", "JWT") catch {};
header.updateString("kid", try config.stringOf(alloc, "boxAppSettings.appAuth.publicKeyID")) catch {};
const jwt = try chilkat.Jwt.init();
defer jwt.deinit();
const prng = try chilkat.Prng.init();
defer prng.deinit();
const nonce = prng.genRandom(alloc, 32, "hex") catch {
std.debug.print("{s}\n", .{try prng.getLastErrorText(alloc)});
return;
};
const claims = try chilkat.JsonObject.init();
defer claims.deinit();
claims.updateString("iss", try config.stringOf(alloc, "boxAppSettings.clientID")) catch {};
claims.updateString("sub", try config.stringOf(alloc, "enterpriseID")) catch {};
claims.updateString("box_sub_type", "enterprise") catch {};
claims.updateString("aud", "https://api.box.com/oauth2/token") catch {};
claims.updateString("jti", nonce) catch {};
claims.updateInt("exp", jwt.genNumericDate(45)) catch {};
const assertion = jwt.createJwtPk(alloc, try header.emit(alloc), try claims.emit(alloc), key) catch {
std.debug.print("{s}\n", .{try jwt.getLastErrorText(alloc)});
return;
};
const curl = try chilkat.HttpCurl.init();
defer curl.deinit();
curl.setVar("client_id", try config.stringOf(alloc, "boxAppSettings.clientID"));
curl.setVar("client_secret", try config.stringOf(alloc, "boxAppSettings.clientSecret"));
curl.setVar("assertion", assertion);
curl.clearTargetOutput("*");
curl.clearVar("access_token");
curl.addTargetOutput("access_token", "access_token");
success = if (curl.doYourThing("curl -X POST \"https://api.box.com/oauth2/token\" --data-urlencode \"grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer\" --data-urlencode \"client_id={{client_id}}\" --data-urlencode \"client_secret={{client_secret}}\" --data-urlencode \"assertion={{assertion}}\"")) true else |_| false;
if ((!success) or (curl.getStatusCode() != 200)) {
std.debug.print("Box request failed. HTTP status: {d}\n", .{curl.getStatusCode()});
std.debug.print("Failure reason: {d}\n", .{curl.getFailReason()});
return;
}
if (!curl.varDefined("!")) {
std.debug.print("Expected response fields are missing.\n", .{});
return;
}
// Reuse the token in this HttpCurl instance. JWT tokens are renewed by making
// a new assertion/token request, not by using a refresh token.
std.debug.print("JWT access token obtained.\n", .{});
}