Sample code for 30+ languages & platforms
Zig Requires Chilkat v11.5.0+

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

Zig
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", .{});
}