diff --git a/app-config.yaml b/app-config.yaml index 6202d48560..38f16e1ac3 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -136,8 +136,6 @@ auth: env: AUTH_AUTH0_DOMAIN microsoft: development: - appOrigin: 'http://localhost:3000/' - secure: false clientId: $secret: env: AUTH_MICROSOFT_CLIENT_ID diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index c23f09a5be..eedd07ed08 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -135,8 +135,7 @@ export const apis = (config: ConfigApi) => { builder.add( microsoftAuthApiRef, MicrosoftAuth.create({ - backendUrl, - basePath: '/auth/', + discoveryApi, oauthRequestApi, }), ); diff --git a/packages/core-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts b/packages/core-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts index d4a70995e3..5800308c26 100644 --- a/packages/core-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts +++ b/packages/core-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts @@ -30,15 +30,17 @@ import { BackstageIdentity, } from '../../../definitions/auth'; -import { OAuthRequestApi, AuthProvider } from '../../../definitions'; +import { + OAuthRequestApi, + AuthProvider, + DiscoveryApi, +} from '../../../definitions'; import { SessionManager } from '../../../../lib/AuthSessionManager/types'; import { RefreshingAuthSessionManager } from '../../../../lib/AuthSessionManager'; import { Observable } from '../../../../types'; type CreateOptions = { - backendUrl: string; - basePath: string; - + discoveryApi: DiscoveryApi; oauthRequestApi: OAuthRequestApi; environment?: string; @@ -70,15 +72,13 @@ class MicrosoftAuth BackstageIdentityApi, SessionStateApi { static create({ - backendUrl, - basePath, environment = 'development', provider = DEFAULT_PROVIDER, oauthRequestApi, + discoveryApi, }: CreateOptions) { const connector = new DefaultAuthConnector({ - backendUrl, - basePath, + discoveryApi, environment, provider, oauthRequestApi: oauthRequestApi, diff --git a/plugins/auth-backend/src/lib/OAuthProvider.ts b/plugins/auth-backend/src/lib/OAuthProvider.ts index dccab34da1..dac31b442d 100644 --- a/plugins/auth-backend/src/lib/OAuthProvider.ts +++ b/plugins/auth-backend/src/lib/OAuthProvider.ts @@ -274,6 +274,13 @@ export class OAuthProvider implements AuthProviderRouteHandlers { await this.populateIdentity(response.backstageIdentity); + if ( + response.providerInfo.refreshToken && + response.providerInfo.refreshToken !== refreshToken + ) { + this.setRefreshTokenCookie(res, response.providerInfo.refreshToken); + } + res.send(response); } catch (error) { res.status(401).send(`${error.message}`); diff --git a/plugins/auth-backend/src/lib/PassportStrategyHelper.ts b/plugins/auth-backend/src/lib/PassportStrategyHelper.ts index 4cc0de4444..9a169f9696 100644 --- a/plugins/auth-backend/src/lib/PassportStrategyHelper.ts +++ b/plugins/auth-backend/src/lib/PassportStrategyHelper.ts @@ -45,7 +45,6 @@ export const makeProfileInfo = ( if ((!email || !picture) && idToken) { try { const decoded: Record = jwtDecoder(idToken); - if (!email && decoded.email) { email = decoded.email; } @@ -133,7 +132,7 @@ export const executeRefreshTokenStrategy = async ( ( err: Error | null, accessToken: string, - _refreshToken: string, + newRefreshToken: string, params: any, ) => { if (err) { @@ -149,6 +148,7 @@ export const executeRefreshTokenStrategy = async ( resolve({ accessToken, + refreshToken: newRefreshToken, params, }); }, diff --git a/plugins/auth-backend/src/providers/oauth2/provider.ts b/plugins/auth-backend/src/providers/oauth2/provider.ts index 72cd76c4cd..4b8a826d81 100644 --- a/plugins/auth-backend/src/providers/oauth2/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2/provider.ts @@ -67,6 +67,7 @@ export class OAuth2AuthProvider implements OAuthProviderHandlers { done: PassportDoneCallback, ) => { const profile = makeProfileInfo(rawProfile, params.id_token); + done( undefined, { @@ -113,11 +114,16 @@ export class OAuth2AuthProvider implements OAuthProviderHandlers { } async refresh(refreshToken: string, scope: string): Promise { - const { accessToken, params } = await executeRefreshTokenStrategy( + const refreshTokenResponse = await executeRefreshTokenStrategy( this._strategy, refreshToken, scope, ); + const { + accessToken, + params, + refreshToken: updatedRefreshToken, + } = refreshTokenResponse; const profile = await executeFetchUserProfileStrategy( this._strategy, @@ -128,6 +134,7 @@ export class OAuth2AuthProvider implements OAuthProviderHandlers { return this.populateIdentity({ providerInfo: { accessToken, + refreshToken: updatedRefreshToken, idToken: params.id_token, expiresInSeconds: params.expires_in, scope: params.scope, @@ -146,7 +153,6 @@ export class OAuth2AuthProvider implements OAuthProviderHandlers { if (!profile.email) { throw new Error('Profile does not contain a profile'); } - const id = profile.email.split('@')[0]; return { ...response, backstageIdentity: { id } }; diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index bdc12a382f..80b8899d94 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -213,6 +213,10 @@ export type OAuthProviderInfo = { * Scopes granted for the access token. */ scope: string; + /** + * A refresh token issued for the signed in user + */ + refreshToken?: string; }; export type OAuthPrivateInfo = { @@ -280,6 +284,10 @@ export type RefreshTokenResponse = { * An access token issued for the signed in user. */ accessToken: string; + /** + * Optionally, the server can issue a new Refresh Token for the user + */ + refreshToken?: string; params: any; };