Skip to content

Pass API Key as request param for Regional Auth requests & Demo App changes #9102

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

Merged
merged 9 commits into from
Jun 23, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/test-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ env:
# the behavior to use the new URLs.
CHROMEDRIVER_CDNURL: https://googlechromelabs.github.io/
CHROMEDRIVER_CDNBINARIESURL: https://storage.googleapis.com/chrome-for-testing-public
CHROME_VALIDATED_VERSION: linux-132.0.6834.110
CHROME_VALIDATED_VERSION: linux-137.0.0.0
CHROME_VERSION_MISMATCH_MESSAGE: "The Chrome version doesn't match the previously validated version. Consider updating CHROME_VALIDATED_VERSION in the GitHub workflow if tests pass, or rollback the installed Chrome version if tests fail."
artifactRetentionDays: 14
# Bump Node memory limit
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-changed-auth.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ env:
# the behavior to use the new URLs.
CHROMEDRIVER_CDNURL: https://googlechromelabs.github.io/
CHROMEDRIVER_CDNBINARIESURL: https://storage.googleapis.com/chrome-for-testing-public
CHROME_VALIDATED_VERSION: linux-120.0.6099.71
CHROME_VALIDATED_VERSION: linux-137.0.7151.119
# Bump Node memory limit
NODE_OPTIONS: "--max_old_space_size=4096"

Expand Down Expand Up @@ -119,4 +119,4 @@ jobs:
- name: Run tests on changed packages
run: yarn test:changed auth
env:
BROWSERS: 'WebkitHeadless'
BROWSERS: 'WebkitHeadless'
17 changes: 17 additions & 0 deletions packages/auth/demo/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@
Action Code Settings
</a>
</li>
<li role="presentation">
<a href="#tab-byo-ciam-content"
aria-controls="tab-byo-ciam-content"
data-toggle="tab" role="tab">
BYO-CIAM methods
</a>
</li>
<li role="presentation" class="visible-xs">
<a href="#logs-section"
aria-controls="logs-section"
Expand Down Expand Up @@ -844,6 +851,16 @@
id="action-code-settings-reset">Reset</button>
</form>
</div>
<div class="tab-pane" id="tab-byo-ciam-content">
<h2>Sign in with your CIAM token</h2>
<input type="text" id="byo-ciam-token"
class="form-control" placeholder="Enter CIAM token" />
<button class="btn btn-block btn-primary"
id="exchange-token">
Exchange Token
</button>
<pre id="byo-ciam-result"></pre>
</div>
<div class="tab-pane" id="logs-section">
<pre class="well logs"></pre>
<button class="btn btn-xs btn-default pull-right clear-logs">
Expand Down
45 changes: 44 additions & 1 deletion packages/auth/demo/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ import {
connectAuthEmulator,
initializeRecaptchaConfig,
validatePassword,
revokeAccessToken
revokeAccessToken,
exchangeToken
} from '@firebase/auth';

import { config } from './config';
Expand All @@ -95,6 +96,7 @@ const AUTH_EMULATOR_URL = 'http://localhost:9099';

let app = null;
let auth = null;
let regionalAuth = null;
let currentTab = null;
let lastUser = null;
let applicationVerifier = null;
Expand Down Expand Up @@ -1506,6 +1508,32 @@ function onFinalizeSignInWithTotpMultiFactor(event) {
}, onAuthError);
}

async function exchangeCIAMToken(token) {
const firebaseToken = await exchangeToken(
regaionalAuth,
(idpConfigId = 'Bar-e2e-idpconfig-002'),
token
);
return firebaseToken;
}

function onExchangeToken(event) {
event.preventDefault();
const byoCiamInput = document.getElementById('byo-ciam-token');
const byoCiamResult = document.getElementById('byo-ciam-result');

byoCiamResult.textContent = 'Exchanging token...';

exchangeCIAMToken(byoCiamInput.value)
.then(response => {
byoCiamResult.textContent = response.accessToken;
console.log('Token:', response);
})
.catch(error => {
console.error('Error exchanging token:', error);
});
}

