Skip to content

Commit

Permalink
Merge pull request #513 from momentohq/rework-auth-client-api
Browse files Browse the repository at this point in the history
feat: clean up and consolidate AuthClient API between web and node.js SDKs
  • Loading branch information
cprice404 authored May 17, 2023
2 parents c508bc6 + d51dcde commit d7b7945
Show file tree
Hide file tree
Showing 25 changed files with 379 additions and 295 deletions.
10 changes: 5 additions & 5 deletions packages/client-sdk-nodejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
},
"scripts": {
"prebuild": "eslint . --ext .ts",
"test": "jest --testPathIgnorePatterns auth.test.ts",
"integration-test-auth": "jest -- auth.test.ts",
"unit-test": "jest unit --testPathIgnorePatterns auth.test.ts",
"integration-test": "jest integration --testPathIgnorePatterns auth.test.ts",
"build-and-run-tests": "cd ../common-integration-tests && npm run build && cd - && jest --testPathIgnorePatterns auth.test.ts",
"test": "jest --testPathIgnorePatterns auth-client.test.ts",
"integration-test-auth": "jest auth-client.test.ts",
"unit-test": "jest unit",
"integration-test": "jest integration --testPathIgnorePatterns auth-client.test.ts",
"build-and-run-tests": "cd ../common-integration-tests && npm run build && cd - && jest --testPathIgnorePatterns auth-client.test.ts",
"lint": "eslint . --ext .ts",
"format": "eslint . --ext .ts --fix",
"watch": "tsc -w",
Expand Down
8 changes: 8 additions & 0 deletions packages/client-sdk-nodejs/src/auth-client-props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {CredentialProvider} from '.';

export interface AuthClientProps {
/**
* controls how the client will get authentication information for connecting to the Momento service
*/
credentialProvider: CredentialProvider;
}
22 changes: 6 additions & 16 deletions packages/client-sdk-nodejs/src/auth-client.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {AuthClient as InternalAuthClient} from './internal/auth-client';
import {InternalAuthClient} from './internal/internal-auth-client';
import {IAuthClient} from '@gomomento/sdk-core/dist/src/internal/clients/auth/IAuthClient';
import {AbstractAuthClient} from '@gomomento/sdk-core/dist/src/internal/clients/auth/AbstractAuthClient';
import {
GenerateAuthToken,
ExpiresIn,
CredentialProvider,
RefreshAuthToken,
} from '@gomomento/sdk-core';
import {AuthClientProps} from './auth-client-props';

export class AuthClient extends AbstractAuthClient implements IAuthClient {
constructor() {
const authClient = new InternalAuthClient();
constructor(props: AuthClientProps) {
const authClient = new InternalAuthClient(props);

super({createAuthClient: () => authClient});
}
Expand All @@ -27,15 +27,9 @@ export class AuthClient extends AbstractAuthClient implements IAuthClient {
* {@link GenerateAuthToken.Error} on failure.
*/
public async generateAuthToken(
controlEndpoint: string,
token: string,
expiresIn: ExpiresIn
): Promise<GenerateAuthToken.Response> {
return await this.authClient.generateAuthToken(
controlEndpoint,
token,
expiresIn
);
return await this.authClient.generateAuthToken(expiresIn);
}

/**
Expand All @@ -48,12 +42,8 @@ export class AuthClient extends AbstractAuthClient implements IAuthClient {
* {@link RefreshAuthToken.Error} on failure.
*/
public async refreshAuthToken(
credentialProvider: CredentialProvider,
refreshToken: string
): Promise<RefreshAuthToken.Response> {
return await this.authClient.refreshAuthToken(
credentialProvider,
refreshToken
);
return await this.authClient.refreshAuthToken(refreshToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,34 @@ import {
RefreshAuthToken,
GenerateAuthToken,
} from '@gomomento/sdk-core/dist/src';
import {IAuthClient} from '@gomomento/sdk-core/dist/src/internal/clients';
import {AuthClientProps} from '../auth-client-props';

export class AuthClient {
export class InternalAuthClient implements IAuthClient {
private static readonly REQUEST_TIMEOUT_MS: number = 60 * 1000;

private readonly creds: CredentialProvider;
private readonly interceptors: Interceptor[];

constructor() {
constructor(props: AuthClientProps) {
this.creds = props.credentialProvider;
const headers = [new Header('Agent', `nodejs:${version}`)];
this.interceptors = [
new HeaderInterceptorProvider(headers).createHeadersInterceptor(),
ClientTimeoutInterceptor(AuthClient.REQUEST_TIMEOUT_MS),
ClientTimeoutInterceptor(InternalAuthClient.REQUEST_TIMEOUT_MS),
];
}

public async generateAuthToken(
controlEndpoint: string,
token: string,
expiresIn: ExpiresIn
): Promise<GenerateAuthToken.Response> {
const authClient = new grpcAuth.AuthClient(
controlEndpoint,
this.creds.getControlEndpoint(),
ChannelCredentials.createSsl()
);

const request = new grpcAuth._GenerateApiTokenRequest({
session_token: token,
session_token: this.creds.getAuthToken(),
});

if (expiresIn.doesExpire()) {
Expand Down Expand Up @@ -81,16 +83,15 @@ export class AuthClient {
}

public async refreshAuthToken(
credentialProvider: CredentialProvider,
refreshToken: string
): Promise<RefreshAuthToken.Response> {
const authClient = new grpcAuth.AuthClient(
credentialProvider.getControlEndpoint(),
this.creds.getControlEndpoint(),
ChannelCredentials.createSsl()
);

const request = new grpcAuth._RefreshApiTokenRequest({
api_key: credentialProvider.getAuthToken(),
api_key: this.creds.getAuthToken(),
refresh_token: refreshToken,
});

Expand Down
116 changes: 0 additions & 116 deletions packages/client-sdk-nodejs/test/integration/auth.test.ts

This file was deleted.

35 changes: 19 additions & 16 deletions packages/client-sdk-nodejs/test/integration/integration-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ function momentoClientForTesting(): CacheClient {
return new CacheClient(IntegrationTestCacheClientProps);
}

function momentoAuthClientForTesting(): AuthClient {
return new AuthClient();
}

function momentoTopicClientForTesting(): TopicClient {
return new TopicClient({
configuration: IntegrationTestCacheClientProps.configuration,
Expand Down Expand Up @@ -98,20 +94,27 @@ export function SetupTopicIntegrationTest(): {
return {topicClient, Momento, IntegrationTestCacheName};
}

export function SetupAuthIntegrationTest(): {
authClient: AuthClient;
sessionToken: string;
controlEndpoint: string;
export function SetupAuthClientIntegrationTest(): {
sessionTokenAuthClient: AuthClient;
authTokenAuthClientFactory: (authToken: string) => AuthClient;
} {
const sessionToken = process.env.TEST_SESSION_TOKEN;
if (sessionToken === undefined) {
throw new Error('Missing required env var TEST_SESSION_TOKEN');
}

return {
authClient: momentoAuthClientForTesting(),
sessionToken: sessionToken,
controlEndpoint: credsProvider.getControlEndpoint(),
sessionTokenAuthClient: new AuthClient({
credentialProvider: CredentialProvider.fromEnvironmentVariable({
environmentVariableName: 'TEST_SESSION_TOKEN',
// session tokens don't include cache/control endpoints, so we must provide them. In this case we just hackily
// steal them from the auth-token-based creds provider.
cacheEndpoint: credsProvider.getCacheEndpoint(),
controlEndpoint: credsProvider.getControlEndpoint(),
}),
}),
authTokenAuthClientFactory: authToken => {
return new AuthClient({
credentialProvider: CredentialProvider.fromString({
authToken: authToken,
}),
});
},
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {SetupAuthClientIntegrationTest} from '../integration-setup';
import {runAuthClientTests} from '@gomomento/common-integration-tests';

const {sessionTokenAuthClient, authTokenAuthClientFactory} =
SetupAuthClientIntegrationTest();

runAuthClientTests(sessionTokenAuthClient, authTokenAuthClientFactory);
7 changes: 4 additions & 3 deletions packages/client-sdk-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
},
"scripts": {
"prebuild": "eslint . --ext .ts",
"test": "jest",
"test": "jest --testPathIgnorePatterns auth-client.test.ts",
"unit-test": "jest unit",
"integration-test": "jest integration",
"build-and-run-tests": "cd ../common-integration-tests && npm run build && cd - && jest",
"integration-test-auth": "jest auth-client.test.ts",
"integration-test": "jest integration --testPathIgnorePatterns auth-client.test.ts",
"build-and-run-tests": "cd ../common-integration-tests && npm run build && cd - && jest --testPathIgnorePatterns auth-client.test.ts",
"lint": "eslint . --ext .ts",
"format": "eslint . --ext .ts --fix",
"watch": "tsc -w",
Expand Down
8 changes: 8 additions & 0 deletions packages/client-sdk-web/src/auth-client-props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {CredentialProvider} from '.';

export interface AuthClientProps {
/**
* controls how the client will get authentication information for connecting to the Momento service
*/
credentialProvider: CredentialProvider;
}
5 changes: 3 additions & 2 deletions packages/client-sdk-web/src/auth-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import {
IAuthClient,
} from '@gomomento/sdk-core/dist/src/internal/clients/index';
import {InternalWebGrpcAuthClient} from './internal/auth-client';
import {AuthClientProps} from './auth-client-props';

export class AuthClient extends AbstractAuthClient {
constructor() {
constructor(props: AuthClientProps) {
const createAuthClient = (): IAuthClient => {
return new InternalWebGrpcAuthClient();
return new InternalWebGrpcAuthClient(props);
};
super({createAuthClient});
}
Expand Down
Loading

0 comments on commit d7b7945

Please sign in to comment.