Fix line endings

This commit is contained in:
Ryan Manny
2021-02-10 10:40:44 -08:00
parent 1deb311410
commit 9f740b443d
2 changed files with 426 additions and 426 deletions
+225 -225
View File
@@ -1,225 +1,225 @@
/*
* Copyright 2020 Spotify AB
*
* 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 {
alertApiRef,
errorApiRef,
AlertApiForwarder,
ErrorApiForwarder,
ErrorAlerter,
discoveryApiRef,
GoogleAuth,
GithubAuth,
OAuth2,
OktaAuth,
GitlabAuth,
Auth0Auth,
MicrosoftAuth,
oauthRequestApiRef,
OAuthRequestManager,
googleAuthApiRef,
githubAuthApiRef,
oauth2ApiRef,
oktaAuthApiRef,
gitlabAuthApiRef,
auth0AuthApiRef,
microsoftAuthApiRef,
storageApiRef,
WebStorage,
createApiFactory,
configApiRef,
UrlPatternDiscovery,
samlAuthApiRef,
SamlAuth,
oneloginAuthApiRef,
OneLoginAuth,
oidcAuthApiRef,
} from '@backstage/core-api';
import OAuth2Icon from '@material-ui/icons/AcUnit';
export const defaultApis = [
createApiFactory({
api: discoveryApiRef,
deps: { configApi: configApiRef },
factory: ({ configApi }) =>
UrlPatternDiscovery.compile(
`${configApi.getString('backend.baseUrl')}/api/{{ pluginId }}`,
),
}),
createApiFactory(alertApiRef, new AlertApiForwarder()),
createApiFactory({
api: errorApiRef,
deps: { alertApi: alertApiRef },
factory: ({ alertApi }) =>
new ErrorAlerter(alertApi, new ErrorApiForwarder()),
}),
createApiFactory({
api: storageApiRef,
deps: { errorApi: errorApiRef },
factory: ({ errorApi }) => WebStorage.create({ errorApi }),
}),
createApiFactory(oauthRequestApiRef, new OAuthRequestManager()),
createApiFactory({
api: googleAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
GoogleAuth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: microsoftAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
MicrosoftAuth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: githubAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
GithubAuth.create({
discoveryApi,
oauthRequestApi,
defaultScopes: ['read:user'],
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: oktaAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OktaAuth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: gitlabAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
GitlabAuth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: auth0AuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
Auth0Auth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: oauth2ApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OAuth2.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: samlAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, configApi }) =>
SamlAuth.create({
discoveryApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: oneloginAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OneLoginAuth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: oidcAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OAuth2.create({
discoveryApi,
oauthRequestApi,
provider: {
id: 'oidc',
title: 'Your Identity Provider',
icon: OAuth2Icon,
},
defaultScopes: [
'openid',
'offline_access',
'email',
],
environment: configApi.getOptionalString('auth.environment'),
}),
}),
];
/*
* Copyright 2020 Spotify AB
*
* 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 {
alertApiRef,
errorApiRef,
AlertApiForwarder,
ErrorApiForwarder,
ErrorAlerter,
discoveryApiRef,
GoogleAuth,
GithubAuth,
OAuth2,
OktaAuth,
GitlabAuth,
Auth0Auth,
MicrosoftAuth,
oauthRequestApiRef,
OAuthRequestManager,
googleAuthApiRef,
githubAuthApiRef,
oauth2ApiRef,
oktaAuthApiRef,
gitlabAuthApiRef,
auth0AuthApiRef,
microsoftAuthApiRef,
storageApiRef,
WebStorage,
createApiFactory,
configApiRef,
UrlPatternDiscovery,
samlAuthApiRef,
SamlAuth,
oneloginAuthApiRef,
OneLoginAuth,
oidcAuthApiRef,
} from '@backstage/core-api';
import OAuth2Icon from '@material-ui/icons/AcUnit';
export const defaultApis = [
createApiFactory({
api: discoveryApiRef,
deps: { configApi: configApiRef },
factory: ({ configApi }) =>
UrlPatternDiscovery.compile(
`${configApi.getString('backend.baseUrl')}/api/{{ pluginId }}`,
),
}),
createApiFactory(alertApiRef, new AlertApiForwarder()),
createApiFactory({
api: errorApiRef,
deps: { alertApi: alertApiRef },
factory: ({ alertApi }) =>
new ErrorAlerter(alertApi, new ErrorApiForwarder()),
}),
createApiFactory({
api: storageApiRef,
deps: { errorApi: errorApiRef },
factory: ({ errorApi }) => WebStorage.create({ errorApi }),
}),
createApiFactory(oauthRequestApiRef, new OAuthRequestManager()),
createApiFactory({
api: googleAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
GoogleAuth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: microsoftAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
MicrosoftAuth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: githubAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
GithubAuth.create({
discoveryApi,
oauthRequestApi,
defaultScopes: ['read:user'],
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: oktaAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OktaAuth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: gitlabAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
GitlabAuth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: auth0AuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
Auth0Auth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: oauth2ApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OAuth2.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: samlAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, configApi }) =>
SamlAuth.create({
discoveryApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: oneloginAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OneLoginAuth.create({
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
}),
}),
createApiFactory({
api: oidcAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OAuth2.create({
discoveryApi,
oauthRequestApi,
provider: {
id: 'oidc',
title: 'Your Identity Provider',
icon: OAuth2Icon,
},
defaultScopes: [
'openid',
'offline_access',
'email',
],
environment: configApi.getOptionalString('auth.environment'),
}),
}),
];
@@ -1,201 +1,201 @@
/*
* Copyright 2020 Spotify AB
*
* 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 express from 'express';
import {
Issuer,
Client,
Strategy as OidcStrategy,
TokenSet,
UserinfoResponse,
} from 'openid-client';
import {
OAuthAdapter,
OAuthProviderOptions,
OAuthHandlers,
OAuthResponse,
OAuthEnvironmentHandler,
OAuthStartRequest,
encodeState,
OAuthRefreshRequest,
} from '../../lib/oauth';
import {
executeFrameHandlerStrategy,
executeRedirectStrategy,
PassportDoneCallback,
} from '../../lib/passport';
import { RedirectInfo, AuthProviderFactory, ProfileInfo } from '../types';
type PrivateInfo = {
refreshToken: string;
};
type OidcImpl = {
strategy: OidcStrategy<UserinfoResponse, Client>;
client: Client;
};
export type OidcAuthProviderOptions = OAuthProviderOptions & {
metadataUrl: string;
tokenSignedResponseAlg?: string;
};
export class OidcAuthProvider implements OAuthHandlers {
private readonly implementation: Promise<OidcImpl>;
constructor(options: OidcAuthProviderOptions) {
this.implementation = this.setupStrategy(options);
}
async start(req: OAuthStartRequest): Promise<RedirectInfo> {
const { strategy } = await this.implementation;
return await executeRedirectStrategy(req, strategy, {
accessType: 'offline',
prompt: 'none',
scope: req.scope,
state: encodeState(req.state),
});
}
async handler(
req: express.Request,
): Promise<{ response: OAuthResponse; refreshToken: string }> {
const { strategy } = await this.implementation;
const { response, privateInfo } = await executeFrameHandlerStrategy<
OAuthResponse,
PrivateInfo
>(req, strategy);
return {
response: await this.populateIdentity(response),
refreshToken: privateInfo.refreshToken,
};
}
async refresh(req: OAuthRefreshRequest): Promise<OAuthResponse> {
const { client } = await this.implementation;
const tokenset = await client.refresh(req.refreshToken);
if (!tokenset.access_token) {
throw new Error('Refresh failed');
}
const profile = await client.userinfo(tokenset.access_token);
return this.populateIdentity({
providerInfo: {
accessToken: tokenset.access_token,
refreshToken: tokenset.refresh_token,
expiresInSeconds: tokenset.expires_in,
idToken: tokenset.id_token,
scope: tokenset.scope || '',
},
profile,
});
}
private async setupStrategy(
options: OidcAuthProviderOptions,
): Promise<OidcImpl> {
const issuer = await Issuer.discover(options.metadataUrl);
const client = new issuer.Client({
client_id: options.clientId,
client_secret: options.clientSecret,
redirect_uris: [options.callbackUrl],
response_types: ['code'],
id_token_signed_response_alg: options.tokenSignedResponseAlg || 'RS256',
});
const strategy = new OidcStrategy(
{
client,
passReqToCallback: false as true,
},
(
tokenset: TokenSet,
userinfo: UserinfoResponse,
done: PassportDoneCallback<OAuthResponse, PrivateInfo>,
) => {
const profile: ProfileInfo = {
displayName: userinfo.name,
email: userinfo.email,
picture: userinfo.picture,
};
done(
undefined,
{
providerInfo: {
idToken: tokenset.id_token || '',
accessToken: tokenset.access_token || '',
scope: tokenset.scope || '',
expiresInSeconds: tokenset.expires_in,
},
profile,
},
{
refreshToken: tokenset.refresh_token || '',
},
);
},
);
strategy.error = console.error;
return { strategy, client };
}
// Use this function to grab the user profile info from the token
// Then populate the profile with it
private async populateIdentity(
response: OAuthResponse,
): Promise<OAuthResponse> {
const { profile } = response;
if (!profile.email) {
throw new Error('Profile does not contain an email');
}
const id = profile.email.split('@')[0];
return { ...response, backstageIdentity: { id } };
}
}
export const createOidcProvider: AuthProviderFactory = ({
providerId,
globalConfig,
config,
tokenIssuer,
}) =>
OAuthEnvironmentHandler.mapConfig(config, envConfig => {
const clientId = envConfig.getString('clientId');
const clientSecret = envConfig.getString('clientSecret');
const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
const metadataUrl = envConfig.getString('metadataUrl');
const tokenSignedResponseAlg = envConfig.getString(
'tokenSignedResponseAlg',
);
const provider = new OidcAuthProvider({
clientId,
clientSecret,
callbackUrl,
tokenSignedResponseAlg,
metadataUrl,
});
return OAuthAdapter.fromConfig(globalConfig, provider, {
disableRefresh: false,
providerId,
tokenIssuer,
});
});
/*
* Copyright 2020 Spotify AB
*
* 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 express from 'express';
import {
Issuer,
Client,
Strategy as OidcStrategy,
TokenSet,
UserinfoResponse,
} from 'openid-client';
import {
OAuthAdapter,
OAuthProviderOptions,
OAuthHandlers,
OAuthResponse,
OAuthEnvironmentHandler,
OAuthStartRequest,
encodeState,
OAuthRefreshRequest,
} from '../../lib/oauth';
import {
executeFrameHandlerStrategy,
executeRedirectStrategy,
PassportDoneCallback,
} from '../../lib/passport';
import { RedirectInfo, AuthProviderFactory, ProfileInfo } from '../types';
type PrivateInfo = {
refreshToken: string;
};
type OidcImpl = {
strategy: OidcStrategy<UserinfoResponse, Client>;
client: Client;
};
export type OidcAuthProviderOptions = OAuthProviderOptions & {
metadataUrl: string;
tokenSignedResponseAlg?: string;
};
export class OidcAuthProvider implements OAuthHandlers {
private readonly implementation: Promise<OidcImpl>;
constructor(options: OidcAuthProviderOptions) {
this.implementation = this.setupStrategy(options);
}
async start(req: OAuthStartRequest): Promise<RedirectInfo> {
const { strategy } = await this.implementation;
return await executeRedirectStrategy(req, strategy, {
accessType: 'offline',
prompt: 'none',
scope: req.scope,
state: encodeState(req.state),
});
}
async handler(
req: express.Request,
): Promise<{ response: OAuthResponse; refreshToken: string }> {
const { strategy } = await this.implementation;
const { response, privateInfo } = await executeFrameHandlerStrategy<
OAuthResponse,
PrivateInfo
>(req, strategy);
return {
response: await this.populateIdentity(response),
refreshToken: privateInfo.refreshToken,
};
}
async refresh(req: OAuthRefreshRequest): Promise<OAuthResponse> {
const { client } = await this.implementation;
const tokenset = await client.refresh(req.refreshToken);
if (!tokenset.access_token) {
throw new Error('Refresh failed');
}
const profile = await client.userinfo(tokenset.access_token);
return this.populateIdentity({
providerInfo: {
accessToken: tokenset.access_token,
refreshToken: tokenset.refresh_token,
expiresInSeconds: tokenset.expires_in,
idToken: tokenset.id_token,
scope: tokenset.scope || '',
},
profile,
});
}
private async setupStrategy(
options: OidcAuthProviderOptions,
): Promise<OidcImpl> {
const issuer = await Issuer.discover(options.metadataUrl);
const client = new issuer.Client({
client_id: options.clientId,
client_secret: options.clientSecret,
redirect_uris: [options.callbackUrl],
response_types: ['code'],
id_token_signed_response_alg: options.tokenSignedResponseAlg || 'RS256',
});
const strategy = new OidcStrategy(
{
client,
passReqToCallback: false as true,
},
(
tokenset: TokenSet,
userinfo: UserinfoResponse,
done: PassportDoneCallback<OAuthResponse, PrivateInfo>,
) => {
const profile: ProfileInfo = {
displayName: userinfo.name,
email: userinfo.email,
picture: userinfo.picture,
};
done(
undefined,
{
providerInfo: {
idToken: tokenset.id_token || '',
accessToken: tokenset.access_token || '',
scope: tokenset.scope || '',
expiresInSeconds: tokenset.expires_in,
},
profile,
},
{
refreshToken: tokenset.refresh_token || '',
},
);
},
);
strategy.error = console.error;
return { strategy, client };
}
// Use this function to grab the user profile info from the token
// Then populate the profile with it
private async populateIdentity(
response: OAuthResponse,
): Promise<OAuthResponse> {
const { profile } = response;
if (!profile.email) {
throw new Error('Profile does not contain an email');
}
const id = profile.email.split('@')[0];
return { ...response, backstageIdentity: { id } };
}
}
export const createOidcProvider: AuthProviderFactory = ({
providerId,
globalConfig,
config,
tokenIssuer,
}) =>
OAuthEnvironmentHandler.mapConfig(config, envConfig => {
const clientId = envConfig.getString('clientId');
const clientSecret = envConfig.getString('clientSecret');
const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
const metadataUrl = envConfig.getString('metadataUrl');
const tokenSignedResponseAlg = envConfig.getString(
'tokenSignedResponseAlg',
);
const provider = new OidcAuthProvider({
clientId,
clientSecret,
callbackUrl,
tokenSignedResponseAlg,
metadataUrl,
});
return OAuthAdapter.fromConfig(globalConfig, provider, {
disableRefresh: false,
providerId,
tokenIssuer,
});
});