create auth error api ref
Signed-off-by: Stephen Glass <stephen@stephen.glass>
This commit is contained in:
@@ -35,6 +35,7 @@ import {
|
||||
createFetchApi,
|
||||
FetchMiddlewares,
|
||||
VMwareCloudAuth,
|
||||
SignInAuthErrorApi,
|
||||
} from '@backstage/core-app-api';
|
||||
|
||||
import {
|
||||
@@ -58,6 +59,7 @@ import {
|
||||
bitbucketServerAuthApiRef,
|
||||
atlassianAuthApiRef,
|
||||
vmwareCloudAuthApiRef,
|
||||
authErrorApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import {
|
||||
permissionApiRef,
|
||||
@@ -287,4 +289,11 @@ export const apis = [
|
||||
factory: ({ config, discovery, identity }) =>
|
||||
IdentityPermissionApi.create({ config, discovery, identity }),
|
||||
}),
|
||||
createApiFactory({
|
||||
api: authErrorApiRef,
|
||||
deps: {
|
||||
discovery: discoveryApiRef,
|
||||
},
|
||||
factory: ({ discovery }) => SignInAuthErrorApi.create({ discovery }),
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2021 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 { DiscoveryApi, AuthErrorApi } from '@backstage/core-plugin-api';
|
||||
import { deserializeError } from '@backstage/errors';
|
||||
|
||||
/**
|
||||
* The default implementation of the AuthErrorApi, which simply calls auth error endpoint.
|
||||
* @public
|
||||
*/
|
||||
export class SignInAuthErrorApi implements AuthErrorApi {
|
||||
private constructor(private readonly discoveryApi: DiscoveryApi) {}
|
||||
|
||||
static create(options: { discovery: DiscoveryApi }) {
|
||||
const { discovery } = options;
|
||||
return new SignInAuthErrorApi(discovery);
|
||||
}
|
||||
|
||||
async getSignInAuthError(): Promise<Error | undefined> {
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl('auth');
|
||||
const response = await fetch(`${baseUrl}/.backstage/error`, {
|
||||
credentials: 'include',
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
return data ? deserializeError(data) : undefined;
|
||||
}
|
||||
}
|
||||
+1
-13
@@ -13,17 +13,5 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { DiscoveryApi } from '@backstage/core-plugin-api';
|
||||
import { deserializeError } from '@backstage/errors';
|
||||
|
||||
export async function getSignInAuthError(
|
||||
discoveryApi: DiscoveryApi,
|
||||
): Promise<Error | undefined> {
|
||||
const baseUrl = await discoveryApi.getBaseUrl('auth');
|
||||
const response = await fetch(`${baseUrl}/.backstage/error`, {
|
||||
credentials: 'include',
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
return data ? deserializeError(data) : undefined;
|
||||
}
|
||||
export { SignInAuthErrorApi } from './SignInAuthErrorApi';
|
||||
@@ -175,10 +175,6 @@ export default class MicrosoftAuth {
|
||||
return this.microsoftGraph().signOut();
|
||||
}
|
||||
|
||||
getSignInAuthError() {
|
||||
return this.microsoftGraph().getSignInAuthError();
|
||||
}
|
||||
|
||||
sessionState$() {
|
||||
return this.microsoftGraph().sessionState$();
|
||||
}
|
||||
|
||||
@@ -31,12 +31,10 @@ import {
|
||||
SessionApi,
|
||||
BackstageIdentityApi,
|
||||
BackstageUserIdentity,
|
||||
DiscoveryApi,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { Observable } from '@backstage/types';
|
||||
import { OAuth2Session } from './types';
|
||||
import { OAuthApiCreateOptions } from '../types';
|
||||
import { getSignInAuthError } from '../../../../lib';
|
||||
|
||||
/**
|
||||
* OAuth2 create options.
|
||||
@@ -154,21 +152,18 @@ export default class OAuth2
|
||||
},
|
||||
});
|
||||
|
||||
return new OAuth2({ sessionManager, scopeTransform, discoveryApi });
|
||||
return new OAuth2({ sessionManager, scopeTransform });
|
||||
}
|
||||
|
||||
private readonly sessionManager: SessionManager<OAuth2Session>;
|
||||
private readonly scopeTransform: (scopes: string[]) => string[];
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
|
||||
private constructor(options: {
|
||||
sessionManager: SessionManager<OAuth2Session>;
|
||||
scopeTransform: (scopes: string[]) => string[];
|
||||
discoveryApi: DiscoveryApi;
|
||||
}) {
|
||||
this.sessionManager = options.sessionManager;
|
||||
this.scopeTransform = options.scopeTransform;
|
||||
this.discoveryApi = options.discoveryApi;
|
||||
}
|
||||
|
||||
async signIn() {
|
||||
@@ -229,8 +224,4 @@ export default class OAuth2
|
||||
|
||||
return new Set(scopeTransform(scopeList));
|
||||
}
|
||||
|
||||
async getSignInAuthError() {
|
||||
return getSignInAuthError(this.discoveryApi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import {
|
||||
SessionApi,
|
||||
SessionState,
|
||||
BackstageIdentityResponse,
|
||||
DiscoveryApi,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { Observable } from '@backstage/types';
|
||||
import { DirectAuthConnector } from '../../../../lib/AuthConnector';
|
||||
@@ -33,7 +32,6 @@ import {
|
||||
import { SessionManager } from '../../../../lib/AuthSessionManager/types';
|
||||
import { AuthApiCreateOptions } from '../types';
|
||||
import { SamlSession, samlSessionSchema } from './types';
|
||||
import { getSignInAuthError } from '../../../../lib';
|
||||
|
||||
export type SamlAuthResponse = {
|
||||
profile: ProfileInfo;
|
||||
@@ -77,7 +75,7 @@ export default class SamlAuth
|
||||
schema: samlSessionSchema,
|
||||
});
|
||||
|
||||
return new SamlAuth(authSessionStore, discoveryApi);
|
||||
return new SamlAuth(authSessionStore);
|
||||
}
|
||||
|
||||
sessionState$(): Observable<SessionState> {
|
||||
@@ -86,7 +84,6 @@ export default class SamlAuth
|
||||
|
||||
private constructor(
|
||||
private readonly sessionManager: SessionManager<SamlSession>,
|
||||
private readonly discoveryApi: DiscoveryApi,
|
||||
) {}
|
||||
|
||||
async signIn() {
|
||||
@@ -107,8 +104,4 @@ export default class SamlAuth
|
||||
const session = await this.sessionManager.getSession(options);
|
||||
return session?.profile;
|
||||
}
|
||||
|
||||
async getSignInAuthError() {
|
||||
return getSignInAuthError(this.discoveryApi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,3 +30,4 @@ export * from './FeatureFlagsApi';
|
||||
export * from './FetchApi';
|
||||
export * from './OAuthRequestApi';
|
||||
export * from './StorageApi';
|
||||
export * from './AuthErrorApi';
|
||||
|
||||
@@ -16,6 +16,5 @@
|
||||
|
||||
export * from './subjects';
|
||||
export * from './loginPopup';
|
||||
export * from './signInAuthError';
|
||||
export * from './AuthConnector';
|
||||
export * from './AuthSessionManager';
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
configApiRef,
|
||||
SignInPageProps,
|
||||
useApi,
|
||||
authErrorApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { UserIdentity } from './UserIdentity';
|
||||
import Button from '@material-ui/core/Button';
|
||||
@@ -98,6 +99,7 @@ export const SingleSignInPage = ({
|
||||
const classes = useStyles();
|
||||
const authApi = useApi(provider.apiRef);
|
||||
const configApi = useApi(configApiRef);
|
||||
const authErrorApi = useApi(authErrorApiRef);
|
||||
const { t } = useTranslationRef(coreComponentsTranslationRef);
|
||||
|
||||
const [error, setError] = useState<Error>();
|
||||
@@ -155,9 +157,9 @@ export const SingleSignInPage = ({
|
||||
}
|
||||
};
|
||||
|
||||
const [_state, actions] = useAsync(async () => {
|
||||
const [_, { execute }] = useAsync(async () => {
|
||||
if (searchParams.get('error') !== 'false') {
|
||||
const errorResponse = await authApi.getSignInAuthError();
|
||||
const errorResponse = await authErrorApi.getSignInAuthError();
|
||||
if (errorResponse) {
|
||||
setError(errorResponse);
|
||||
}
|
||||
@@ -165,7 +167,7 @@ export const SingleSignInPage = ({
|
||||
});
|
||||
|
||||
useMountEffect(() => {
|
||||
actions.execute();
|
||||
execute();
|
||||
login({ checkExisting: true });
|
||||
});
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
useApiHolder,
|
||||
errorApiRef,
|
||||
IdentityApi,
|
||||
authErrorApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import {
|
||||
IdentityProviders,
|
||||
@@ -31,6 +32,8 @@ import { commonProvider } from './commonProvider';
|
||||
import { guestProvider } from './guestProvider';
|
||||
import { customProvider } from './customProvider';
|
||||
import { IdentityApiSignOutProxy } from './IdentityApiSignOutProxy';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useMountEffect, useAsync } from '@react-hookz/web';
|
||||
|
||||
const PROVIDER_STORAGE_KEY = '@backstage/core:SignInPage:provider';
|
||||
|
||||
@@ -86,8 +89,22 @@ export const useSignInProviders = (
|
||||
) => {
|
||||
const errorApi = useApi(errorApiRef);
|
||||
const apiHolder = useApiHolder();
|
||||
const authErrorApi = useApi(authErrorApiRef);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const [searchParams, _setSearchParams] = useSearchParams();
|
||||
|
||||
const [_, { execute }] = useAsync(async () => {
|
||||
if (searchParams.get('error') !== 'false') {
|
||||
const errorResponse = await authErrorApi.getSignInAuthError();
|
||||
if (errorResponse) {
|
||||
errorApi.post(errorResponse);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
useMountEffect(execute);
|
||||
|
||||
// This decorates the result with sign out logic from this hook
|
||||
const handleWrappedResult = useCallback(
|
||||
(identityApi: IdentityApi) => {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 { ApiRef, createApiRef } from '../system';
|
||||
|
||||
/**
|
||||
* A wrapper for retrieving any errors caught in authentication redirect flow
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type AuthErrorApi = {
|
||||
/**
|
||||
* Get any caught errors during the auth redirect flow
|
||||
*/
|
||||
getSignInAuthError(): Promise<Error | undefined>;
|
||||
};
|
||||
|
||||
/**
|
||||
* The {@link ApiRef} of {@link AuthErrorApi}.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is a wrapper that uses fetch to retrieve any caught errors
|
||||
* in the authentication redirect flow process. This API calls a
|
||||
* Backstage endpoint to read any error stored in authentication error
|
||||
* cookie and returns it to the user.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const authErrorApiRef: ApiRef<AuthErrorApi> = createApiRef({
|
||||
id: 'core.authError',
|
||||
});
|
||||
@@ -291,11 +291,6 @@ export type SessionApi = {
|
||||
*/
|
||||
signOut(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get any caught errors during the auth redirect flow
|
||||
*/
|
||||
getSignInAuthError(): Promise<Error | undefined>;
|
||||
|
||||
/**
|
||||
* Observe the current state of the auth session. Emits the current state on subscription.
|
||||
*/
|
||||
|
||||
@@ -33,3 +33,4 @@ export * from './FetchApi';
|
||||
export * from './IdentityApi';
|
||||
export * from './OAuthRequestApi';
|
||||
export * from './StorageApi';
|
||||
export * from './AuthErrorApi';
|
||||
|
||||
Reference in New Issue
Block a user