-
Notifications
You must be signed in to change notification settings - Fork 390
feat(auth): Add support for Auth Emulator #1044
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4505e8f
654e19b
ee5ff77
f51e31b
b506e15
3b43e21
8ef7f0a
2a249fc
d7503f8
66b9abb
e65d769
3d5989f
17c1f45
6c1ee4b
6915268
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,9 +21,12 @@ import { AuthorizedHttpClient, HttpError, HttpRequestConfig, HttpClient } from ' | |
|
||
import * as validator from '../utils/validator'; | ||
import { toWebSafeBase64 } from '../utils'; | ||
import { Algorithm } from 'jsonwebtoken'; | ||
|
||
|
||
const ALGORITHM_RS256 = 'RS256'; | ||
const ALGORITHM_RS256: Algorithm = 'RS256' as const; | ||
const ALGORITHM_NONE: Algorithm = 'none' as const; | ||
|
||
const ONE_HOUR_IN_SECONDS = 60 * 60; | ||
|
||
// List of blacklisted claims which cannot be provided when creating a custom token | ||
|
@@ -39,6 +42,12 @@ const FIREBASE_AUDIENCE = 'https://identitytoolkit.googleapis.com/google.identit | |
* CryptoSigner interface represents an object that can be used to sign JWTs. | ||
*/ | ||
export interface CryptoSigner { | ||
|
||
/** | ||
* The name of the signing algorithm. | ||
*/ | ||
readonly algorithm: Algorithm; | ||
|
||
/** | ||
* Cryptographically signs a buffer of data. | ||
* | ||
|
@@ -82,6 +91,8 @@ interface JWTBody { | |
* sign data. Performs all operations locally, and does not make any RPC calls. | ||
*/ | ||
export class ServiceAccountSigner implements CryptoSigner { | ||
|
||
algorithm = ALGORITHM_RS256; | ||
|
||
/** | ||
* Creates a new CryptoSigner instance from the given service account credential. | ||
|
@@ -124,6 +135,8 @@ export class ServiceAccountSigner implements CryptoSigner { | |
* @see https://cloud.google.com/compute/docs/storing-retrieving-metadata | ||
*/ | ||
export class IAMSigner implements CryptoSigner { | ||
algorithm = ALGORITHM_RS256; | ||
|
||
private readonly httpClient: AuthorizedHttpClient; | ||
private serviceAccountId?: string; | ||
|
||
|
@@ -215,6 +228,29 @@ export class IAMSigner implements CryptoSigner { | |
} | ||
} | ||
|
||
/** | ||
* A CryptoSigner implementation that is used when communicating with the Auth emulator. | ||
* It produces unsigned tokens. | ||
*/ | ||
export class EmulatedSigner implements CryptoSigner { | ||
|
||
algorithm = ALGORITHM_NONE; | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
public sign(_: Buffer): Promise<Buffer> { | ||
return Promise.resolve(Buffer.from('')); | ||
} | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
public getAccountId(): Promise<string> { | ||
return Promise.resolve('[email protected]'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not so sure about this ... could we do something better here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cc @yuchenshi There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is probably the best thing we can do |
||
} | ||
} | ||
|
||
/** | ||
* Create a new CryptoSigner instance for the given app. If the app has been initialized with a service | ||
* account credential, creates a ServiceAccountSigner. Otherwise creates an IAMSigner. | ||
|
@@ -250,7 +286,7 @@ export class FirebaseTokenGenerator { | |
'INTERNAL ASSERT: Must provide a CryptoSigner to use FirebaseTokenGenerator.', | ||
); | ||
} | ||
if (typeof tenantId !== 'undefined' && !validator.isNonEmptyString(tenantId)) { | ||
if (typeof this.tenantId !== 'undefined' && !validator.isNonEmptyString(this.tenantId)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_ARGUMENT, | ||
'`tenantId` argument must be a non-empty string.'); | ||
|
@@ -298,7 +334,7 @@ export class FirebaseTokenGenerator { | |
} | ||
return this.signer.getAccountId().then((account) => { | ||
const header: JWTHeader = { | ||
alg: ALGORITHM_RS256, | ||
alg: this.signer.algorithm, | ||
typ: 'JWT', | ||
}; | ||
const iat = Math.floor(Date.now() / 1000); | ||
|
@@ -319,6 +355,7 @@ export class FirebaseTokenGenerator { | |
} | ||
const token = `${this.encodeSegment(header)}.${this.encodeSegment(body)}`; | ||
const signPromise = this.signer.sign(Buffer.from(token)); | ||
|
||
return Promise.all([token, signPromise]); | ||
}).then(([token, signature]) => { | ||
return `${token}.${this.encodeSegment(signature)}`; | ||
|
Uh oh!
There was an error while loading. Please reload this page.