diff --git a/sdk/communication/communication-chat/README.md b/sdk/communication/communication-chat/README.md index ff452903abb7..bfc5d8d1e913 100644 --- a/sdk/communication/communication-chat/README.md +++ b/sdk/communication/communication-chat/README.md @@ -38,13 +38,13 @@ Use resource url and user access token to initialize chat client. ```JavaScript import { ChatClient } from '@azure/communication-chat'; -import { AzureCommunicationUserCredential } from "@azure/communication-common"; +import { AzureCommunicationTokenCredential } from "@azure/communication-common"; // Your unique Azure Communication service endpoint let endpointUrl = ''; let userAccessToken = ''; -let userCredential = new AzureCommunicationUserCredential(userAccessToken); -let chatClient = new ChatClient(endpointUrl, userCredential); +let tokenCredential = new AzureCommunicationTokenCredential(userAccessToken); +let chatClient = new ChatClient(endpointUrl, tokenCredential); ``` diff --git a/sdk/communication/communication-chat/review/communication-chat.api.md b/sdk/communication/communication-chat/review/communication-chat.api.md index 790c3888a158..5f6ecdb11105 100644 --- a/sdk/communication/communication-chat/review/communication-chat.api.md +++ b/sdk/communication/communication-chat/review/communication-chat.api.md @@ -7,8 +7,8 @@ import { ChatMessageDeletedEvent } from '@azure/communication-signaling'; import { ChatMessageEditedEvent } from '@azure/communication-signaling'; import { ChatMessageReceivedEvent } from '@azure/communication-signaling'; +import { CommunicationTokenCredential } from '@azure/communication-common'; import { CommunicationUser } from '@azure/communication-common'; -import { CommunicationUserCredential } from '@azure/communication-common'; import * as coreHttp from '@azure/core-http'; import { HttpResponse } from '@azure/core-http'; import { OperationOptions } from '@azure/core-http'; @@ -27,7 +27,7 @@ export interface AddMembersRequest extends Omit; deleteChatThread(threadId: string, options?: DeleteChatThreadOptions): Promise; getChatThread(threadId: string, options?: GetChatThreadOptions): Promise; @@ -67,7 +67,7 @@ export interface ChatThread extends Omit; deleteMessage(messageId: string, options?: DeleteMessageOptions): Promise; dispose(): void; diff --git a/sdk/communication/communication-chat/src/chatClient.ts b/sdk/communication/communication-chat/src/chatClient.ts index 072c5ecc7759..724fa3c1ccaa 100644 --- a/sdk/communication/communication-chat/src/chatClient.ts +++ b/sdk/communication/communication-chat/src/chatClient.ts @@ -5,7 +5,7 @@ import { logger } from "./models/logger"; import { EventEmitter } from "events"; import { SDK_VERSION } from "./constants"; -import { CommunicationUserCredential } from "@azure/communication-common"; +import { CommunicationTokenCredential } from "@azure/communication-common"; import { SignalingClient, ChatEventId, @@ -16,7 +16,7 @@ import { TypingIndicatorReceivedEvent } from "@azure/communication-signaling"; import { getSignalingClient } from "./signaling/signalingClient"; -import { createCommunicationUserCredentialPolicy } from "./credential/communicationUserCredentialPolicy"; +import { createCommunicationTokenCredentialPolicy } from "./credential/communicationTokenCredentialPolicy"; import { ChatApiClient } from "./generated/src/chatApiClient"; import { InternalPipelineOptions, @@ -50,7 +50,7 @@ export { ChatThreadInfo } from "./generated/src/models"; * The client to do chat operations */ export class ChatClient { - private readonly tokenCredential: CommunicationUserCredential; + private readonly tokenCredential: CommunicationTokenCredential; private readonly clientOptions: ChatClientOptions; private readonly api: ChatApiClient; private readonly signalingClient: SignalingClient | undefined = undefined; @@ -61,12 +61,12 @@ export class ChatClient { * Creates an instance of the ChatClient for a given resource and user. * * @param url The url of the Communication Services resouce. - * @param credential The user credential. Use AzureCommunicationUserCredential from @azure/communication-common to create a credential. + * @param credential The token credential. Use AzureCommunicationTokenCredential from @azure/communication-common to create a credential. * @param options Additional client options. */ constructor( private readonly url: string, - credential: CommunicationUserCredential, + credential: CommunicationTokenCredential, options: ChatClientOptions = {} ) { this.tokenCredential = credential; @@ -94,7 +94,7 @@ export class ChatClient { } }; - const authPolicy = createCommunicationUserCredentialPolicy(this.tokenCredential); + const authPolicy = createCommunicationTokenCredentialPolicy(this.tokenCredential); const pipeline = createPipelineFromOptions(internalPipelineOptions, authPolicy); this.api = new ChatApiClient(this.url, pipeline); diff --git a/sdk/communication/communication-chat/src/chatThreadClient.ts b/sdk/communication/communication-chat/src/chatThreadClient.ts index c7841d8e993f..e7e5dfa81494 100644 --- a/sdk/communication/communication-chat/src/chatThreadClient.ts +++ b/sdk/communication/communication-chat/src/chatThreadClient.ts @@ -3,8 +3,8 @@ import { logger } from "./models/logger"; import { SDK_VERSION } from "./constants"; -import { CommunicationUser, CommunicationUserCredential } from "@azure/communication-common"; -import { createCommunicationUserCredentialPolicy } from "./credential/communicationUserCredentialPolicy"; +import { CommunicationUser, CommunicationTokenCredential } from "@azure/communication-common"; +import { createCommunicationTokenCredentialPolicy } from "./credential/communicationTokenCredentialPolicy"; import { ChatApiClient } from "./generated/src/chatApiClient"; import { InternalPipelineOptions, @@ -61,7 +61,7 @@ export class ChatThreadClient { */ readonly threadId: string; - private readonly tokenCredential: CommunicationUserCredential; + private readonly tokenCredential: CommunicationTokenCredential; private readonly api: ChatApiClient; private disposed = false; @@ -70,7 +70,7 @@ export class ChatThreadClient { constructor( threadId: string, private readonly url: string, - credential: CommunicationUserCredential, + credential: CommunicationTokenCredential, options: ChatThreadClientOptions = {} ) { this.threadId = threadId; @@ -98,7 +98,7 @@ export class ChatThreadClient { } }; - const authPolicy = createCommunicationUserCredentialPolicy(this.tokenCredential); + const authPolicy = createCommunicationTokenCredentialPolicy(this.tokenCredential); const pipeline = createPipelineFromOptions(internalPipelineOptions, authPolicy); this.api = new ChatApiClient(this.url, pipeline); diff --git a/sdk/communication/communication-chat/src/credential/communicationUserCredentialPolicy.ts b/sdk/communication/communication-chat/src/credential/communicationTokenCredentialPolicy.ts similarity index 63% rename from sdk/communication/communication-chat/src/credential/communicationUserCredentialPolicy.ts rename to sdk/communication/communication-chat/src/credential/communicationTokenCredentialPolicy.ts index 45d754c81cf7..2b5cd6c97039 100644 --- a/sdk/communication/communication-chat/src/credential/communicationUserCredentialPolicy.ts +++ b/sdk/communication/communication-chat/src/credential/communicationTokenCredentialPolicy.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { CommunicationUserCredential } from "@azure/communication-common"; +import { CommunicationTokenCredential } from "@azure/communication-common"; import { Constants, HttpOperationResponse, @@ -13,38 +13,38 @@ import { } from "@azure/core-http"; /** - * Creates a new CommunicationUserCredentialPolicy factory. + * Creates a new CommunicationTokenCredentialPolicy factory. * - * @param credential The CommunicationUserCredential implementation that can supply the user credential. + * @param credential The CommunicationTokenCredential implementation that can supply the user credential. */ -export const createCommunicationUserCredentialPolicy = ( - credential: CommunicationUserCredential +export const createCommunicationTokenCredentialPolicy = ( + credential: CommunicationTokenCredential ): RequestPolicyFactory => ({ create: (nextPolicy: RequestPolicy, options: RequestPolicyOptions) => { - return new CommunicationUserCredentialPolicy(nextPolicy, options, credential); + return new CommunicationTokenCredentialPolicy(nextPolicy, options, credential); } }); /** * - * Provides a RequestPolicy that can request a token from a CommunicationUserCredential + * Provides a RequestPolicy that can request a token from a CommunicationTokenCredential * implementation and then apply it to the Authorization header of a request. * * @internal */ -export class CommunicationUserCredentialPolicy extends BaseRequestPolicy { +export class CommunicationTokenCredentialPolicy extends BaseRequestPolicy { /** - * Creates a new CommunicationUserCredentialPolicy object. + * Creates a new CommunicationTokenCredentialPolicy object. * * @param nextPolicy The next RequestPolicy in the request pipeline. * @param options Options for this RequestPolicy. - * @param credential The CommunicationUserCredential implementation that can supply the user credential. - * @param tokenCache The cache for the most recent AccessToken returned from the CommunicationUserCredential. + * @param credential The CommunicationTokenCredential implementation that can supply the user credential. + * @param tokenCache The cache for the most recent AccessToken returned from the CommunicationTokenCredential. */ constructor( nextPolicy: RequestPolicy, options: RequestPolicyOptions, - private readonly credential: CommunicationUserCredential + private readonly credential: CommunicationTokenCredential ) { super(nextPolicy, options); } diff --git a/sdk/communication/communication-chat/src/signaling/signalingClient.browser.ts b/sdk/communication/communication-chat/src/signaling/signalingClient.browser.ts index 05d172c2e788..4063a810ed48 100644 --- a/sdk/communication/communication-chat/src/signaling/signalingClient.browser.ts +++ b/sdk/communication/communication-chat/src/signaling/signalingClient.browser.ts @@ -2,11 +2,11 @@ // Licensed under the MIT license. import { CommunicationSignalingClient, SignalingClient } from "@azure/communication-signaling"; -import { CommunicationUserCredential } from "@azure/communication-common"; +import { CommunicationTokenCredential } from "@azure/communication-common"; import { AzureLogger } from "@azure/logger"; export const getSignalingClient = ( - credential: CommunicationUserCredential, + credential: CommunicationTokenCredential, logger: AzureLogger ): SignalingClient | undefined => { return new CommunicationSignalingClient(credential, logger); diff --git a/sdk/communication/communication-chat/src/signaling/signalingClient.ts b/sdk/communication/communication-chat/src/signaling/signalingClient.ts index 6e6647635dd7..c26fdf756930 100644 --- a/sdk/communication/communication-chat/src/signaling/signalingClient.ts +++ b/sdk/communication/communication-chat/src/signaling/signalingClient.ts @@ -2,11 +2,11 @@ // Licensed under the MIT license. import { SignalingClient } from "@azure/communication-signaling"; -import { CommunicationUserCredential } from "@azure/communication-common"; +import { CommunicationTokenCredential } from "@azure/communication-common"; import { AzureLogger } from "@azure/logger"; export const getSignalingClient = ( - _credential: CommunicationUserCredential, + _credential: CommunicationTokenCredential, _logger: AzureLogger ): SignalingClient | undefined => { return undefined; diff --git a/sdk/communication/communication-chat/test/chatClient.mocked.spec.ts b/sdk/communication/communication-chat/test/chatClient.mocked.spec.ts index 6aca46107643..ea808cccca24 100644 --- a/sdk/communication/communication-chat/test/chatClient.mocked.spec.ts +++ b/sdk/communication/communication-chat/test/chatClient.mocked.spec.ts @@ -7,7 +7,7 @@ import { ChatClient, CreateChatThreadRequest } from "../src"; import * as RestModel from "../src/generated/src/models"; import { apiVersion } from "../src/generated/src/models/parameters"; import { baseUri, generateToken } from "./utils/connectionUtils"; -import { AzureCommunicationUserCredential } from "@azure/communication-common"; +import { AzureCommunicationTokenCredential } from "@azure/communication-common"; import { mockThread, generateHttpClient, @@ -25,7 +25,7 @@ describe("[Mocked] ChatClient", async () => { }); it("can instantiate", async () => { - new ChatClient(baseUri, new AzureCommunicationUserCredential(generateToken())); + new ChatClient(baseUri, new AzureCommunicationTokenCredential(generateToken())); }); it("makes successful create thread request", async () => { diff --git a/sdk/communication/communication-chat/test/chatThreadClient.mocked.spec.ts b/sdk/communication/communication-chat/test/chatThreadClient.mocked.spec.ts index 31ea8c63c58a..5b0afcfcc9d1 100644 --- a/sdk/communication/communication-chat/test/chatThreadClient.mocked.spec.ts +++ b/sdk/communication/communication-chat/test/chatThreadClient.mocked.spec.ts @@ -3,7 +3,7 @@ import sinon from "sinon"; import { assert } from "chai"; -import { AzureCommunicationUserCredential } from "@azure/communication-common"; +import { AzureCommunicationTokenCredential } from "@azure/communication-common"; import { ChatThreadClient, UpdateThreadOptions, @@ -35,7 +35,7 @@ describe("[Mocked] ChatThreadClient", async () => { }); it("can instantiate", async () => { - new ChatThreadClient(threadId, baseUri, new AzureCommunicationUserCredential(generateToken())); + new ChatThreadClient(threadId, baseUri, new AzureCommunicationTokenCredential(generateToken())); }); it("makes successful update thread request", async () => { diff --git a/sdk/communication/communication-chat/test/utils/mockClient.ts b/sdk/communication/communication-chat/test/utils/mockClient.ts index 06314406ae5a..2c612074dcad 100644 --- a/sdk/communication/communication-chat/test/utils/mockClient.ts +++ b/sdk/communication/communication-chat/test/utils/mockClient.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { AzureCommunicationUserCredential } from "@azure/communication-common"; +import { AzureCommunicationTokenCredential } from "@azure/communication-common"; import { HttpClient, HttpHeaders, WebResourceLike, HttpOperationResponse } from "@azure/core-http"; import { ChatClient, ChatThreadMember } from "../../src"; import * as RestModel from "../../src/generated/src/models"; @@ -75,7 +75,7 @@ export const generateHttpClient = (status: number, parsedBody?: any): HttpClient }; export const createChatClient = (mockHttpClient: HttpClient): ChatClient => { - return new ChatClient(baseUri, new AzureCommunicationUserCredential(generateToken()), { + return new ChatClient(baseUri, new AzureCommunicationTokenCredential(generateToken()), { httpClient: mockHttpClient }); }; @@ -87,7 +87,7 @@ export const createChatThreadClient = ( return new ChatThreadClient( threadId, baseUri, - new AzureCommunicationUserCredential(generateToken()), + new AzureCommunicationTokenCredential(generateToken()), { httpClient: mockHttpClient } diff --git a/sdk/communication/communication-chat/test/utils/recordedClient.ts b/sdk/communication/communication-chat/test/utils/recordedClient.ts index f3b9c3da5cbe..f74a83e24a7f 100644 --- a/sdk/communication/communication-chat/test/utils/recordedClient.ts +++ b/sdk/communication/communication-chat/test/utils/recordedClient.ts @@ -9,7 +9,7 @@ import { isNode } from "@azure/core-http"; import { ChatClient } from "../../src"; import { CommunicationUser, - AzureCommunicationUserCredential, + AzureCommunicationTokenCredential, parseClientArguments } from "@azure/communication-common"; import { @@ -64,5 +64,5 @@ export function createChatClient(userToken: string): ChatClient { userToken = generateToken(); } const { url } = parseClientArguments(env.COMMUNICATION_CONNECTION_STRING); - return new ChatClient(url, new AzureCommunicationUserCredential(userToken)); + return new ChatClient(url, new AzureCommunicationTokenCredential(userToken)); } diff --git a/sdk/communication/communication-common/CHANGELOG.md b/sdk/communication/communication-common/CHANGELOG.md index 12000482fba1..d33e380b8ecf 100644 --- a/sdk/communication/communication-common/CHANGELOG.md +++ b/sdk/communication/communication-common/CHANGELOG.md @@ -2,6 +2,9 @@ ## 1.0.0-beta.4 (Unreleased) +### Breaking Changes + +- Renamed `communicationUserCredential` to `communicationTokenCredential`. ## 1.0.0-beta.3 (2020-11-16) diff --git a/sdk/communication/communication-common/README.md b/sdk/communication/communication-common/README.md index 3a662a2c324c..6a65529a63c2 100644 --- a/sdk/communication/communication-common/README.md +++ b/sdk/communication/communication-common/README.md @@ -17,20 +17,20 @@ npm install @azure/communication-common ## Key concepts -### CommunicationUserCredential and AzureCommunicationUserCredential +### CommunicationTokenCredential and AzureCommunicationTokenCredential -A `CommunicationUserCredential` authenticates a user with Communication Services, such as Chat or Calling. It optionally provides an auto-refresh mechanism to ensure a continuously stable authentication state during communications. +A `CommunicationTokenCredential` authenticates a user with Communication Services, such as Chat or Calling. It optionally provides an auto-refresh mechanism to ensure a continuously stable authentication state during communications. -It is up to you the developer to first create valid user tokens with the Azure Communication Administration library. Then you use these tokens to create a `AzureCommunicationUserCredential`. +It is up to you the developer to first create valid user tokens with the Azure Communication Administration library. Then you use these tokens to create a `AzureCommunicationTokenCredential`. -`CommunicationUserCredential` is only the interface, please always use the `AzureCommunicationUserCredential` constructor to create a credential and take advantage of the built-in refresh logic. +`CommunicationTokenCredential` is only the interface, please always use the `AzureCommunicationTokenCredential` constructor to create a credential and take advantage of the built-in refresh logic. ## Examples ### Create a credential with a static token ```typescript -const userCredential = new AzureCommunicationUserCredential( +const tokenCredential = new AzureCommunicationTokenCredential( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjM2MDB9.adM-ddBZZlQ1WlN3pdPBOF5G4Wh9iZpxNP_fSvpF4cWs" ); ``` @@ -40,7 +40,7 @@ const userCredential = new AzureCommunicationUserCredential( Here we assume that we have a function `fetchTokenFromMyServerForUser` that makes a network request to retrieve a token string for a user. We pass it into the credential to fetch a token for Bob from our own server. Our server would use the Azure Communication Administration library to issue tokens. ```typescript -const userCredential = new AzureCommunicationUserCredential({ +const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher: async () => fetchTokenFromMyServerForUser("bob@contoso.com") }); ``` @@ -50,7 +50,7 @@ const userCredential = new AzureCommunicationUserCredential({ Setting `refreshProactively` to true will call your `tokenRefresher` function when the token is close to expiry. ```typescript -const userCredential = new AzureCommunicationUserCredential({ +const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher: async () => fetchTokenFromMyServerForUser("bob@contoso.com"), refreshProactively: true }); @@ -61,10 +61,10 @@ const userCredential = new AzureCommunicationUserCredential({ Passing `initialToken` is an optional optimization to skip the first call to `tokenRefresher`. You can use this to separate the boot from your application from subsequent token refresh cycles. ```typescript -const userCredential = new AzureCommunicationUserCredential({ +const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher: async () => fetchTokenFromMyServerForUser("bob@contoso.com"), refreshProactively: true, - initialToken: + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjM2MDB9.adM-ddBZZlQ1WlN3pdPBOF5G4Wh9iZpxNP_fSvpF4cWs" }); ``` diff --git a/sdk/communication/communication-common/review/communication-common.api.md b/sdk/communication/communication-common/review/communication-common.api.md index fd541caf8d7c..37c02d80f90c 100644 --- a/sdk/communication/communication-common/review/communication-common.api.md +++ b/sdk/communication/communication-common/review/communication-common.api.md @@ -10,7 +10,7 @@ import { KeyCredential } from '@azure/core-auth'; import { RequestPolicyFactory } from '@azure/core-http'; // @public -export class AzureCommunicationUserCredential implements CommunicationUserCredential { +export class AzureCommunicationTokenCredential implements CommunicationTokenCredential { constructor(token: string); constructor(refreshOptions: RefreshOptions); dispose(): void; @@ -28,14 +28,14 @@ export interface CallingApplicationKind extends CallingApplication { } // @public -export interface CommunicationUser { - communicationUserId: string; +export interface CommunicationTokenCredential { + dispose(): void; + getToken(abortSignal?: AbortSignalLike): Promise; } // @public -export interface CommunicationUserCredential { - dispose(): void; - getToken(abortSignal?: AbortSignalLike): Promise; +export interface CommunicationUser { + communicationUserId: string; } // @public @@ -85,8 +85,8 @@ export interface PhoneNumberKind extends PhoneNumber { // @public export interface RefreshOptions { - initialToken?: string; refreshProactively?: boolean; + token?: string; tokenRefresher: (abortSignal?: AbortSignalLike) => Promise; } diff --git a/sdk/communication/communication-common/src/autoRefreshUserCredential.ts b/sdk/communication/communication-common/src/autoRefreshTokenCredential.ts similarity index 84% rename from sdk/communication/communication-common/src/autoRefreshUserCredential.ts rename to sdk/communication/communication-common/src/autoRefreshTokenCredential.ts index 0cfb00a69959..a5bf0c81434a 100644 --- a/sdk/communication/communication-common/src/autoRefreshUserCredential.ts +++ b/sdk/communication/communication-common/src/autoRefreshTokenCredential.ts @@ -3,24 +3,24 @@ import { AbortSignalLike, AccessToken } from "@azure/core-http"; import { parseToken } from "./tokenParser"; -import { UserCredential } from "./communicationUserCredential"; +import { TokenCredential } from "./communicationTokenCredential"; /** - * Options for auto-refreshing a Communication user credential. + * Options for auto-refreshing a Communication Token credential. */ export interface RefreshOptions { /** - * Function that returns a user token acquired from the Communication configuration SDK. + * Function that returns a token acquired from the Communication configuration SDK. */ tokenRefresher: (abortSignal?: AbortSignalLike) => Promise; /** - * Optional user token to initialize. + * Optional token to initialize. */ - initialToken?: string; + token?: string; /** - * Indicates whether the user token should be proactively renewed prior to expiry or only renew on demand. + * Indicates whether the token should be proactively renewed prior to expiry or only renew on demand. * By default false. */ refreshProactively?: boolean; @@ -30,7 +30,7 @@ const expiredToken = { token: "", expiresOnTimestamp: -10 }; const minutesToMs = (minutes: number): number => minutes * 1000 * 60; const defaultRefreshingInterval = minutesToMs(10); -export class AutoRefreshUserCredential implements UserCredential { +export class AutoRefreshTokenCredential implements TokenCredential { private readonly refresh: (abortSignal?: AbortSignalLike) => Promise; private readonly refreshProactively: boolean; private readonly refreshingIntervalInMs: number = defaultRefreshingInterval; @@ -42,10 +42,10 @@ export class AutoRefreshUserCredential implements UserCredential { private disposed = false; constructor(refreshArgs: RefreshOptions) { - const { tokenRefresher, initialToken, refreshProactively } = refreshArgs; + const { tokenRefresher, token, refreshProactively } = refreshArgs; this.refresh = tokenRefresher; - this.currentToken = initialToken ? parseToken(initialToken) : expiredToken; + this.currentToken = token ? parseToken(token) : expiredToken; this.refreshProactively = refreshProactively ?? false; if (this.refreshProactively) { diff --git a/sdk/communication/communication-common/src/communicationUserCredential.ts b/sdk/communication/communication-common/src/communicationTokenCredential.ts similarity index 56% rename from sdk/communication/communication-common/src/communicationUserCredential.ts rename to sdk/communication/communication-common/src/communicationTokenCredential.ts index a81877bd07d6..70fbf2137b02 100644 --- a/sdk/communication/communication-common/src/communicationUserCredential.ts +++ b/sdk/communication/communication-common/src/communicationTokenCredential.ts @@ -4,48 +4,48 @@ import { AbortSignalLike, AccessToken } from "@azure/core-http"; import { parseToken } from "./tokenParser"; import { StaticTokenCredential } from "./staticTokenCredential"; -import { AutoRefreshUserCredential, RefreshOptions } from "./autoRefreshUserCredential"; +import { AutoRefreshTokenCredential, RefreshOptions } from "./autoRefreshTokenCredential"; -export type UserCredential = Pick; +export type TokenCredential = Pick; /** - * The Azure Communication Services User token credential. + * The Azure Communication Services token credential. */ -export interface CommunicationUserCredential { +export interface CommunicationTokenCredential { /** * Gets an `AccessToken` for the user. Throws if already disposed. * @param abortSignal An implementation of `AbortSignalLike` to cancel the operation. */ getToken(abortSignal?: AbortSignalLike): Promise; /** - * Disposes the CommunicationUserCredential and cancels any internal auto-refresh operation. + * Disposes the CommunicationTokenCredential and cancels any internal auto-refresh operation. */ dispose(): void; } /** - * The CommunicationUserCredential implementation with support for proactive token refresh. + * The CommunicationTokenCredential implementation with support for proactive token refresh. */ -export class AzureCommunicationUserCredential implements CommunicationUserCredential { - private readonly userCredential: UserCredential; +export class AzureCommunicationTokenCredential implements CommunicationTokenCredential { + private readonly tokenCredential: TokenCredential; private disposed = false; /** - * Creates an instance of CommunicationUserCredential with a static token and no proactive refreshing. + * Creates an instance of CommunicationTokenCredential with a static token and no proactive refreshing. * @param token A user access token issued by Communication Services. */ constructor(token: string); /** - * Creates an instance of CommunicationUserCredential with a lambda to get a token and options + * Creates an instance of CommunicationTokenCredential with a lambda to get a token and options * to configure proactive refreshing. * @param refreshOptions Options to configure refresh and opt-in to proactive refreshing. */ constructor(refreshOptions: RefreshOptions); constructor(tokenOrRefreshOptions: string | RefreshOptions) { if (typeof tokenOrRefreshOptions === "string") { - this.userCredential = new StaticTokenCredential(parseToken(tokenOrRefreshOptions)); + this.tokenCredential = new StaticTokenCredential(parseToken(tokenOrRefreshOptions)); } else { - this.userCredential = new AutoRefreshUserCredential(tokenOrRefreshOptions); + this.tokenCredential = new AutoRefreshTokenCredential(tokenOrRefreshOptions); } } @@ -55,17 +55,17 @@ export class AzureCommunicationUserCredential implements CommunicationUserCreden */ public async getToken(abortSignal?: AbortSignalLike): Promise { this.throwIfDisposed(); - const token = await this.userCredential.getToken(abortSignal); + const token = await this.tokenCredential.getToken(abortSignal); this.throwIfDisposed(); return token; } /** - * Disposes the CommunicationUserCredential and cancels any internal auto-refresh operation. + * Disposes the CommunicationTokenCredential and cancels any internal auto-refresh operation. */ public dispose(): void { this.disposed = true; - this.userCredential.dispose(); + this.tokenCredential.dispose(); } private throwIfDisposed(): void { diff --git a/sdk/communication/communication-common/src/index.ts b/sdk/communication/communication-common/src/index.ts index 871e4933a091..ac9f9a4ebd0b 100644 --- a/sdk/communication/communication-common/src/index.ts +++ b/sdk/communication/communication-common/src/index.ts @@ -2,9 +2,9 @@ // Licensed under the MIT license. export { - AzureCommunicationUserCredential, - CommunicationUserCredential -} from "./communicationUserCredential"; -export { RefreshOptions } from "./autoRefreshUserCredential"; + AzureCommunicationTokenCredential, + CommunicationTokenCredential +} from "./communicationTokenCredential"; +export { RefreshOptions } from "./autoRefreshTokenCredential"; export * from "./credential"; export * from "./identifierModels"; diff --git a/sdk/communication/communication-common/src/staticTokenCredential.ts b/sdk/communication/communication-common/src/staticTokenCredential.ts index 65c4ee2d44ad..7d8b1ee2f9d2 100644 --- a/sdk/communication/communication-common/src/staticTokenCredential.ts +++ b/sdk/communication/communication-common/src/staticTokenCredential.ts @@ -2,12 +2,12 @@ // Licensed under the MIT license. import { AccessToken } from "@azure/core-http"; -import { UserCredential } from "./communicationUserCredential"; +import { TokenCredential } from "./communicationTokenCredential"; /** * StaticTokenCredential */ -export class StaticTokenCredential implements UserCredential { +export class StaticTokenCredential implements TokenCredential { constructor(private readonly token: AccessToken) {} public async getToken(): Promise { diff --git a/sdk/communication/communication-common/test/communicationUserCredential.spec.ts b/sdk/communication/communication-common/test/communicationTokenCredential.spec.ts similarity index 68% rename from sdk/communication/communication-common/test/communicationUserCredential.spec.ts rename to sdk/communication/communication-common/test/communicationTokenCredential.spec.ts index e1a3172afaaa..1c02d01d1e6a 100644 --- a/sdk/communication/communication-common/test/communicationUserCredential.spec.ts +++ b/sdk/communication/communication-common/test/communicationTokenCredential.spec.ts @@ -6,7 +6,7 @@ import chaiAsPromised from "chai-as-promised"; import { assert, use } from "chai"; import { isNode } from "@azure/core-http"; import { AbortSignal } from "@azure/abort-controller"; -import { AzureCommunicationUserCredential } from "../src/communicationUserCredential"; +import { AzureCommunicationTokenCredential } from "../src/communicationTokenCredential"; use(chaiAsPromised); @@ -20,21 +20,21 @@ const generateToken = (validForMinutes: number): string => { }; const exposeInternalTimeout = ( - userCredential: AzureCommunicationUserCredential + tokenCredential: AzureCommunicationTokenCredential ): ReturnType => { - return ((userCredential as any).userCredential as any).activeTimeout; + return ((tokenCredential as any).tokenCredential as any).activeTimeout; }; const exposeInternalUpdatePromise = async ( - userCredential: AzureCommunicationUserCredential + tokenCredential: AzureCommunicationTokenCredential ): Promise => { - const internalPromise = ((userCredential as any).userCredential as any).activeTokenUpdating; + const internalPromise = ((tokenCredential as any).tokenCredential as any).activeTokenUpdating; if (internalPromise) { await internalPromise; } }; -describe("CommunicationUserCredential", () => { +describe("CommunicationTokenCredential", () => { let clock: sinon.SinonFakeTimers; beforeEach(() => { @@ -46,16 +46,16 @@ describe("CommunicationUserCredential", () => { }); it("handles valid JWT strings", async () => { - new AzureCommunicationUserCredential(generateToken(60)); + new AzureCommunicationTokenCredential(generateToken(60)); }); it("throws if non-JWT token", async () => { - assert.throws(() => new AzureCommunicationUserCredential("IAmNotAToken"), /Invalid token/); + assert.throws(() => new AzureCommunicationTokenCredential("IAmNotAToken"), /Invalid token/); }); it("throws if non-JWT passed as lambda", async () => { await assert.isRejected( - new AzureCommunicationUserCredential({ + new AzureCommunicationTokenCredential({ tokenRefresher: async () => "IAmNotAToken" }).getToken() ); @@ -63,38 +63,38 @@ describe("CommunicationUserCredential", () => { it("returns token as expected", async () => { const token = generateToken(60); - const userCredential = new AzureCommunicationUserCredential(token); - const tokenResult = (await userCredential.getToken()).token; + const tokenCredential = new AzureCommunicationTokenCredential(token); + const tokenResult = (await tokenCredential.getToken()).token; assert.strictEqual(tokenResult, token); }); it("returns token as expected when using lambda", async () => { const token = generateToken(60); const tokenRefresher = sinon.stub().resolves(token); - const userCredential = new AzureCommunicationUserCredential({ + const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher }); - const tokenResult = (await userCredential.getToken()).token; + const tokenResult = (await tokenCredential.getToken()).token; assert.strictEqual(tokenResult, token); sinon.assert.calledOnce(tokenRefresher); }); it("uses initial token as expected", async () => { - const initialToken = generateToken(60); + const token = generateToken(60); const tokenRefresher = sinon.stub().resolves(generateToken(120)); - const userCredential = new AzureCommunicationUserCredential({ + const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher, - initialToken, + token, refreshProactively: true }); - const tokenResult = (await userCredential.getToken()).token; - assert.strictEqual(tokenResult, initialToken); + const tokenResult = (await tokenCredential.getToken()).token; + assert.strictEqual(tokenResult, token); sinon.assert.notCalled(tokenRefresher); }); it("no proactive refresh, accepts expired token", async () => { const tokenRefresher = sinon.stub().resolves(generateToken(-1)); - new AzureCommunicationUserCredential({ + new AzureCommunicationTokenCredential({ tokenRefresher }); clock.tick(5 * 60 * 1000); @@ -103,7 +103,7 @@ describe("CommunicationUserCredential", () => { it("with proactive refresh, passing an expired token triggers immediate refresh", async () => { const tokenRefresher = sinon.stub().resolves(generateToken(-1)); - new AzureCommunicationUserCredential({ + new AzureCommunicationTokenCredential({ tokenRefresher, refreshProactively: true }); @@ -113,24 +113,24 @@ describe("CommunicationUserCredential", () => { it("returns expired token when not using a lambda", async () => { const token = generateToken(-1); - const userCredential = new AzureCommunicationUserCredential(token); - const tokenResult = (await userCredential.getToken()).token; + const tokenCredential = new AzureCommunicationTokenCredential(token); + const tokenResult = (await tokenCredential.getToken()).token; assert.strictEqual(tokenResult, token); }); it("passes abortSignal through to tokenRefresher", async () => { const tokenRefresher = sinon.stub().resolves(generateToken(60)); - const userCredential = new AzureCommunicationUserCredential({ + const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher }); const abortSignal = AbortSignal.none; - userCredential.getToken(abortSignal); + tokenCredential.getToken(abortSignal); sinon.assert.calledOnceWithExactly(tokenRefresher, abortSignal); }); it("throws if disposed", async () => { - const withStatic = new AzureCommunicationUserCredential(generateToken(60)); - const withLambda = new AzureCommunicationUserCredential({ + const withStatic = new AzureCommunicationTokenCredential(generateToken(60)); + const withLambda = new AzureCommunicationTokenCredential({ tokenRefresher: async () => generateToken(60) }); withStatic.dispose(); @@ -141,32 +141,32 @@ describe("CommunicationUserCredential", () => { it("doesn't swallow error from tokenrefresher", async () => { const tokenRefresher = sinon.stub().throws(new Error("No token for you!")); - const userCredential = new AzureCommunicationUserCredential({ + const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher }); - await assert.isRejected(userCredential.getToken()); + await assert.isRejected(tokenCredential.getToken()); }); it("requests new token when token is about to expire", async () => { const token = generateToken(20); const newToken = generateToken(60); const tokenRefresher = sinon.stub().resolves(token); - const userCredential = new AzureCommunicationUserCredential({ tokenRefresher }); + const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher }); - const tokenResult = await userCredential.getToken(); + const tokenResult = await tokenCredential.getToken(); assert.strictEqual(tokenResult.token, token); tokenRefresher.resolves(newToken); // go into soon to expire window clock.tick(19 * 60 * 1000); - const secondTokenResult = await userCredential.getToken(); + const secondTokenResult = await tokenCredential.getToken(); // returns old token because it's still valid assert.strictEqual(secondTokenResult.token, token); clock.tick(5 * 60 * 1000); // now it returns new token - const thirdTokenResult = await userCredential.getToken(); + const thirdTokenResult = await tokenCredential.getToken(); assert.strictEqual(thirdTokenResult.token, newToken); sinon.assert.calledTwice(tokenRefresher); @@ -175,10 +175,10 @@ describe("CommunicationUserCredential", () => { it("proactively refreshes token when it is about to expire", async () => { const token = (): string => generateToken(20); const tokenRefresher = sinon.stub().resolves(token()); - new AzureCommunicationUserCredential({ + new AzureCommunicationTokenCredential({ tokenRefresher, refreshProactively: true, - initialToken: token() + token: token() }); // go into soon to expire window @@ -189,18 +189,18 @@ describe("CommunicationUserCredential", () => { it("repeats proactive refreshing", async () => { const token = (): string => generateToken(20); const tokenRefresher = sinon.stub().resolves(token()); - const userCredential = new AzureCommunicationUserCredential({ + const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher, refreshProactively: true, - initialToken: token() + token: token() }); - const internalTimeout = exposeInternalTimeout(userCredential); + const internalTimeout = exposeInternalTimeout(tokenCredential); // go into soon to expire window clock.tick(19 * 60 * 1000); - await exposeInternalUpdatePromise(userCredential); - const newInternalTimeout = exposeInternalTimeout(userCredential); + await exposeInternalUpdatePromise(tokenCredential); + const newInternalTimeout = exposeInternalTimeout(tokenCredential); assert.isDefined(internalTimeout); assert.isDefined(newInternalTimeout); @@ -210,13 +210,13 @@ describe("CommunicationUserCredential", () => { it("dispose cancels timer", async () => { const token = (): string => generateToken(20); const tokenRefresher = sinon.stub().resolves(token()); - const userCredential = new AzureCommunicationUserCredential({ + const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher, refreshProactively: true, - initialToken: token() + token: token() }); - userCredential.dispose(); + tokenCredential.dispose(); // go into soon to expire window clock.tick(19 * 60 * 1000); sinon.assert.notCalled(tokenRefresher); @@ -224,10 +224,10 @@ describe("CommunicationUserCredential", () => { it("multiple calls to getToken call tokenRefresher only once", async () => { const tokenRefresher = sinon.stub().resolves(generateToken(60)); - const userCredential = new AzureCommunicationUserCredential({ tokenRefresher }); + const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher }); for (let i = 0; i < 10; i++) { - await userCredential.getToken(); + await tokenCredential.getToken(); } sinon.assert.calledOnce(tokenRefresher); @@ -235,14 +235,14 @@ describe("CommunicationUserCredential", () => { it("calls tokenRefresher only once when proactive refreshing is in progress", async () => { const tokenRefresher = sinon.stub().resolves(generateToken(20)); - const userCredential = new AzureCommunicationUserCredential({ + const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher, refreshProactively: true }); // go into soon to expire window clock.tick(19 * 60 * 1000); - await userCredential.getToken(); + await tokenCredential.getToken(); sinon.assert.calledOnce(tokenRefresher); }); });