diff --git a/plugins/auth-backend/src/lib/session/constants.ts b/plugins/auth-backend/src/lib/session/constants.ts deleted file mode 100644 index 0d14987ab2..0000000000 --- a/plugins/auth-backend/src/lib/session/constants.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// BACKSTAGE_SESSION_EXPIRATION the default session expiration time -// TODO: find a less hard-coded way to access this, perhaps by reading it from the configuration. -export const BACKSTAGE_SESSION_EXPIRATION = 3600; diff --git a/plugins/auth-backend/src/lib/session/index.ts b/plugins/auth-backend/src/lib/session/index.ts deleted file mode 100644 index 306d483ae0..0000000000 --- a/plugins/auth-backend/src/lib/session/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { BACKSTAGE_SESSION_EXPIRATION } from './constants'; diff --git a/plugins/auth-backend/src/service/readBackstageTokenExpiration.test.ts b/plugins/auth-backend/src/service/readBackstageTokenExpiration.test.ts new file mode 100644 index 0000000000..e1f863678a --- /dev/null +++ b/plugins/auth-backend/src/service/readBackstageTokenExpiration.test.ts @@ -0,0 +1,77 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ConfigReader } from '@backstage/config'; +import { readBackstageTokenExpiration } from './readBackstageTokenExpiration'; + +describe('Test for default backstage token expiry time', () => { + it('Will return default backstage session expiration', () => { + const config = new ConfigReader({ + app: { + baseUrl: 'http://example.com/extra-path', + }, + }); + expect(readBackstageTokenExpiration(config)).toBe(3600); + }); + + it('Will return user defined 120 minutes as backstage session expiration', () => { + const config = new ConfigReader({ + app: { + baseUrl: 'http://example.com/extra-path', + }, + auth: { + backstageTokenExpiration: { minutes: 120 }, + }, + }); + expect(readBackstageTokenExpiration(config)).toBe(7200); + }); + + it('Will return minimum duration of 10 minutes as backstage session expiration', () => { + const config = new ConfigReader({ + app: { + baseUrl: 'http://example.com/extra-path', + }, + auth: { + backstageTokenExpiration: { minutes: 2 }, + }, + }); + expect(readBackstageTokenExpiration(config)).toBe(600); + }); + + it('Will return user configured value as backstage session expiration', () => { + const config = new ConfigReader({ + app: { + baseUrl: 'http://example.com/extra-path', + }, + auth: { + backstageTokenExpiration: { minutes: 20 }, + }, + }); + expect(readBackstageTokenExpiration(config)).toBe(1200); + }); + + it('Will return maximum of 24 hour as backstage session expiration if user configured value is more than a day', () => { + const config = new ConfigReader({ + app: { + baseUrl: 'http://example.com/extra-path', + }, + auth: { + backstageTokenExpiration: { minutes: 1500 }, + }, + }); + expect(readBackstageTokenExpiration(config)).toBe(86400); + }); +}); diff --git a/plugins/auth-backend/src/service/readBackstageTokenExpiration.ts b/plugins/auth-backend/src/service/readBackstageTokenExpiration.ts new file mode 100644 index 0000000000..c687ecdfc5 --- /dev/null +++ b/plugins/auth-backend/src/service/readBackstageTokenExpiration.ts @@ -0,0 +1,44 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RootConfigService } from '@backstage/backend-plugin-api'; +import { readDurationFromConfig } from '@backstage/config'; +import { durationToMilliseconds } from '@backstage/types'; + +const TOKEN_EXP_DEFAULT_S = 3600; +const TOKEN_EXP_MIN_S = 600; +const TOKEN_EXP_MAX_S = 86400; + +export function readBackstageTokenExpiration(config: RootConfigService) { + const processingIntervalKey = 'auth.backstageTokenExpiration'; + + if (!config.has(processingIntervalKey)) { + return TOKEN_EXP_DEFAULT_S; + } + + const duration = readDurationFromConfig(config, { + key: processingIntervalKey, + }); + + const durationS = Math.round(durationToMilliseconds(duration) / 1000); + + if (durationS < TOKEN_EXP_MIN_S) { + return TOKEN_EXP_MIN_S; + } else if (durationS > TOKEN_EXP_MAX_S) { + return TOKEN_EXP_MAX_S; + } + return durationS; +} diff --git a/plugins/auth-backend/src/service/router.test.ts b/plugins/auth-backend/src/service/router.test.ts index 8805a60e56..3a1fde881e 100644 --- a/plugins/auth-backend/src/service/router.test.ts +++ b/plugins/auth-backend/src/service/router.test.ts @@ -15,11 +15,7 @@ */ import { ConfigReader } from '@backstage/config'; -import { - createOriginFilter, - getDefaultBackstageTokenExpiryTime, -} from './router'; -import { BACKSTAGE_SESSION_EXPIRATION } from '../lib/session'; +import { createOriginFilter } from './router'; describe('Auth origin filtering', () => { const config = new ConfigReader({ @@ -56,64 +52,3 @@ describe('Auth origin filtering', () => { expect(createOriginFilter(config)(origin)).toBeTruthy(); }); }); - -describe('Test for default backstage token expiry time', () => { - it('Will return default backstage session expiration', () => { - const config = new ConfigReader({ - app: { - baseUrl: 'http://example.com/extra-path', - }, - }); - expect(getDefaultBackstageTokenExpiryTime(config)).toBe( - BACKSTAGE_SESSION_EXPIRATION, - ); - }); - - it('Will return user defined 120 minutes as backstage session expiration', () => { - const config = new ConfigReader({ - app: { - baseUrl: 'http://example.com/extra-path', - }, - auth: { - backstageTokenExpiration: { minutes: 120 }, - }, - }); - expect(getDefaultBackstageTokenExpiryTime(config)).toBe(7200); - }); - - it('Will return minimum duration of 10 minutes as backstage session expiration', () => { - const config = new ConfigReader({ - app: { - baseUrl: 'http://example.com/extra-path', - }, - auth: { - backstageTokenExpiration: { minutes: 2 }, - }, - }); - expect(getDefaultBackstageTokenExpiryTime(config)).toBe(600); - }); - - it('Will return user configured value as backstage session expiration', () => { - const config = new ConfigReader({ - app: { - baseUrl: 'http://example.com/extra-path', - }, - auth: { - backstageTokenExpiration: { minutes: 20 }, - }, - }); - expect(getDefaultBackstageTokenExpiryTime(config)).toBe(1200); - }); - - it('Will return maximum of 24 hour as backstage session expiration if user configured value is more than a day', () => { - const config = new ConfigReader({ - app: { - baseUrl: 'http://example.com/extra-path', - }, - auth: { - backstageTokenExpiration: { minutes: 1500 }, - }, - }); - expect(getDefaultBackstageTokenExpiryTime(config)).toBe(86400); - }); -}); diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index dddac82c2d..44861207ed 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -36,12 +36,11 @@ import passport from 'passport'; import { Minimatch } from 'minimatch'; import { CatalogAuthResolverContext } from '../lib/resolvers'; import { AuthDatabase } from '../database/AuthDatabase'; -import { BACKSTAGE_SESSION_EXPIRATION } from '../lib/session'; +import { readBackstageTokenExpiration } from './readBackstageTokenExpiration'; import { TokenIssuer } from '../identity/types'; import { StaticTokenIssuer } from '../identity/StaticTokenIssuer'; import { StaticKeyStore } from '../identity/StaticKeyStore'; -import { Config, readDurationFromConfig } from '@backstage/config'; -import { durationToMilliseconds } from '@backstage/types'; +import { Config } from '@backstage/config'; /** @public */ export type ProviderFactories = { [s: string]: AuthProviderFactory }; @@ -77,7 +76,7 @@ export async function createRouter( const appUrl = config.getString('app.baseUrl'); const authUrl = await discovery.getExternalBaseUrl('auth'); - const backstageTokenExpiration = getDefaultBackstageTokenExpiryTime(config); + const backstageTokenExpiration = readBackstageTokenExpiration(config); const authDb = AuthDatabase.create(database); const keyStore = await KeyStores.fromConfig(config, { @@ -249,27 +248,3 @@ export function createOriginFilter( return allowedOriginPatterns.some(pattern => pattern.match(origin)); }; } - -/** @internal */ -export function getDefaultBackstageTokenExpiryTime(config: Config) { - const processingIntervalKey = 'auth.backstageTokenExpiration'; - - if (!config.has(processingIntervalKey)) { - return BACKSTAGE_SESSION_EXPIRATION; - } - - const duration = readDurationFromConfig(config, { - key: processingIntervalKey, - }); - - const roundedDuration = Math.round(durationToMilliseconds(duration) / 1000); - - const minSeconds = Math.max(600, roundedDuration); - - const maxSeconds = Math.min(86400, roundedDuration); - - if (roundedDuration < minSeconds) { - return minSeconds - } - return maxSeconds; -}