New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

firebase-auth-cloudflare-workers

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

firebase-auth-cloudflare-workers - npm Package Compare versions

Comparing version 1.1.0 to 1.2.0

dist/main/api-requests.d.ts

63

dist/main/auth.d.ts

@@ -0,1 +1,2 @@

import type { Credential } from './credential';
import type { EmulatorEnv } from './emulator';

@@ -7,3 +8,6 @@ import type { KeyStorer } from './key-store';

protected readonly idTokenVerifier: FirebaseTokenVerifier;
constructor(projectId: string, keyStore: KeyStorer);
protected readonly sessionCookieVerifier: FirebaseTokenVerifier;
private readonly _authApiClient?;
constructor(projectId: string, keyStore: KeyStorer, credential?: Credential);
private get authApiClient();
/**

@@ -22,2 +26,59 @@ * Verifies a Firebase ID token (JWT). If the token is valid, the promise is

verifyIdToken(idToken: string, env?: EmulatorEnv): Promise<FirebaseIdToken>;
/**
* Creates a new Firebase session cookie with the specified options. The created
* JWT string can be set as a server-side session cookie with a custom cookie
* policy, and be used for session management. The session cookie JWT will have
* the same payload claims as the provided ID token.
*
* See {@link https://firebase.google.com/docs/auth/admin/manage-cookies | Manage Session Cookies}
* for code samples and detailed documentation.
*
* @param idToken - The Firebase ID token to exchange for a session
* cookie.
* @param sessionCookieOptions - The session
* cookie options which includes custom session duration.
* @param env - An optional parameter specifying the environment in which the function is running.
* If the function is running in an emulator environment, this should be set to `EmulatorEnv`.
* If not specified, the function will assume it is running in a production environment.
*
* @returns A promise that resolves on success with the
* created session cookie.
*/
createSessionCookie(idToken: string, sessionCookieOptions: SessionCookieOptions, env?: EmulatorEnv): Promise<string>;
/**
* Verifies a Firebase session cookie. Returns a Promise with the cookie claims.
* Rejects the promise if the cookie could not be verified.
*
* If `checkRevoked` is set to true, first verifies whether the corresponding
* user is disabled: If yes, an `auth/user-disabled` error is thrown. If no,
* verifies if the session corresponding to the session cookie was revoked.
* If the corresponding user's session was invalidated, an
* `auth/session-cookie-revoked` error is thrown. If not specified the check
* is not performed.
*
* See {@link https://firebase.google.com/docs/auth/admin/manage-cookies#verify_session_cookie_and_check_permissions |
* Verify Session Cookies}
* for code samples and detailed documentation
*
* @param sessionCookie - The session cookie to verify.
* @param env - An optional parameter specifying the environment in which the function is running.
* If the function is running in an emulator environment, this should be set to `EmulatorEnv`.
* If not specified, the function will assume it is running in a production environment.
*
* @returns A promise fulfilled with the
* session cookie's decoded claims if the session cookie is valid; otherwise,
* a rejected promise.
*/
verifySessionCookie(sessionCookie: string, env?: EmulatorEnv): Promise<FirebaseIdToken>;
}
/**
* Interface representing the session cookie options needed for the
* {@link BaseAuth.createSessionCookie} method.
*/
export interface SessionCookieOptions {
/**
* The session cookie custom expiration in milliseconds. The minimum allowed is
* 5 minutes and the maxium allowed is 2 weeks.
*/
expiresIn: number;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseAuth = void 0;
const auth_api_requests_1 = require("./auth-api-requests");
const emulator_1 = require("./emulator");
const errors_1 = require("./errors");
const token_verifier_1 = require("./token-verifier");
const validator_1 = require("./validator");
class BaseAuth {
constructor(projectId, keyStore) {
/** @internal */
idTokenVerifier;
sessionCookieVerifier;
_authApiClient;
constructor(projectId, keyStore, credential) {
this.idTokenVerifier = (0, token_verifier_1.createIdTokenVerifier)(projectId, keyStore);
this.sessionCookieVerifier = (0, token_verifier_1.createSessionCookieVerifier)(projectId, keyStore);
if (credential) {
this._authApiClient = new auth_api_requests_1.AuthApiClient(projectId, credential);
}
}
get authApiClient() {
if (this._authApiClient) {
return this._authApiClient;
}
throw new errors_1.FirebaseAppError(errors_1.AppErrorCodes.INVALID_CREDENTIAL, 'Service account must be required in initialization.');
}
/**

@@ -26,3 +43,58 @@ * Verifies a Firebase ID token (JWT). If the token is valid, the promise is

}
/**
* Creates a new Firebase session cookie with the specified options. The created
* JWT string can be set as a server-side session cookie with a custom cookie
* policy, and be used for session management. The session cookie JWT will have
* the same payload claims as the provided ID token.
*
* See {@link https://firebase.google.com/docs/auth/admin/manage-cookies | Manage Session Cookies}
* for code samples and detailed documentation.
*
* @param idToken - The Firebase ID token to exchange for a session
* cookie.
* @param sessionCookieOptions - The session
* cookie options which includes custom session duration.
* @param env - An optional parameter specifying the environment in which the function is running.
* If the function is running in an emulator environment, this should be set to `EmulatorEnv`.
* If not specified, the function will assume it is running in a production environment.
*
* @returns A promise that resolves on success with the
* created session cookie.
*/
async createSessionCookie(idToken, sessionCookieOptions, env) {
// Return rejected promise if expiresIn is not available.
if (!(0, validator_1.isNonNullObject)(sessionCookieOptions) || !(0, validator_1.isNumber)(sessionCookieOptions.expiresIn)) {
throw new errors_1.FirebaseAuthError(errors_1.AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION);
}
return await this.authApiClient.createSessionCookie(idToken, sessionCookieOptions.expiresIn, env);
}
/**
* Verifies a Firebase session cookie. Returns a Promise with the cookie claims.
* Rejects the promise if the cookie could not be verified.
*
* If `checkRevoked` is set to true, first verifies whether the corresponding
* user is disabled: If yes, an `auth/user-disabled` error is thrown. If no,
* verifies if the session corresponding to the session cookie was revoked.
* If the corresponding user's session was invalidated, an
* `auth/session-cookie-revoked` error is thrown. If not specified the check
* is not performed.
*
* See {@link https://firebase.google.com/docs/auth/admin/manage-cookies#verify_session_cookie_and_check_permissions |
* Verify Session Cookies}
* for code samples and detailed documentation
*
* @param sessionCookie - The session cookie to verify.
* @param env - An optional parameter specifying the environment in which the function is running.
* If the function is running in an emulator environment, this should be set to `EmulatorEnv`.
* If not specified, the function will assume it is running in a production environment.
*
* @returns A promise fulfilled with the
* session cookie's decoded claims if the session cookie is valid; otherwise,
* a rejected promise.
*/
verifySessionCookie(sessionCookie, env) {
const isEmulator = (0, emulator_1.useEmulator)(env);
return this.sessionCookieVerifier.verifyJWT(sessionCookie, isEmulator);
}
}
exports.BaseAuth = BaseAuth;
export declare const decodeBase64Url: (str: string) => Uint8Array;
export declare const encodeBase64Url: (buf: ArrayBufferLike) => string;
export declare const encodeBase64: (buf: ArrayBufferLike) => string;
export declare const decodeBase64: (str: string) => Uint8Array;
export declare const encodeObjectBase64Url: (obj: any) => string;

9

dist/main/base64.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeBase64 = exports.encodeBase64Url = exports.decodeBase64Url = void 0;
exports.encodeObjectBase64Url = exports.decodeBase64 = exports.encodeBase64 = exports.encodeBase64Url = exports.decodeBase64Url = void 0;
const utf8_1 = require("./utf8");
const decodeBase64Url = (str) => {
return decodeBase64(str.replace(/_|-/g, m => ({ _: '/', '-': '+' })[m] ?? m));
return (0, exports.decodeBase64)(str.replace(/_|-/g, m => ({ _: '/', '-': '+' })[m] ?? m));
};

@@ -28,1 +29,5 @@ exports.decodeBase64Url = decodeBase64Url;

};
exports.decodeBase64 = decodeBase64;
const jsonUTF8Stringify = (obj) => utf8_1.utf8Encoder.encode(JSON.stringify(obj));
const encodeObjectBase64Url = (obj) => (0, exports.encodeBase64Url)(jsonUTF8Stringify(obj));
exports.encodeObjectBase64Url = encodeObjectBase64Url;

@@ -30,2 +30,6 @@ /**

static INVALID_CREDENTIAL: string;
static INTERNAL_ERROR: string;
static NETWORK_ERROR: string;
static NETWORK_TIMEOUT: string;
static UNABLE_TO_PARSE_RESPONSE: string;
}

@@ -48,2 +52,6 @@ /**

};
static INVALID_ID_TOKEN: {
code: string;
message: string;
};
static ID_TOKEN_REVOKED: {

@@ -65,2 +73,10 @@ code: string;

};
static SESSION_COOKIE_EXPIRED: {
code: string;
message: string;
};
static INVALID_SESSION_COOKIE_DURATION: {
code: string;
message: string;
};
}

@@ -158,1 +174,11 @@ /**

}
/**
* Firebase App error code structure. This extends PrefixedFirebaseError.
*
* @param code - The error code.
* @param message - The error message.
* @constructor
*/
export declare class FirebaseAppError extends PrefixedFirebaseError {
constructor(code: string, message: string);
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FirebaseAuthError = exports.PrefixedFirebaseError = exports.FirebaseError = exports.AuthClientErrorCode = exports.AppErrorCodes = exports.JwtErrorCode = exports.JwtError = void 0;
exports.FirebaseAppError = exports.FirebaseAuthError = exports.PrefixedFirebaseError = exports.FirebaseError = exports.AuthClientErrorCode = exports.AppErrorCodes = exports.JwtErrorCode = exports.JwtError = void 0;
/**

@@ -12,2 +12,4 @@ * Jwt error code structure.

class JwtError extends Error {
code;
message;
constructor(code, message) {

@@ -38,5 +40,9 @@ super(message);

class AppErrorCodes {
static INVALID_CREDENTIAL = 'invalid-credential';
static INTERNAL_ERROR = 'internal-error';
static NETWORK_ERROR = 'network-error';
static NETWORK_TIMEOUT = 'network-timeout';
static UNABLE_TO_PARSE_RESPONSE = 'unable-to-parse-response';
}
exports.AppErrorCodes = AppErrorCodes;
AppErrorCodes.INVALID_CREDENTIAL = 'invalid-credential';
/**

@@ -46,32 +52,44 @@ * Auth client error codes and their default messages.

class AuthClientErrorCode {
static INVALID_ARGUMENT = {
code: 'argument-error',
message: 'Invalid argument provided.',
};
static INVALID_CREDENTIAL = {
code: 'invalid-credential',
message: 'Invalid credential object provided.',
};
static ID_TOKEN_EXPIRED = {
code: 'id-token-expired',
message: 'The provided Firebase ID token is expired.',
};
static INVALID_ID_TOKEN = {
code: 'invalid-id-token',
message: 'The provided ID token is not a valid Firebase ID token.',
};
static ID_TOKEN_REVOKED = {
code: 'id-token-revoked',
message: 'The Firebase ID token has been revoked.',
};
static INTERNAL_ERROR = {
code: 'internal-error',
message: 'An internal error has occurred.',
};
static USER_NOT_FOUND = {
code: 'user-not-found',
message: 'There is no user record corresponding to the provided identifier.',
};
static USER_DISABLED = {
code: 'user-disabled',
message: 'The user record is disabled.',
};
static SESSION_COOKIE_EXPIRED = {
code: 'session-cookie-expired',
message: 'The Firebase session cookie is expired.',
};
static INVALID_SESSION_COOKIE_DURATION = {
code: 'invalid-session-cookie-duration',
message: 'The session cookie duration must be a valid number in milliseconds ' + 'between 5 minutes and 2 weeks.',
};
}
exports.AuthClientErrorCode = AuthClientErrorCode;
AuthClientErrorCode.INVALID_ARGUMENT = {
code: 'argument-error',
message: 'Invalid argument provided.',
};
AuthClientErrorCode.INVALID_CREDENTIAL = {
code: 'invalid-credential',
message: 'Invalid credential object provided.',
};
AuthClientErrorCode.ID_TOKEN_EXPIRED = {
code: 'id-token-expired',
message: 'The provided Firebase ID token is expired.',
};
AuthClientErrorCode.ID_TOKEN_REVOKED = {
code: 'id-token-revoked',
message: 'The Firebase ID token has been revoked.',
};
AuthClientErrorCode.INTERNAL_ERROR = {
code: 'internal-error',
message: 'An internal error has occurred.',
};
AuthClientErrorCode.USER_NOT_FOUND = {
code: 'user-not-found',
message: 'There is no user record corresponding to the provided identifier.',
};
AuthClientErrorCode.USER_DISABLED = {
code: 'user-disabled',
message: 'The user record is disabled.',
};
/**

@@ -84,2 +102,3 @@ * Firebase error code structure. This extends Error.

class FirebaseError extends Error {
errorInfo;
constructor(errorInfo) {

@@ -120,2 +139,3 @@ super(errorInfo.message);

class PrefixedFirebaseError extends FirebaseError {
codePrefix;
constructor(codePrefix, code, message) {

@@ -165,1 +185,19 @@ super({

exports.FirebaseAuthError = FirebaseAuthError;
/**
* Firebase App error code structure. This extends PrefixedFirebaseError.
*
* @param code - The error code.
* @param message - The error message.
* @constructor
*/
class FirebaseAppError extends PrefixedFirebaseError {
constructor(code, message) {
super('app', code, message);
/* tslint:disable:max-line-length */
// Set the prototype explicitly. See the following link for more details:
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
/* tslint:enable:max-line-length */
this.__proto__ = FirebaseAppError.prototype;
}
}
exports.FirebaseAppError = FirebaseAppError;
/// <reference types="@cloudflare/workers-types" />
import { BaseAuth } from './auth';
import type { Credential } from './credential';
import type { KeyStorer } from './key-store';
import { WorkersKVStore } from './key-store';
export { type Credential, ServiceAccountCredential } from './credential';
export { emulatorHost, useEmulator } from './emulator';

@@ -12,3 +14,3 @@ export type { KeyStorer };

private constructor();
static getOrInitialize(projectId: string, keyStore: KeyStorer): Auth;
static getOrInitialize(projectId: string, keyStore: KeyStorer, credential?: Credential): Auth;
}

@@ -15,0 +17,0 @@ export declare class WorkersKVStoreSingle extends WorkersKVStore {

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WorkersKVStoreSingle = exports.Auth = exports.useEmulator = exports.emulatorHost = void 0;
exports.WorkersKVStoreSingle = exports.Auth = exports.useEmulator = exports.emulatorHost = exports.ServiceAccountCredential = void 0;
const auth_1 = require("./auth");
const key_store_1 = require("./key-store");
var credential_1 = require("./credential");
Object.defineProperty(exports, "ServiceAccountCredential", { enumerable: true, get: function () { return credential_1.ServiceAccountCredential; } });
var emulator_1 = require("./emulator");

@@ -10,8 +12,9 @@ Object.defineProperty(exports, "emulatorHost", { enumerable: true, get: function () { return emulator_1.emulatorHost; } });

class Auth extends auth_1.BaseAuth {
constructor(projectId, keyStore) {
super(projectId, keyStore);
static instance;
constructor(projectId, keyStore, credential) {
super(projectId, keyStore, credential);
}
static getOrInitialize(projectId, keyStore) {
static getOrInitialize(projectId, keyStore, credential) {
if (!Auth.instance) {
Auth.instance = new Auth(projectId, keyStore);
Auth.instance = new Auth(projectId, keyStore, credential);
}

@@ -23,2 +26,3 @@ return Auth.instance;

class WorkersKVStoreSingle extends key_store_1.WorkersKVStore {
static instance;
constructor(cacheKey, cfKVNamespace) {

@@ -25,0 +29,0 @@ super(cacheKey, cfKVNamespace);

@@ -6,2 +6,6 @@ import type { JsonWebKeyWithKid } from './jwt-decoder';

}
interface JWKMetadata {
keys: Array<JsonWebKeyWithKid>;
}
export declare const isJWKMetadata: (value: any) => value is JWKMetadata;
/**

@@ -31,1 +35,2 @@ * Class to fetch public keys from a client certificates URL.

}
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HTTPFetcher = exports.parseMaxAge = exports.UrlKeyFetcher = void 0;
exports.HTTPFetcher = exports.parseMaxAge = exports.UrlKeyFetcher = exports.isJWKMetadata = void 0;
const validator_1 = require("./validator");
const isJWKMetadata = (value) => (0, validator_1.isNonNullObject)(value) && !!value.keys && (0, validator_1.isArray)(value.keys);
const isJWKMetadata = (value) => {
if (!(0, validator_1.isNonNullObject)(value) || !value.keys) {
return false;
}
const keys = value.keys;
if (!Array.isArray(keys)) {
return false;
}
const filtered = keys.filter((key) => (0, validator_1.isObject)(key) && !!key.kid && typeof key.kid === 'string');
return keys.length === filtered.length;
};
exports.isJWKMetadata = isJWKMetadata;
/**

@@ -10,2 +21,4 @@ * Class to fetch public keys from a client certificates URL.

class UrlKeyFetcher {
fetcher;
keyStorer;
constructor(fetcher, keyStorer) {

@@ -35,3 +48,3 @@ this.fetcher = fetcher;

const publicKeys = await resp.json();
if (!isJWKMetadata(publicKeys)) {
if (!(0, exports.isJWKMetadata)(publicKeys)) {
throw new Error(`The public keys are not an object or null: "${publicKeys}`);

@@ -67,2 +80,3 @@ }

class HTTPFetcher {
clientCertUrl;
constructor(clientCertUrl) {

@@ -69,0 +83,0 @@ this.clientCertUrl = clientCertUrl;

@@ -19,2 +19,3 @@ "use strict";

class PublicKeySignatureVerifier {
keyFetcher;
constructor(keyFetcher) {

@@ -21,0 +22,0 @@ this.keyFetcher = keyFetcher;

@@ -9,2 +9,4 @@ "use strict";

class RS256Token {
rawToken;
decodedToken;
constructor(rawToken, decodedToken) {

@@ -11,0 +13,0 @@ this.rawToken = rawToken;

@@ -8,2 +8,4 @@ "use strict";

class WorkersKVStore {
cacheKey;
cfKVNamespace;
constructor(cacheKey, cfKVNamespace) {

@@ -10,0 +12,0 @@ this.cacheKey = cacheKey;

@@ -205,2 +205,21 @@ import type { ErrorInfo } from './errors';

*/
export declare function createFirebaseTokenVerifier(signatureVerifier: SignatureVerifier, projectID: string): FirebaseTokenVerifier;
export declare function baseCreateIdTokenVerifier(signatureVerifier: SignatureVerifier, projectID: string): FirebaseTokenVerifier;
/**
* User facing token information related to the Firebase session cookie.
*
* @internal
*/
export declare const SESSION_COOKIE_INFO: FirebaseTokenInfo;
/**
* Creates a new FirebaseTokenVerifier to verify Firebase session cookies.
*
* @internal
* @param app - Firebase app instance.
* @returns FirebaseTokenVerifier
*/
export declare function createSessionCookieVerifier(projectID: string, keyStorer: KeyStorer): FirebaseTokenVerifier;
/**
* @internal
* @returns FirebaseTokenVerifier
*/
export declare function baseCreateSessionCookieVerifier(signatureVerifier: SignatureVerifier, projectID: string): FirebaseTokenVerifier;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFirebaseTokenVerifier = exports.createIdTokenVerifier = exports.ID_TOKEN_INFO = exports.FirebaseTokenVerifier = exports.FIREBASE_AUDIENCE = void 0;
exports.baseCreateSessionCookieVerifier = exports.createSessionCookieVerifier = exports.SESSION_COOKIE_INFO = exports.baseCreateIdTokenVerifier = exports.createIdTokenVerifier = exports.ID_TOKEN_INFO = exports.FirebaseTokenVerifier = exports.FIREBASE_AUDIENCE = void 0;
const errors_1 = require("./errors");

@@ -18,2 +18,7 @@ const jws_verifier_1 = require("./jws-verifier");

class FirebaseTokenVerifier {
signatureVerifier;
projectId;
issuer;
tokenInfo;
shortNameArticle;
constructor(signatureVerifier, projectId, issuer, tokenInfo) {

@@ -182,3 +187,3 @@ this.signatureVerifier = signatureVerifier;

const signatureVerifier = jws_verifier_1.PublicKeySignatureVerifier.withCertificateUrl(CLIENT_JWK_URL, keyStorer);
return createFirebaseTokenVerifier(signatureVerifier, projectID);
return baseCreateIdTokenVerifier(signatureVerifier, projectID);
}

@@ -190,5 +195,39 @@ exports.createIdTokenVerifier = createIdTokenVerifier;

*/
function createFirebaseTokenVerifier(signatureVerifier, projectID) {
function baseCreateIdTokenVerifier(signatureVerifier, projectID) {
return new FirebaseTokenVerifier(signatureVerifier, projectID, 'https://securetoken.google.com/', exports.ID_TOKEN_INFO);
}
exports.createFirebaseTokenVerifier = createFirebaseTokenVerifier;
exports.baseCreateIdTokenVerifier = baseCreateIdTokenVerifier;
// URL containing the public keys for Firebase session cookies.
const SESSION_COOKIE_CERT_URL = 'https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys';
/**
* User facing token information related to the Firebase session cookie.
*
* @internal
*/
exports.SESSION_COOKIE_INFO = {
url: 'https://firebase.google.com/docs/auth/admin/manage-cookies',
verifyApiName: 'verifySessionCookie()',
jwtName: 'Firebase session cookie',
shortName: 'session cookie',
expiredErrorCode: errors_1.AuthClientErrorCode.SESSION_COOKIE_EXPIRED,
};
/**
* Creates a new FirebaseTokenVerifier to verify Firebase session cookies.
*
* @internal
* @param app - Firebase app instance.
* @returns FirebaseTokenVerifier
*/
function createSessionCookieVerifier(projectID, keyStorer) {
const signatureVerifier = jws_verifier_1.PublicKeySignatureVerifier.withCertificateUrl(SESSION_COOKIE_CERT_URL, keyStorer);
return baseCreateSessionCookieVerifier(signatureVerifier, projectID);
}
exports.createSessionCookieVerifier = createSessionCookieVerifier;
/**
* @internal
* @returns FirebaseTokenVerifier
*/
function baseCreateSessionCookieVerifier(signatureVerifier, projectID) {
return new FirebaseTokenVerifier(signatureVerifier, projectID, 'https://session.firebase.google.com/', exports.SESSION_COOKIE_INFO);
}
exports.baseCreateSessionCookieVerifier = baseCreateSessionCookieVerifier;

@@ -30,9 +30,2 @@ /**

/**
* Validates that a value is an array.
*
* @param value - The value to validate.
* @returns Whether the value is an array or not.
*/
export declare function isArray<T>(value: any): value is T[];
/**
*

@@ -39,0 +32,0 @@ /**

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isNonNullObject = exports.isObject = exports.isArray = exports.isNonEmptyString = exports.isString = exports.isNumber = exports.isURL = void 0;
exports.isNonNullObject = exports.isObject = exports.isNonEmptyString = exports.isString = exports.isNumber = exports.isURL = void 0;
/**

@@ -78,12 +78,2 @@ * Validates that a string is a valid web URL.

/**
* Validates that a value is an array.
*
* @param value - The value to validate.
* @returns Whether the value is an array or not.
*/
function isArray(value) {
return Array.isArray(value);
}
exports.isArray = isArray;
/**
*

@@ -97,3 +87,3 @@ /**

function isObject(value) {
return typeof value === 'object' && !isArray(value);
return typeof value === 'object' && !Array.isArray(value);
}

@@ -100,0 +90,0 @@ exports.isObject = isObject;

@@ -0,9 +1,24 @@

import { AuthApiClient } from './auth-api-requests';
import { useEmulator } from './emulator';
import { createIdTokenVerifier } from './token-verifier';
import { AppErrorCodes, AuthClientErrorCode, FirebaseAppError, FirebaseAuthError } from './errors';
import { createIdTokenVerifier, createSessionCookieVerifier } from './token-verifier';
import { isNonNullObject, isNumber } from './validator';
export class BaseAuth {
/** @internal */
idTokenVerifier;
constructor(projectId, keyStore) {
sessionCookieVerifier;
_authApiClient;
constructor(projectId, keyStore, credential) {
this.idTokenVerifier = createIdTokenVerifier(projectId, keyStore);
this.sessionCookieVerifier = createSessionCookieVerifier(projectId, keyStore);
if (credential) {
this._authApiClient = new AuthApiClient(projectId, credential);
}
}
get authApiClient() {
if (this._authApiClient) {
return this._authApiClient;
}
throw new FirebaseAppError(AppErrorCodes.INVALID_CREDENTIAL, 'Service account must be required in initialization.');
}
/**

@@ -25,2 +40,57 @@ * Verifies a Firebase ID token (JWT). If the token is valid, the promise is

}
/**
* Creates a new Firebase session cookie with the specified options. The created
* JWT string can be set as a server-side session cookie with a custom cookie
* policy, and be used for session management. The session cookie JWT will have
* the same payload claims as the provided ID token.
*
* See {@link https://firebase.google.com/docs/auth/admin/manage-cookies | Manage Session Cookies}
* for code samples and detailed documentation.
*
* @param idToken - The Firebase ID token to exchange for a session
* cookie.
* @param sessionCookieOptions - The session
* cookie options which includes custom session duration.
* @param env - An optional parameter specifying the environment in which the function is running.
* If the function is running in an emulator environment, this should be set to `EmulatorEnv`.
* If not specified, the function will assume it is running in a production environment.
*
* @returns A promise that resolves on success with the
* created session cookie.
*/
async createSessionCookie(idToken, sessionCookieOptions, env) {
// Return rejected promise if expiresIn is not available.
if (!isNonNullObject(sessionCookieOptions) || !isNumber(sessionCookieOptions.expiresIn)) {
throw new FirebaseAuthError(AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION);
}
return await this.authApiClient.createSessionCookie(idToken, sessionCookieOptions.expiresIn, env);
}
/**
* Verifies a Firebase session cookie. Returns a Promise with the cookie claims.
* Rejects the promise if the cookie could not be verified.
*
* If `checkRevoked` is set to true, first verifies whether the corresponding
* user is disabled: If yes, an `auth/user-disabled` error is thrown. If no,
* verifies if the session corresponding to the session cookie was revoked.
* If the corresponding user's session was invalidated, an
* `auth/session-cookie-revoked` error is thrown. If not specified the check
* is not performed.
*
* See {@link https://firebase.google.com/docs/auth/admin/manage-cookies#verify_session_cookie_and_check_permissions |
* Verify Session Cookies}
* for code samples and detailed documentation
*
* @param sessionCookie - The session cookie to verify.
* @param env - An optional parameter specifying the environment in which the function is running.
* If the function is running in an emulator environment, this should be set to `EmulatorEnv`.
* If not specified, the function will assume it is running in a production environment.
*
* @returns A promise fulfilled with the
* session cookie's decoded claims if the session cookie is valid; otherwise,
* a rejected promise.
*/
verifySessionCookie(sessionCookie, env) {
const isEmulator = useEmulator(env);
return this.sessionCookieVerifier.verifyJWT(sessionCookie, isEmulator);
}
}

@@ -0,1 +1,2 @@

import { utf8Encoder } from './utf8';
export const decodeBase64Url = (str) => {

@@ -12,3 +13,3 @@ return decodeBase64(str.replace(/_|-/g, m => ({ _: '/', '-': '+' })[m] ?? m));

// atob does not support utf-8 characters. So we need a little bit hack.
const decodeBase64 = (str) => {
export const decodeBase64 = (str) => {
const binary = atob(str);

@@ -23,1 +24,3 @@ const bytes = new Uint8Array(new ArrayBuffer(binary.length));

};
const jsonUTF8Stringify = (obj) => utf8Encoder.encode(JSON.stringify(obj));
export const encodeObjectBase64Url = (obj) => encodeBase64Url(jsonUTF8Stringify(obj));

@@ -36,2 +36,6 @@ /**

static INVALID_CREDENTIAL = 'invalid-credential';
static INTERNAL_ERROR = 'internal-error';
static NETWORK_ERROR = 'network-error';
static NETWORK_TIMEOUT = 'network-timeout';
static UNABLE_TO_PARSE_RESPONSE = 'unable-to-parse-response';
}

@@ -54,2 +58,6 @@ /**

};
static INVALID_ID_TOKEN = {
code: 'invalid-id-token',
message: 'The provided ID token is not a valid Firebase ID token.',
};
static ID_TOKEN_REVOKED = {

@@ -71,2 +79,10 @@ code: 'id-token-revoked',

};
static SESSION_COOKIE_EXPIRED = {
code: 'session-cookie-expired',
message: 'The Firebase session cookie is expired.',
};
static INVALID_SESSION_COOKIE_DURATION = {
code: 'invalid-session-cookie-duration',
message: 'The session cookie duration must be a valid number in milliseconds ' + 'between 5 minutes and 2 weeks.',
};
}

@@ -158,1 +174,18 @@ /**

}
/**
* Firebase App error code structure. This extends PrefixedFirebaseError.
*
* @param code - The error code.
* @param message - The error message.
* @constructor
*/
export class FirebaseAppError extends PrefixedFirebaseError {
constructor(code, message) {
super('app', code, message);
/* tslint:disable:max-line-length */
// Set the prototype explicitly. See the following link for more details:
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
/* tslint:enable:max-line-length */
this.__proto__ = FirebaseAppError.prototype;
}
}
import { BaseAuth } from './auth';
import { WorkersKVStore } from './key-store';
export { ServiceAccountCredential } from './credential';
export { emulatorHost, useEmulator } from './emulator';
export class Auth extends BaseAuth {
static instance;
constructor(projectId, keyStore) {
super(projectId, keyStore);
constructor(projectId, keyStore, credential) {
super(projectId, keyStore, credential);
}
static getOrInitialize(projectId, keyStore) {
static getOrInitialize(projectId, keyStore, credential) {
if (!Auth.instance) {
Auth.instance = new Auth(projectId, keyStore);
Auth.instance = new Auth(projectId, keyStore, credential);
}

@@ -13,0 +14,0 @@ return Auth.instance;

@@ -1,3 +0,13 @@

import { isArray, isNonNullObject, isURL } from './validator';
const isJWKMetadata = (value) => isNonNullObject(value) && !!value.keys && isArray(value.keys);
import { isNonNullObject, isObject, isURL } from './validator';
export const isJWKMetadata = (value) => {
if (!isNonNullObject(value) || !value.keys) {
return false;
}
const keys = value.keys;
if (!Array.isArray(keys)) {
return false;
}
const filtered = keys.filter((key) => isObject(key) && !!key.kid && typeof key.kid === 'string');
return keys.length === filtered.length;
};
/**

@@ -4,0 +14,0 @@ * Class to fetch public keys from a client certificates URL.

@@ -182,3 +182,3 @@ import { AuthClientErrorCode, FirebaseAuthError, JwtError, JwtErrorCode } from './errors';

const signatureVerifier = PublicKeySignatureVerifier.withCertificateUrl(CLIENT_JWK_URL, keyStorer);
return createFirebaseTokenVerifier(signatureVerifier, projectID);
return baseCreateIdTokenVerifier(signatureVerifier, projectID);
}

@@ -189,4 +189,36 @@ /**

*/
export function createFirebaseTokenVerifier(signatureVerifier, projectID) {
export function baseCreateIdTokenVerifier(signatureVerifier, projectID) {
return new FirebaseTokenVerifier(signatureVerifier, projectID, 'https://securetoken.google.com/', ID_TOKEN_INFO);
}
// URL containing the public keys for Firebase session cookies.
const SESSION_COOKIE_CERT_URL = 'https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys';
/**
* User facing token information related to the Firebase session cookie.
*
* @internal
*/
export const SESSION_COOKIE_INFO = {
url: 'https://firebase.google.com/docs/auth/admin/manage-cookies',
verifyApiName: 'verifySessionCookie()',
jwtName: 'Firebase session cookie',
shortName: 'session cookie',
expiredErrorCode: AuthClientErrorCode.SESSION_COOKIE_EXPIRED,
};
/**
* Creates a new FirebaseTokenVerifier to verify Firebase session cookies.
*
* @internal
* @param app - Firebase app instance.
* @returns FirebaseTokenVerifier
*/
export function createSessionCookieVerifier(projectID, keyStorer) {
const signatureVerifier = PublicKeySignatureVerifier.withCertificateUrl(SESSION_COOKIE_CERT_URL, keyStorer);
return baseCreateSessionCookieVerifier(signatureVerifier, projectID);
}
/**
* @internal
* @returns FirebaseTokenVerifier
*/
export function baseCreateSessionCookieVerifier(signatureVerifier, projectID) {
return new FirebaseTokenVerifier(signatureVerifier, projectID, 'https://session.firebase.google.com/', SESSION_COOKIE_INFO);
}

@@ -71,11 +71,2 @@ /**

/**
* Validates that a value is an array.
*
* @param value - The value to validate.
* @returns Whether the value is an array or not.
*/
export function isArray(value) {
return Array.isArray(value);
}
/**
*

@@ -89,3 +80,3 @@ /**

export function isObject(value) {
return typeof value === 'object' && !isArray(value);
return typeof value === 'object' && !Array.isArray(value);
}

@@ -92,0 +83,0 @@ /**

{
"name": "firebase-auth-cloudflare-workers",
"version": "1.1.0",
"version": "1.2.0",
"description": "Zero-dependencies firebase auth library for Cloudflare Workers.",

@@ -15,33 +15,21 @@ "author": "codehex",

],
"scripts": {
"test": "vitest run",
"build": "run-p build:*",
"build:main": "tsc -p tsconfig.main.json",
"build:module": "tsc -p tsconfig.module.json",
"start-firebase-emulator": "firebase emulators:start --project example-project12345",
"start-example": "wrangler dev example/index.ts --config=example/wrangler.toml --local=true",
"prettier": "prettier --write --list-different \"**/*.ts\"",
"prettier:check": "prettier --check \"**/*.ts\"",
"lint": "eslint --ext .ts .",
"lint-fix": "eslint --fix --ext .ts .",
"prepublish": "run-p build:*"
},
"dependencies": {},
"devDependencies": {
"@cloudflare/workers-types": "^4.20231025.0",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"eslint": "^8.53.0",
"eslint-config-prettier": "^9.0.0",
"@cloudflare/workers-types": "^4.20240208.0",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-define-config": "^1.24.1",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.29.0",
"firebase-tools": "^12.8.1",
"miniflare": "^3.20231025.1",
"eslint-plugin-import": "^2.29.1",
"firebase-tools": "^13.3.0",
"hono": "^4.0.4",
"miniflare": "^3.20240129.3",
"npm-run-all": "^4.1.5",
"prettier": "^3.0.3",
"typescript": "^5.2.2",
"vitest": "^0.34.6",
"wrangler": "^3.15.0"
"prettier": "^3.2.5",
"typescript": "^5.3.3",
"undici": "^6.6.2",
"vitest": "^1.3.0",
"wrangler": "^3.28.3"
},

@@ -58,3 +46,18 @@ "keywords": [

"url": "https://github.com/Code-Hex/firebase-auth-cloudflare-workers/issues"
},
"scripts": {
"test": "vitest run",
"test-with-emulator": "firebase emulators:exec --project project12345 'vitest run'",
"build": "run-p build:*",
"build:main": "tsc -p tsconfig.main.json",
"build:module": "tsc -p tsconfig.module.json",
"start-firebase-emulator": "firebase emulators:start --project project12345",
"start-example": "wrangler dev example/index.ts --config=example/wrangler.toml --local=true",
"prettier": "prettier --write --list-different \"**/*.ts\"",
"prettier:check": "prettier --check \"**/*.ts\"",
"lint": "eslint --ext .ts .",
"lint-fix": "eslint --fix --ext .ts .",
"prepublish": "run-p build:*",
"wrangler": "wrangler"
}
}
}

@@ -113,3 +113,3 @@ # firebase-auth-cloudflare-workers

### `Auth.getOrInitialize(projectId: string, keyStore: KeyStorer): Auth`
### `Auth.getOrInitialize(projectId: string, keyStore: KeyStorer, credential?: Credential): Auth`

@@ -120,2 +120,3 @@ Auth is created as a singleton object. This is because the Module Worker syntax only use environment variables at the time of request.

- `keyStore` is used to cache the public key used to validate the Firebase ID token (JWT).
- `credential` is an optional. This is used to utilize Admin APIs such as `createSessionCookie`. Currently, you can specify `ServiceAccountCredential` class, which allows you to use a service account.

@@ -130,2 +131,3 @@ See official document for project ID: https://firebase.google.com/docs/projects/learn-more#project-identifiers

- `idToken` The ID token to verify.
- `env` is an optional parameter. but this is using to detect should use emulator or not.

@@ -144,2 +146,21 @@

### `createSessionCookie(idToken: string, sessionCookieOptions: SessionCookieOptions, env?: EmulatorEnv): Promise<string>`
Creates a new Firebase session cookie with the specified options. The created JWT string can be set as a server-side session cookie with a custom cookie policy, and be used for session management. The session cookie JWT will have the same payload claims as the provided ID token. See [Manage Session Cookies](https://firebase.google.com/docs/auth/admin/manage-cookies) for code samples and detailed documentation.
- `idToken` The Firebase ID token to exchange for a session cookie.
- `sessionCookieOptions` The session cookie options which includes custom session duration.
- `env` is an optional parameter. but this is using to detect should use emulator or not.
**Required** service acccount credential to use this API. You need to set the credentials with `Auth.getOrInitialize`.
### `verifySessionCookie(sessionCookie: string, env?: EmulatorEnv): Promise<FirebaseIdToken>`
Verifies a Firebase session cookie. Returns a Promise with the cookie claims. Rejects the promise if the cookie could not be verified.
See [Verify Session Cookies](https://firebase.google.com/docs/auth/admin/manage-cookies#verify_session_cookie_and_check_permissions) for code samples and detailed documentation.
- `sessionCookie` The session cookie to verify.
- `env` is an optional parameter. but this is using to detect should use emulator or not.
### `emulatorHost(env?: EmulatorEnv): string | undefined`

@@ -192,10 +213,16 @@

1. Clone this repository and change your directory to it.
2. Install dev dependencies as `yarn` command.
3. Run firebase auth emulator by `$ yarn start-firebase-emulator`
2. Install dev dependencies as `pnpm` command.
3. Run firebase auth emulator by `$ pnpm start-firebase-emulator`
4. Access to Emulator UI in your favorite browser.
5. Create a new user on Emulator UI. (email: `test@example.com` password: `test1234`)
6. Run example code on local (may serve as `localhost:8787`) by `$ yarn start-example`
6. Run example code on local (may serve as `localhost:8787`) by `$ pnpm start-example`
7. Get jwt for created user by `$ curl -s http://localhost:8787/get-jwt | jq .idToken -r`
8. Try authorization with user jwt `$ curl http://localhost:8787/ -H 'Authorization: Bearer PASTE-JWT-HERE'`
### for Session Cookie
You can try session cookie with your browser.
Access to `/admin/login` after started up Emulator and created an account (email: `test@example.com` password: `test1234`).
## Todo

@@ -202,0 +229,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc