Skip to content

Commit

Permalink
Merge 69a309d into f8ace2d
Browse files Browse the repository at this point in the history
  • Loading branch information
schultzp2020 committed Nov 7, 2023
2 parents f8ace2d + 69a309d commit aa42a3d
Show file tree
Hide file tree
Showing 12 changed files with 390 additions and 133 deletions.
5 changes: 5 additions & 0 deletions .changeset/tiny-cougars-unite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'app': minor
---

Add authentication provider conditional rendering for login page
5 changes: 5 additions & 0 deletions packages/app/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,9 @@ export interface Config {
};
};
};
/**
* The signInPage provider
* @visibility frontend
*/
signInPage?: string;
}
4 changes: 2 additions & 2 deletions packages/app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import DynamicRoot from './components/DynamicRoot';
import { apis } from './apis';
import React from 'react';
import { apis } from './apis';
import DynamicRoot from './components/DynamicRoot';

const AppRoot = () => (
<DynamicRoot apis={apis} afterInit={() => import('./components/AppBase')} />
Expand Down
27 changes: 27 additions & 0 deletions packages/app/src/api/AuthApiRefs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
createApiRef,
type ApiRef,
type BackstageIdentityApi,
type OAuthApi,
type OpenIdConnectApi,
type ProfileInfoApi,
type SessionApi,
} from '@backstage/core-plugin-api';

type CustomAuthApiRefType = OAuthApi &
OpenIdConnectApi &
ProfileInfoApi &
BackstageIdentityApi &
SessionApi;

export const oidcAuthApiRef: ApiRef<CustomAuthApiRefType> = createApiRef({
id: 'internal.auth.oidc',
});

export const auth0AuthApiRef: ApiRef<CustomAuthApiRefType> = createApiRef({
id: 'internal.auth.auth0',
});

export const samlAuthApiRef: ApiRef<CustomAuthApiRefType> = createApiRef({
id: 'internal.auth.saml',
});
64 changes: 64 additions & 0 deletions packages/app/src/api/CustomDataApiClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {
ConfigApi,
createApiRef,
DiscoveryApi,
} from '@backstage/core-plugin-api';
import { TechRadarLoaderResponse } from '@backstage/plugin-tech-radar';
import { QuickAccessLinks } from '../types/types';

const DEFAULT_PROXY_PATH = '/developer-hub';

export interface CustomDataApi {
getHomeDataJson(): Promise<QuickAccessLinks[]>;
getTechRadarDataJson(): Promise<TechRadarLoaderResponse>;
}

export const customDataApiRef = createApiRef<CustomDataApi>({
id: 'app.developer-hub.service',
});

export type Options = {
discoveryApi: DiscoveryApi;
configApi: ConfigApi;
};

export class CustomDataApiClient implements CustomDataApi {
private readonly discoveryApi: DiscoveryApi;
private readonly configApi: ConfigApi;

constructor(options: Options) {
this.discoveryApi = options.discoveryApi;
this.configApi = options.configApi;
}

private async getBaseUrl() {
const proxyPath =
this.configApi.getOptionalString('developerHub.proxyPath') ||
DEFAULT_PROXY_PATH;
return `${await this.discoveryApi.getBaseUrl('proxy')}${proxyPath}`;
}

private async fetcher(url: string) {
const response = await fetch(url, {
headers: { 'Content-Type': 'application/json' },
});
if (!response.ok) {
throw new Error(
`failed to fetch data, status ${response.status}: ${response.statusText}`,
);
}
return await response.json();
}

async getHomeDataJson() {
const proxyUrl = await this.getBaseUrl();
const data = await this.fetcher(`${proxyUrl}`);
return data;
}

async getTechRadarDataJson() {
const proxyUrl = await this.getBaseUrl();
const data = await this.fetcher(`${proxyUrl}/tech-radar`);
return data;
}
}
71 changes: 2 additions & 69 deletions packages/app/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,2 @@
import {
ConfigApi,
createApiRef,
DiscoveryApi,
} from '@backstage/core-plugin-api';
import { TechRadarLoaderResponse } from '@backstage/plugin-tech-radar';
import { QuickAccessLinks } from '../types/types';

const DEFAULT_PROXY_PATH = '/developer-hub';

export interface JanusBackstageCustomizeApi {
getHomeDataJson(): Promise<QuickAccessLinks[]>;
getTechRadarDataJson(): Promise<TechRadarLoaderResponse>;
}

export const janusBackstageCustomizeApiRef =
createApiRef<JanusBackstageCustomizeApi>({
id: 'app.developer-hub.service',
});

export type Options = {
discoveryApi: DiscoveryApi;
configApi: ConfigApi;
};

