packages/core: rename AuthHelper to AuthConnector

This commit is contained in:
Patrik Oldsberg
2020-05-20 12:12:19 +02:00
parent e6537acc9c
commit eccb7e1cb8
9 changed files with 43 additions and 32 deletions
@@ -15,7 +15,7 @@
*/
import GoogleIcon from '@material-ui/icons/AcUnit';
import { AuthHelper } from '../../lib/AuthHelper';
import { DefaultAuthConnector } from '../../lib/AuthConnector';
import { GoogleSession } from './types';
import {
OAuthApi,
@@ -37,7 +37,7 @@ const SCOPE_PREFIX = 'https://www.googleapis.com/auth/';
class GoogleAuth implements OAuthApi, OpenIdConnectApi {
static create(oauthRequestApi: OAuthRequestApi) {
const helper = new AuthHelper({
const connector = new DefaultAuthConnector({
providerPath: 'google/',
environment: 'dev',
provider: {
@@ -56,7 +56,7 @@ class GoogleAuth implements OAuthApi, OpenIdConnectApi {
});
const sessionManager = new RefreshingAuthSessionManager({
helper,
connector,
defaultScopes: new Set([
'openid',
`${SCOPE_PREFIX}userinfo.email`,
@@ -15,7 +15,7 @@
*/
import ProviderIcon from '@material-ui/icons/AcUnit';
import { AuthHelper } from './AuthHelper';
import { DefaultAuthConnector } from './DefaultAuthConnector';
import MockOAuthApi from '../../OAuthRequestManager/MockOAuthApi';
import * as loginPopup from '../loginPopup';
@@ -37,7 +37,7 @@ const defaultOptions = {
}),
};
describe('AuthHelper', () => {
describe('DefaultAuthConnector', () => {
afterEach(() => {
jest.resetAllMocks();
anyFetch.resetMocks();
@@ -53,7 +53,7 @@ describe('AuthHelper', () => {
}),
);
const helper = new AuthHelper<any>(defaultOptions);
const helper = new DefaultAuthConnector<any>(defaultOptions);
const session = await helper.refreshSession();
expect(session.idToken).toBe('mock-id-token');
expect(session.accessToken).toBe('mock-access-token');
@@ -65,7 +65,7 @@ describe('AuthHelper', () => {
it('should handle failure to refresh session', async () => {
anyFetch.mockRejectOnce(new Error('Network NOPE'));
const helper = new AuthHelper(defaultOptions);
const helper = new DefaultAuthConnector(defaultOptions);
await expect(helper.refreshSession()).rejects.toThrow(
'Auth refresh request failed, Error: Network NOPE',
);
@@ -74,7 +74,7 @@ describe('AuthHelper', () => {
it('should handle failure response when refreshing session', async () => {
anyFetch.mockResponseOnce({}, { status: 401, statusText: 'NOPE' });
const helper = new AuthHelper(defaultOptions);
const helper = new DefaultAuthConnector(defaultOptions);
await expect(helper.refreshSession()).rejects.toThrow(
'Auth refresh request failed with status NOPE',
);
@@ -82,7 +82,7 @@ describe('AuthHelper', () => {
it('should fail if popup was rejected', async () => {
const mockOauth = new MockOAuthApi();
const helper = new AuthHelper({
const helper = new DefaultAuthConnector({
...defaultOptions,
oauthRequestApi: mockOauth,
});
@@ -101,7 +101,7 @@ describe('AuthHelper', () => {
scopes: 'a b',
expiresInSeconds: 3600,
});
const helper = new AuthHelper({
const helper = new DefaultAuthConnector({
...defaultOptions,
oauthRequestApi: mockOauth,
});
@@ -17,6 +17,7 @@
import { AuthRequester } from '../../..';
import { OAuthRequestApi, AuthProvider } from '../../../definitions';
import { showLoginPopup } from '../loginPopup';
import { AuthConnector } from './types';
const DEFAULT_BASE_PATH = '/api/auth/';
@@ -30,7 +31,13 @@ type Options<AuthSession> = {
sessionTransform?(response: any): AuthSession | Promise<AuthSession>;
};
export class AuthHelper<AuthSession> implements AuthHelper<AuthSession> {
/**
* DefaultAuthConnector is the default auth connector in Backstage. It talks to the
* backend auth plugin through the standardized API, and requests user permission
* via the OAuthRequestApi.
*/
export class DefaultAuthConnector<AuthSession>
implements AuthConnector<AuthSession> {
private readonly apiOrigin: string;
private readonly basePath: string;
private readonly providerPath: string;
@@ -14,11 +14,11 @@
* limitations under the License.
*/
import MockAuthHelper, { mockAccessToken } from './MockAuthHelper';
import { MockAuthConnector, mockAccessToken } from './MockAuthConnector';
describe('MockAuthHelper', () => {
describe('MockAuthConnector', () => {
it('should return mock tokens', async () => {
const helper = new MockAuthHelper();
const helper = new MockAuthConnector();
await expect(helper.createSession()).resolves.toEqual({
accessToken: mockAccessToken,
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { GenericAuthHelper } from './types';
import { AuthConnector } from './types';
export const mockAccessToken = 'mock-access-token';
@@ -30,7 +30,7 @@ const defaultMockSession: MockSession = {
scopes: 'profile email',
};
export default class MockAuthHelper implements GenericAuthHelper<MockSession> {
export class MockAuthConnector implements AuthConnector<MockSession> {
constructor(private readonly mockSession: MockSession = defaultMockSession) {}
async refreshSession() {
@@ -14,5 +14,5 @@
* limitations under the License.
*/
export { AuthHelper } from './AuthHelper';
export { DefaultAuthConnector } from './DefaultAuthConnector';
export * from './types';
@@ -19,7 +19,11 @@ export type BaseAuthSession = {
expiresAt: Date;
};
export type GenericAuthHelper<AuthSession> = {
/**
* An AuthConnector is responsible for realizing auth session actions
* by for example communicating with a backend or interacting with the user.
*/
export type AuthConnector<AuthSession> = {
refreshSession(): Promise<AuthSession>;
removeSession(): Promise<void>;
createSession(scopes: Set<string>): Promise<AuthSession>;
@@ -24,7 +24,7 @@ describe('RefreshingAuthSessionManager', () => {
const createSession = jest.fn().mockResolvedValue({ expiresAt: theFuture });
const refreshSession = jest.fn().mockRejectedValue(new Error('NOPE'));
const manager = new RefreshingAuthSessionManager({
helper: { createSession, refreshSession },
connector: { createSession, refreshSession },
} as any);
await manager.getSession({});
@@ -40,7 +40,7 @@ describe('RefreshingAuthSessionManager', () => {
const createSession = jest.fn();
const refreshSession = jest.fn().mockRejectedValue(new Error('NOPE'));
const manager = new RefreshingAuthSessionManager({
helper: { createSession, refreshSession },
connector: { createSession, refreshSession },
} as any);
createSession.mockResolvedValue({
@@ -64,7 +64,7 @@ describe('RefreshingAuthSessionManager', () => {
.mockRejectedValueOnce(new Error('NOPE'))
.mockResolvedValue({ scopes: new Set(['a']) });
const manager = new RefreshingAuthSessionManager({
helper: { createSession, refreshSession },
connector: { createSession, refreshSession },
} as any);
createSession.mockResolvedValue({
@@ -85,7 +85,7 @@ describe('RefreshingAuthSessionManager', () => {
const createSession = jest.fn();
const refreshSession = jest.fn().mockRejectedValue(new Error('NOPE'));
const manager = new RefreshingAuthSessionManager({
helper: { createSession, refreshSession },
connector: { createSession, refreshSession },
} as any);
createSession.mockRejectedValueOnce(new Error('some error'));
@@ -98,7 +98,7 @@ describe('RefreshingAuthSessionManager', () => {
const createSession = jest.fn();
const refreshSession = jest.fn().mockRejectedValue(new Error('NOPE'));
const manager = new RefreshingAuthSessionManager({
helper: { createSession, refreshSession },
connector: { createSession, refreshSession },
} as any);
expect(await manager.getSession({ optional: true })).toBe(undefined);
@@ -118,7 +118,7 @@ describe('RefreshingAuthSessionManager', () => {
const removeSession = jest.fn();
const manager = new RefreshingAuthSessionManager({
helper: { removeSession },
connector: { removeSession },
} as any);
await manager.removeSession();
@@ -16,10 +16,10 @@
import { hasScopes } from '../../OAuthRequestManager/OAuthPendingRequests';
import { SessionManager } from './types';
import { BaseAuthSession, GenericAuthHelper } from '../AuthHelper';
import { BaseAuthSession, AuthConnector } from '../AuthConnector';
type Options<AuthSession extends BaseAuthSession> = {
helper: GenericAuthHelper<AuthSession>;
connector: AuthConnector<AuthSession>;
defaultScopes?: Set<string>;
};
@@ -29,16 +29,16 @@ type Options<AuthSession extends BaseAuthSession> = {
*/
export class RefreshingAuthSessionManager<AuthSession extends BaseAuthSession>
implements SessionManager<AuthSession> {
private readonly helper: GenericAuthHelper<AuthSession>;
private readonly connector: AuthConnector<AuthSession>;
private readonly defaultScopes?: Set<string>;
private refreshPromise?: Promise<AuthSession>;
private currentSession: AuthSession | undefined;
constructor(options: Options<AuthSession>) {
const { helper, defaultScopes = new Set() } = options;
const { connector, defaultScopes = new Set() } = options;
this.helper = helper;
this.connector = connector;
this.defaultScopes = defaultScopes;
}
@@ -92,14 +92,14 @@ export class RefreshingAuthSessionManager<AuthSession extends BaseAuthSession>
}
// We can call authRequester multiple times, the returned session will contain all requested scopes.
this.currentSession = await this.helper.createSession(
this.currentSession = await this.connector.createSession(
this.getExtendedScope(options.scope),
);
return this.currentSession;
}
async removeSession() {
await this.helper.removeSession();
await this.connector.removeSession();
window.location.reload(); // TODO(Rugvip): make this work without reload?
}
@@ -141,7 +141,7 @@ export class RefreshingAuthSessionManager<AuthSession extends BaseAuthSession>
return this.refreshPromise;
}
this.refreshPromise = this.helper.refreshSession();
this.refreshPromise = this.connector.refreshSession();
try {
return await this.refreshPromise;