Skip to content

Commit a777385

Browse files
authored
[Auth] Add gmpid header (#5799)
* Add gmpid header * Add changeset
1 parent 931c80d commit a777385

File tree

8 files changed

+82
-19
lines changed

8 files changed

+82
-19
lines changed

.changeset/poor-files-learn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/auth": patch
3+
---
4+
5+
Add X-Firebase-gmpid header to requests

packages/auth/src/api/authentication/token.test.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18+
import * as sinon from 'sinon';
1819
import { expect, use } from 'chai';
1920
import chaiAsPromised from 'chai-as-promised';
2021

@@ -41,7 +42,10 @@ describe('requestStsToken', () => {
4142
fetch.setUp();
4243
});
4344

44-
afterEach(fetch.tearDown);
45+
afterEach(() => {
46+
fetch.tearDown();
47+
sinon.restore();
48+
});
4549

4650
it('should POST to the correct endpoint', async () => {
4751
const mock = fetch.mock(endpoint, {
@@ -90,6 +94,23 @@ describe('requestStsToken', () => {
9094
);
9195
});
9296

97+
it('should include whatever headers come from auth impl', async () => {
98+
sinon.stub(auth, '_getAdditionalHeaders').returns(Promise.resolve({
99+
'look-at-me-im-a-header': 'header-value',
100+
'anotherheader': 'header-value-2',
101+
}));
102+
103+
const mock = fetch.mock(endpoint, {
104+
'access_token': 'new-access-token',
105+
'expires_in': '3600',
106+
'refresh_token': 'new-refresh-token'
107+
});
108+
await requestStsToken(auth, 'old-refresh-token');
109+
110+
expect(mock.calls[0].headers.get('look-at-me-im-a-header')).to.eq('header-value');
111+
expect(mock.calls[0].headers.get('anotherheader')).to.eq('header-value-2');
112+
});
113+
93114
it('should handle errors', async () => {
94115
const mock = fetch.mock(
95116
endpoint,

packages/auth/src/api/authentication/token.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import { querystring } from '@firebase/util';
2222
import {
2323
_getFinalTarget,
2424
_performFetchWithErrorHandling,
25-
HttpMethod
25+
HttpMethod,
26+
HttpHeader
2627
} from '../index';
2728
import { FetchProvider } from '../../core/util/fetch_provider';
2829
import { Auth } from '../../model/public_types';
@@ -52,7 +53,7 @@ export async function requestStsToken(
5253
const response = await _performFetchWithErrorHandling<RequestStsTokenServerResponse>(
5354
auth,
5455
{},
55-
() => {
56+
async () => {
5657
const body = querystring({
5758
'grant_type': 'refresh_token',
5859
'refresh_token': refreshToken
@@ -65,12 +66,12 @@ export async function requestStsToken(
6566
`key=${apiKey}`
6667
);
6768

69+
const headers = await (auth as AuthInternal)._getAdditionalHeaders();
70+
headers[HttpHeader.CONTENT_TYPE] = 'application/x-www-form-urlencoded';
71+
6872
return FetchProvider.fetch()(url, {
6973
method: HttpMethod.POST,
70-
headers: {
71-
'X-Client-Version': (auth as AuthInternal)._getSdkClientVersion(),
72-
'Content-Type': 'application/x-www-form-urlencoded'
73-
},
74+
headers,
7475
body
7576
});
7677
}

packages/auth/src/api/index.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,21 @@ describe('api/_performApiRequest', () => {
9494
);
9595
});
9696

97+
it('should include whatever headers the auth impl attaches', async () => {
98+
sinon.stub(auth, '_getAdditionalHeaders').returns(Promise.resolve({
99+
'look-at-me-im-a-header': 'header-value',
100+
'anotherheader': 'header-value-2',
101+
}));
102+
103+
const mock = mockEndpoint(Endpoint.SIGN_UP, serverResponse);
104+
await _performApiRequest<
105+
typeof request,
106+
typeof serverResponse
107+
>(auth, HttpMethod.POST, Endpoint.SIGN_UP, request);
108+
expect(mock.calls[0].headers.get('look-at-me-im-a-header')).to.eq('header-value');
109+
expect(mock.calls[0].headers.get('anotherheader')).to.eq('header-value-2');
110+
});
111+
97112
it('should set the framework in clientVersion if logged', async () => {
98113
auth._logFramework('Mythical');
99114
const mock = mockEndpoint(Endpoint.SIGN_UP, serverResponse);

packages/auth/src/api/index.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ export const enum HttpMethod {
3636
export const enum HttpHeader {
3737
CONTENT_TYPE = 'Content-Type',
3838
X_FIREBASE_LOCALE = 'X-Firebase-Locale',
39-
X_CLIENT_VERSION = 'X-Client-Version'
39+
X_CLIENT_VERSION = 'X-Client-Version',
40+
X_FIREBASE_GMPID = 'X-Firebase-gmpid'
4041
}
4142

4243
export const enum Endpoint {
@@ -84,7 +85,7 @@ export async function _performApiRequest<T, V>(
8485
request?: T,
8586
customErrorMap: Partial<ServerErrorMap<ServerError>> = {}
8687
): Promise<V> {
87-
return _performFetchWithErrorHandling(auth, customErrorMap, () => {
88+
return _performFetchWithErrorHandling(auth, customErrorMap, async () => {
8889
let body = {};
8990
let params = {};
9091
if (request) {
@@ -102,15 +103,11 @@ export async function _performApiRequest<T, V>(
102103
...params
103104
}).slice(1);
104105

105-
const headers = new (FetchProvider.headers())();
106-
headers.set(HttpHeader.CONTENT_TYPE, 'application/json');
107-
headers.set(
108-
HttpHeader.X_CLIENT_VERSION,
109-
(auth as AuthInternal)._getSdkClientVersion()
110-
);
106+
const headers = await (auth as AuthInternal)._getAdditionalHeaders();
107+
headers[HttpHeader.CONTENT_TYPE] = 'application/json';
111108

112109
if (auth.languageCode) {
113-
headers.set(HttpHeader.X_FIREBASE_LOCALE, auth.languageCode);
110+
headers[HttpHeader.X_FIREBASE_LOCALE] = auth.languageCode;
114111
}
115112

116113
return FetchProvider.fetch()(

packages/auth/src/core/auth/auth_impl.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,4 +460,20 @@ describe('core/auth/auth_impl', () => {
460460
expect(spy).not.to.have.been.called;
461461
});
462462
});
463+
464+
context ('#_getAdditionalHeaders', () => {
465+
it('always adds the client version', async () => {
466+
expect(await auth._getAdditionalHeaders()).to.eql({
467+
'X-Client-Version': 'v',
468+
});
469+
});
470+
471+
it('adds the gmp app ID if available', async () => {
472+
auth.app.options.appId = 'app-id';
473+
expect(await auth._getAdditionalHeaders()).to.eql({
474+
'X-Client-Version': 'v',
475+
'X-Firebase-gmpid': 'app-id',
476+
});
477+
});
478+
});
463479
});

packages/auth/src/core/auth/auth_impl.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import { _assert } from '../util/assert';
5858
import { _getInstance } from '../util/instantiator';
5959
import { _getUserLanguage } from '../util/navigator';
6060
import { _getClientVersion } from '../util/version';
61+
import { HttpHeader } from '../../api';
6162

6263
interface AsyncAction {
6364
(): Promise<void>;
@@ -577,8 +578,15 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
577578
_getFrameworks(): readonly string[] {
578579
return this.frameworks;
579580
}
580-
_getSdkClientVersion(): string {
581-
return this.clientVersion;
581+
async _getAdditionalHeaders(): Promise<Record<string, string>> {
582+
// Additional headers on every request
583+
const headers: Record<string, string> = {
584+
[HttpHeader.X_CLIENT_VERSION]: this.clientVersion,
585+
};
586+
if (this.app.options.appId) {
587+
headers[HttpHeader.X_FIREBASE_GMPID] = this.app.options.appId;
588+
}
589+
return headers;
582590
}
583591
}
584592

packages/auth/src/model/auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export interface AuthInternal extends Auth {
8181
_getPersistence(): string;
8282
_logFramework(framework: string): void;
8383
_getFrameworks(): readonly string[];
84-
_getSdkClientVersion(): string;
84+
_getAdditionalHeaders(): Promise<Record<string, string>>;
8585

8686
readonly name: AppName;
8787
readonly config: ConfigInternal;

0 commit comments

Comments
 (0)