export class JanusBackstageCustomizeApiClient
implements JanusBackstageCustomizeApi
{
// @ts-ignore
private readonly discoveryApi: DiscoveryApi;

private readonly configApi: ConfigApi;

constructor(options: Options) {
this.discoveryApi = options.discoveryApi;
this.configApi = options.configApi;
}

private async getBaseUrl() {
const proxyPath =
this.configApi.getOptionalString('developerHub.proxyPath') ||
DEFAULT_PROXY_PATH;
return `${await this.discoveryApi.getBaseUrl('proxy')}${proxyPath}`;
}

private async fetcher(url: string) {
const response = await fetch(url, {
headers: { 'Content-Type': 'application/json' },
});
if (!response.ok) {
throw new Error(
`failed to fetch data, status ${response.status}: ${response.statusText}`,
);
}
return await response.json();
}

async getHomeDataJson() {
const proxyUrl = await this.getBaseUrl();
const data = await this.fetcher(`${proxyUrl}`);
return data;
}

async getTechRadarDataJson() {
const proxyUrl = await this.getBaseUrl();
const data = await this.fetcher(`${proxyUrl}/tech-radar`);
return data;
}
}
export * from './AuthApiRefs';
export * from './CustomDataApiClient';
85 changes: 76 additions & 9 deletions packages/app/src/apis.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { OAuth2 } from '@backstage/core-app-api';
import {
AnyApiFactory,
analyticsApiRef,
configApiRef,
createApiFactory,
discoveryApiRef,
identityApiRef,
oauthRequestApiRef,
} from '@backstage/core-plugin-api';
import {
ScmAuth,
Expand All @@ -13,11 +15,16 @@ import {
} from '@backstage/integration-react';
import { techRadarApiRef } from '@backstage/plugin-tech-radar';
import { SegmentAnalytics } from '@janus-idp/backstage-plugin-analytics-provider-segment';
import { CustomTechRadar } from './lib/CustomTechRadar';
import {
JanusBackstageCustomizeApiClient,
janusBackstageCustomizeApiRef,
} from './api';
auth0AuthApiRef,
oidcAuthApiRef,
samlAuthApiRef,
} from './api/AuthApiRefs';
import {
CustomDataApiClient,
customDataApiRef,
} from './api/CustomDataApiClient';
import { CustomTechRadar } from './lib/CustomTechRadar';

export const apis: AnyApiFactory[] = [
createApiFactory({
Expand All @@ -33,20 +40,80 @@ export const apis: AnyApiFactory[] = [
SegmentAnalytics.fromConfig(configApi, identityApi),
}),
createApiFactory({
api: janusBackstageCustomizeApiRef,
api: customDataApiRef,
deps: {
discoveryApi: discoveryApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, configApi }) =>
new JanusBackstageCustomizeApiClient({ discoveryApi, configApi }),
new CustomDataApiClient({ discoveryApi, configApi }),
}),
createApiFactory({
api: techRadarApiRef,
deps: {
janusBackstageCustomizeApi: janusBackstageCustomizeApiRef,
customDataApi: customDataApiRef,
},
factory: ({ customDataApi }) => new CustomTechRadar({ customDataApi }),
}),
// OIDC
createApiFactory({
api: oidcAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OAuth2.create({
discoveryApi,
oauthRequestApi,
provider: {
id: 'oidc',
title: 'OIDC',
icon: () => null,
},
environment: configApi.getOptionalString('auth.environment'),
}),
}),
// Auth0
createApiFactory({
api: auth0AuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OAuth2.create({
discoveryApi,
oauthRequestApi,
provider: {
id: 'auth0',
title: 'Auth0',
icon: () => null,
},
defaultScopes: ['openid', 'email', 'profile'],
environment: configApi.getOptionalString('auth.environment'),
}),
}),
// SAML
createApiFactory({
api: samlAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ janusBackstageCustomizeApi }) =>
new CustomTechRadar({ janusBackstageCustomizeApi }),
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OAuth2.create({
discoveryApi,
oauthRequestApi,
provider: {
id: 'saml',
title: 'SAML',
icon: () => null,
},
environment: configApi.getOptionalString('auth.environment'),
}),
}),
];
32 changes: 3 additions & 29 deletions packages/app/src/components/DynamicRoot/defaultAppComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,9 @@
import { ProxiedSignInPage, SignInPage } from '@backstage/core-components';
import {
AppComponents,
configApiRef,
githubAuthApiRef,
useApi,
} from '@backstage/core-plugin-api';
import { AppComponents } from '@backstage/core-plugin-api';
import React from 'react';
import { SignInPage } from '../SignInPage/SignInPage';

const defaultAppComponents: Partial<AppComponents> = {
SignInPage: props => {
const configApi = useApi(configApiRef);
if (configApi.getString('auth.environment') === 'development') {
return (
<SignInPage
{...props}
title="Select a sign-in method"
align="center"
providers={[
'guest',
{
id: 'github-auth-provider',
title: 'GitHub',
message: 'Sign in using GitHub',
apiRef: githubAuthApiRef,
},
]}
/>
);
}
return <ProxiedSignInPage {...props} provider="oauth2Proxy" />;
},
SignInPage: props => <SignInPage {...props} />,
};

export default defaultAppComponents;
Loading

0 comments on commit aa42a3d

Please sign in to comment.