base64url encode/decode
URL friendly data encoding is important when working with data URIs and APIs that work with binary formatted data. base64url is a modification of the base64 encoding that replaces the problematic characters of base64 for URLs. This means swapping ‘+’ for ‘-‘ and ‘/’ for ‘_’, as well as removing the trailing ‘===’ padding.
I found myself needing a concise and dependency free base64url encode/decoder that leverages the native base64 encoding functions. The following is a mix of my own design and elements from numerous alternative solutions from across the internet. There are a number of libraries published to NPM that accomplish this but sometimes adding a dependency adds complexity and risk.
function base64url_encode(buffer: ArrayBuffer): string {
return btoa(Array.from(new Uint8Array(buffer), b => String.fromCharCode(b)).join(''))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
function base64url_decode(value: string): ArrayBuffer {
const m = value.length % 4;
return Uint8Array.from(atob(
value.replace(/-/g, '+')
.replace(/_/g, '/')
.padEnd(value.length + (m === 0 ? 0 : 4 - m), '=')
), c => c.charCodeAt(0)).buffer
}
Things to note about this implementation are:
base64url_decode()
will return an ArrayBuffer that is read only. Usebuffer.slice(0)
to make a writable copy.- The replaceAll and padEnd functions used may require polyfills if you intend to target Internet Explorer.
replaceAll
was chosen in place ofreplace(regex,)
as it should be faster than the overhead of the regex engine.