/**
* Adds a new row to insert an OAuth custom parameter key/value pair.
* @param {!jQuery.Event} _event The jQuery event object.
Expand Down Expand Up @@ -2051,6 +2079,18 @@ function initApp() {
connectAuthEmulator(auth, AUTH_EMULATOR_URL);
}

let tenantConfig = {
'location': 'global',
'tenantId': 'Foo-e2e-tenant-001'
};
const regionalApp = initializeApp(config, `${auth.name}-rgcip`);

regionalAuth = initializeAuth(regionalApp, {
persistence: inMemoryPersistence,
popupRedirectResolver: browserPopupRedirectResolver,
tenantConfig: tenantConfig
});

tempApp = initializeApp(
{
apiKey: config.apiKey,
Expand Down Expand Up @@ -2391,6 +2431,9 @@ function initApp() {
$('#enroll-mfa-totp-finalize').click(onFinalizeEnrollWithTotpMultiFactor);
// Sets tenant for the current auth instance
$('#set-tenant-btn').click(onSetTenantIdClick);

// Performs Exchange Token
$('#exchange-token').click(onExchangeToken);
}

$(initApp);
8 changes: 6 additions & 2 deletions packages/auth/src/api/authentication/exchange_token.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ describe('api/authentication/exchange_token', () => {
let regionalAuth: TestAuth;
const request = {
parent: 'test-parent',
token: 'custom-token'
// eslint-disable-next-line camelcase
id_token: 'custom-token'
};

beforeEach(async () => {
Expand All @@ -52,6 +53,7 @@ describe('api/authentication/exchange_token', () => {
const mock = mockRegionalEndpointWithParent(
RegionalEndpoint.EXCHANGE_TOKEN,
'test-parent',
'test-api-key',
{ accessToken: 'outbound-token', expiresIn: '1000' }
);

Expand All @@ -60,7 +62,8 @@ describe('api/authentication/exchange_token', () => {
expect(response.expiresIn).equal('1000');
expect(mock.calls[0].request).to.eql({
parent: 'test-parent',
token: 'custom-token'
// eslint-disable-next-line camelcase
id_token: 'custom-token'
});
expect(mock.calls[0].method).to.eq('POST');
expect(mock.calls[0].headers!.get(HttpHeader.CONTENT_TYPE)).to.eq(
Expand All @@ -79,6 +82,7 @@ describe('api/authentication/exchange_token', () => {
const mock = mockRegionalEndpointWithParent(
RegionalEndpoint.EXCHANGE_TOKEN,
'test-parent',
'test-api-key',
{
error: {
code: 400,
Expand Down
2 changes: 1 addition & 1 deletion packages/auth/src/api/authentication/exchange_token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { Auth } from '../../model/public_types';

export interface ExchangeTokenRequest {
parent: string;
token: string;
id_token: string;
}

export interface ExchangeTokenResponse {
Expand Down
2 changes: 2 additions & 0 deletions packages/auth/src/api/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,7 @@ describe('api/_performRegionalApiRequest', () => {
const mock = mockRegionalEndpointWithParent(
RegionalEndpoint.EXCHANGE_TOKEN,
'test-parent',
'test-api-key',
serverResponse
);
const response = await _performRegionalApiRequest<
Expand Down Expand Up @@ -689,6 +690,7 @@ describe('api/_performRegionalApiRequest', () => {
const mock = mockRegionalEndpointWithParent(
RegionalEndpoint.EXCHANGE_TOKEN,
'test-parent',
'test-api-key',
serverResponse
);
await _performRegionalApiRequest<typeof request, typeof serverResponse>(
Expand Down
15 changes: 4 additions & 11 deletions packages/auth/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,17 +168,10 @@ async function performApiRequest<T, V>(
}
}

let queryParamString: string;
if (isRegionalAuthInitialized(auth)) {
queryParamString = querystring({
...params
}).slice(1);
} else {
queryParamString = querystring({
key: auth.config.apiKey,
...params
}).slice(1);
}
const queryParamString = querystring({
key: auth.config.apiKey,
...params
}).slice(1);

const headers = await (auth as AuthInternal)._getAdditionalHeaders();
headers[HttpHeader.CONTENT_TYPE] = 'application/json';
Expand Down
2 changes: 1 addition & 1 deletion packages/auth/src/core/auth/auth_impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export const enum DefaultConfig {
API_HOST = 'identitytoolkit.googleapis.com',
API_SCHEME = 'https',
// TODO(sammansi): Update the endpoint before BYO-CIAM Private Preview Release.
REGIONAL_API_HOST = 'identityplatform.googleapis.com/v2alpha/'
REGIONAL_API_HOST = 'autopush-identityplatform.sandbox.googleapis.com/v2alpha/'
}

export class AuthImpl implements AuthInternal, _FirebaseService {
Expand Down
8 changes: 6 additions & 2 deletions packages/auth/src/core/strategies/exchange_token.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ describe('core/strategies/exchangeToken', () => {
const mock = mockRegionalEndpointWithParent(
RegionalEndpoint.EXCHANGE_TOKEN,
'projects/test-project-id/locations/us/tenants/tenant-1/idpConfigs/idp-config',
'test-api-key',
{ accessToken: 'outbound-token', expiresIn: 10 }
);

Expand All @@ -64,7 +65,8 @@ describe('core/strategies/exchangeToken', () => {
expect(mock.calls[0].request).to.eql({
parent:
'projects/test-project-id/locations/us/tenants/tenant-1/idpConfigs/idp-config',
token: 'custom-token'
// eslint-disable-next-line camelcase
id_token: 'custom-token'
});
expect(mock.calls[0].method).to.eq('POST');
expect(mock.calls[0].headers!.get(HttpHeader.CONTENT_TYPE)).to.eq(
Expand All @@ -87,6 +89,7 @@ describe('core/strategies/exchangeToken', () => {
const mock = mockRegionalEndpointWithParent(
RegionalEndpoint.EXCHANGE_TOKEN,
'projects/test-project-id/locations/us/tenants/tenant-1/idpConfigs/idp-config',
'test-api-key',
{
error: {
code: 400,
Expand All @@ -107,7 +110,8 @@ describe('core/strategies/exchangeToken', () => {
expect(mock.calls[0].request).to.eql({
parent:
'projects/test-project-id/locations/us/tenants/tenant-1/idpConfigs/idp-config',
token: 'custom-token'
// eslint-disable-next-line camelcase
id_token: 'custom-token'
});
expect(mock.calls[0].method).to.eq('POST');
expect(mock.calls[0].headers!.get(HttpHeader.CONTENT_TYPE)).to.eq(
Expand Down
3 changes: 2 additions & 1 deletion packages/auth/src/core/strategies/exhange_token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ export async function exchangeToken(
const authInternal = _castAuth(auth);
const token = await getToken(authInternal, {
parent: buildParent(auth, idpConfigId),
token: customToken
// eslint-disable-next-line camelcase
id_token: customToken
});
if (token) {
await authInternal._updateFirebaseToken({
Expand Down
6 changes: 4 additions & 2 deletions packages/auth/test/helpers/api/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,12 @@ export function mockEndpointWithParams(
export function mockRegionalEndpointWithParent(
endpoint: RegionalEndpoint,
parent: string,
key: string,
response: object,
status = 200
): Route {
const url = `${TEST_SCHEME}://${TEST_HOST}${parent}${endpoint}`;
console.log('here ', url);
let url = `${TEST_SCHEME}://${TEST_HOST}${parent}${endpoint}`;
url += '?key=';
url += key;
return mock(url, response, status);
}
Loading