@pedwise/next-firebase-auth-edge
Version:
Next.js 13 Firebase Authentication for Edge and server runtimes. Dedicated for Next 13 server components. Compatible with Next.js middleware.
89 lines (73 loc) • 2.21 kB
text/typescript
import { ServiceAccountCredential } from "../credential";
import { ErrorInfo } from "../error";
import { ALGORITHMS } from "./consts";
import {
arrayBufferToBase64,
pemToArrayBuffer,
stringToArrayBuffer,
} from "./utils";
const ALGORITHM_RS256 = "RS256" as const;
export interface CryptoSigner {
readonly algorithm: "RS256" | "none";
sign(token: string): Promise<string>;
getAccountId(): Promise<string>;
}
export class ServiceAccountSigner implements CryptoSigner {
algorithm = ALGORITHM_RS256;
constructor(private readonly credential: ServiceAccountCredential) {
if (!credential) {
throw new CryptoSignerError({
code: CryptoSignerErrorCode.INVALID_CREDENTIAL,
message:
"INTERNAL ASSERT: Must provide a service account credential to initialize ServiceAccountSigner.",
});
}
}
public async sign(token: string): Promise<string> {
const tokenBuffer = stringToArrayBuffer(token);
const keyData = pemToArrayBuffer(this.credential.privateKey);
const key = await crypto.subtle.importKey(
"pkcs8",
keyData,
ALGORITHMS[ALGORITHM_RS256],
false,
["sign"]
);
const signed = await crypto.subtle.sign(
ALGORITHMS[ALGORITHM_RS256],
key,
tokenBuffer
);
return arrayBufferToBase64(signed);
}
/**
* @inheritDoc
*/
public getAccountId(): Promise<string> {
return Promise.resolve(this.credential.clientEmail);
}
}
export interface ExtendedErrorInfo extends ErrorInfo {
cause?: Error;
}
export class CryptoSignerError extends Error {
constructor(private errorInfo: ExtendedErrorInfo) {
super(errorInfo.message);
Object.setPrototypeOf(this, CryptoSignerError.prototype);
}
public get code(): string {
return this.errorInfo.code;
}
public get message(): string {
return this.errorInfo.message;
}
public get cause(): Error | undefined {
return this.errorInfo.cause;
}
}
export class CryptoSignerErrorCode {
public static INVALID_ARGUMENT = "invalid-argument";
public static INTERNAL_ERROR = "internal-error";
public static INVALID_CREDENTIAL = "invalid-credential";
public static SERVER_ERROR = "server-error";
}