Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Unreleased

- [changed] The `admin.initializeApp()` method can now be invoked without an
explicit `credential` option. In that case the SDK will get initialized with
Google application default credentials.
- [changed] Upgraded Realtime Database client to v0.1.11.
- [changed] Modified the Realtime Database client integration to report the
correct user agent header.
Expand Down
23 changes: 11 additions & 12 deletions src/firebase-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import {Credential, GoogleOAuthAccessToken} from './auth/credential';
import {ApplicationDefaultCredential, Credential, GoogleOAuthAccessToken} from './auth/credential';
import * as validator from './utils/validator';
import {deepCopy, deepExtend} from './utils/deep-copy';
import {FirebaseServiceInterface} from './firebase-service';
Expand Down Expand Up @@ -248,27 +248,26 @@ export class FirebaseApp {
this.name_ = name;
this.options_ = deepCopy(options) as FirebaseAppOptions;

if (typeof this.options_ !== 'object' || this.options_ === null) {
// Ensure the options are a non-null object
this.options_ = {};
if (!validator.isNonNullObject(this.options_)) {
throw new FirebaseAppError(
AppErrorCodes.INVALID_APP_OPTIONS,
`Invalid Firebase app options passed as the first argument to initializeApp() for the ` +
`app named "${this.name_}". Options must be a non-null object.`,
);
}

const hasCredential = ('credential' in this.options_);

let errorMessage: string;
if (!hasCredential) {
errorMessage = 'Options must be an object containing at least a "credential" property.';
this.options_.credential = new ApplicationDefaultCredential();
}

const credential = this.options_.credential;
if (typeof credential !== 'object' || credential === null || typeof credential.getAccessToken !== 'function') {
errorMessage = 'The "credential" property must be an object which implements the Credential interface.';
}

if (typeof errorMessage !== 'undefined') {
throw new FirebaseAppError(
AppErrorCodes.INVALID_APP_OPTIONS,
`Invalid Firebase app options passed as the first argument to initializeApp() for the ` +
`app named "${this.name_}". ${errorMessage}`,
`app named "${this.name_}". The "credential" property must be an object which implements ` +
`the Credential interface.`,
);
}

Expand Down
19 changes: 7 additions & 12 deletions test/unit/firebase.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import * as utils from './utils';
import * as mocks from '../resources/mocks';

import * as firebaseAdmin from '../../src/index';
import {ApplicationDefaultCredential} from '../../src/auth/credential';

chai.should();
chai.use(chaiAsPromised);
Expand Down Expand Up @@ -55,25 +56,19 @@ describe('Firebase', () => {
});

describe('#initializeApp()', () => {
const invalidOptions = [null, NaN, 0, 1, true, false, '', 'a', [], {}, _.noop];
invalidOptions.forEach((invalidOption) => {
const invalidOptions = [null, NaN, 0, 1, true, false, '', 'a', [], _.noop];
invalidOptions.forEach((invalidOption: any) => {
it('should throw given invalid options object: ' + JSON.stringify(invalidOption), () => {
expect(() => {
firebaseAdmin.initializeApp(invalidOption);
}).to.throw('Invalid Firebase app options');
});
});

it('should throw given an options object that does not contain any of the required keys', () => {
expect(() => {
firebaseAdmin.initializeApp({ a: 1, b: true } as any);
}).to.throw('Invalid Firebase app options');
});

it('should throw given an options object containing no "credential" key', () => {
expect(() => {
firebaseAdmin.initializeApp(mocks.appOptionsNoAuth);
}).to.throw('Invalid Firebase app options');
it('should use application default credentials when no credentials are explicitly specified', () => {
const app = firebaseAdmin.initializeApp(mocks.appOptionsNoAuth);
expect(app.options).to.have.property('credential');
expect(app.options.credential).to.be.instanceOf(ApplicationDefaultCredential);
});

it('should not modify the provided options object', () => {
Expand Down