Sample code for 30+ languages & platforms
Zig

Automatically Refresh Token for 401 Unauthorized

See more Google Calendar Examples

Demonstrates how to automatically refresh an access token (without user interaction) when the token expires and a 401 Unauthorized response is received.

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();

    // This example requires the Chilkat API to have been previously unlocked.
    // See Global Unlock Sample for sample code.

    const token_file_path = "qa_data/tokens/googleCalendar.json";

    // Get our current access token.
    const json_token = try chilkat.JsonObject.init();
    defer json_token.deinit();
    try json_token.loadFile(token_file_path);
    if (!json_token.hasMember("access_token")) {
        std.debug.print("No access token found.\n", .{});
        return;
    }

    const http = try chilkat.Http.init();
    defer http.deinit();
    http.setAuthToken(try json_token.stringOf(alloc, "access_token"));

    var json_response: [:0]const u8 = http.quickGetStr(alloc, "https://www.googleapis.com/calendar/v3/users/me/calendarList") catch "";
    if (!http.getLastMethodSuccess()) {
        if (http.getLastStatus() != 401) {
            std.debug.print("{s}\n", .{try http.getLastErrorText(alloc)});
            std.debug.print("----\n", .{});
            std.debug.print("{s}\n", .{try http.getLastResponseBody(alloc)});
            return;
        }

        // The access token must've expired.
        // Refresh the access token and then retry the request.
        const oauth2 = try chilkat.OAuth2.init();
        defer oauth2.deinit();

        oauth2.setTokenEndpoint("https://www.googleapis.com/oauth2/v4/token");

        // Replace these with actual values.
        oauth2.setClientId("GOOGLE-CLIENT-ID");
        oauth2.setClientSecret("GOOGLE-CLIENT-SECRET");

        // Get the "refresh_token"
        oauth2.setRefreshToken(try json_token.stringOf(alloc, "refresh_token"));

        // Send the HTTP POST to refresh the access token..
        oauth2.refreshAccessToken() catch {
            std.debug.print("{s}\n", .{try oauth2.getLastErrorText(alloc)});
            return;
        };

        // The response contains a new access token, but we must keep
        // our existing refresh token for when we need to refresh again in the future.
        json_token.updateString("access_token", try oauth2.getAccessToken(alloc)) catch {};

        // Save the new JSON access token response to a file.
        const sb_json = try chilkat.StringBuilder.init();
        defer sb_json.deinit();
        json_token.setEmitCompact(false);
        json_token.emitSb(sb_json) catch {};
        sb_json.writeFile(token_file_path, "utf-8", false) catch {};

        std.debug.print("OAuth2 authorization granted!\n", .{});
        std.debug.print("New Access Token = {s}\n", .{try oauth2.getAccessToken(alloc)});

        // re-try the original request.
        http.setAuthToken(try oauth2.getAccessToken(alloc));
        json_response = http.quickGetStr(alloc, "https://www.googleapis.com/calendar/v3/users/me/calendarList") catch {
            std.debug.print("{s}\n", .{try http.getLastErrorText(alloc)});
            return;
        };
    }

    std.debug.print("{s}\n", .{json_response});
    std.debug.print("-----------------------------\n", .{});
}