From acb7713b7c8acb9e90ce0e9acffb4cfa18ebcc37 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Mon, 11 Jan 2021 15:27:28 -0800 Subject: [PATCH] [core-auth] Add AzureSASCredential (#13091) This change adds an interfance and supporting class for use by services which support authentication used a shared acccess signature. Fixes #13053 --- sdk/core/core-auth/CHANGELOG.md | 1 + sdk/core/core-auth/review/core-auth.api.md | 12 +++++ sdk/core/core-auth/src/azureSASCredential.ts | 57 ++++++++++++++++++++ sdk/core/core-auth/src/index.ts | 1 + sdk/core/core-auth/test/index.spec.ts | 36 +++++++++++++ 5 files changed, 107 insertions(+) create mode 100644 sdk/core/core-auth/src/azureSASCredential.ts diff --git a/sdk/core/core-auth/CHANGELOG.md b/sdk/core/core-auth/CHANGELOG.md index df9fb841b95e..5764e5a17a66 100644 --- a/sdk/core/core-auth/CHANGELOG.md +++ b/sdk/core/core-auth/CHANGELOG.md @@ -2,6 +2,7 @@ ## 1.1.5 (Unreleased) +- Add `AzureSASCredential` and `SASCredential` for use by service clients which allow authenticiation using a shared access signature. ## 1.1.4 (2021-01-07) diff --git a/sdk/core/core-auth/review/core-auth.api.md b/sdk/core/core-auth/review/core-auth.api.md index b59c783bd520..f371cfde03de 100644 --- a/sdk/core/core-auth/review/core-auth.api.md +++ b/sdk/core/core-auth/review/core-auth.api.md @@ -19,6 +19,13 @@ export class AzureKeyCredential implements KeyCredential { update(newKey: string): void; } +// @public +export class AzureSASCredential implements SASCredential { + constructor(signature: string); + get signature(): string; + update(newSignature: string): void; +} + // @public export interface GetTokenOptions { abortSignal?: AbortSignalLike; @@ -38,6 +45,11 @@ export interface KeyCredential { readonly key: string; } +// @public +export interface SASCredential { + readonly signature: string; +} + // @public export interface SpanContext { spanId: string; diff --git a/sdk/core/core-auth/src/azureSASCredential.ts b/sdk/core/core-auth/src/azureSASCredential.ts new file mode 100644 index 000000000000..29c61d48d5d5 --- /dev/null +++ b/sdk/core/core-auth/src/azureSASCredential.ts @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * Represents a credential defined by a static shared access signature. + */ +export interface SASCredential { + /** + * The value of the shared access signature represented as a string + */ + readonly signature: string; +} + +/** + * A static-signature-based credential that supports updating + * the underlying signature value. + */ +export class AzureSASCredential implements SASCredential { + private _signature: string; + + /** + * The value of the shared access signature to be used in authentication + */ + public get signature(): string { + return this._signature; + } + + /** + * Create an instance of an AzureSASCredential for use + * with a service client. + * + * @param signature - The initial value of the shared access signature to use in authentication + */ + constructor(signature: string) { + if (!signature) { + throw new Error("shared access signature must be a non-empty string"); + } + + this._signature = signature; + } + + /** + * Change the value of the signature. + * + * Updates will take effect upon the next request after + * updating the signature value. + * + * @param newSignature - The new shared access signature value to be used + */ + public update(newSignature: string): void { + if (!newSignature) { + throw new Error("shared access signature must be a non-empty string"); + } + + this._signature = newSignature; + } +} diff --git a/sdk/core/core-auth/src/index.ts b/sdk/core/core-auth/src/index.ts index e29cbb327464..6b9432ec107b 100644 --- a/sdk/core/core-auth/src/index.ts +++ b/sdk/core/core-auth/src/index.ts @@ -2,6 +2,7 @@ // Licensed under the MIT license. export { AzureKeyCredential, KeyCredential } from "./azureKeyCredential"; +export { AzureSASCredential, SASCredential } from "./azureSASCredential"; export { TokenCredential, diff --git a/sdk/core/core-auth/test/index.spec.ts b/sdk/core/core-auth/test/index.spec.ts index 4a5485e41520..fc7be8d9212b 100644 --- a/sdk/core/core-auth/test/index.spec.ts +++ b/sdk/core/core-auth/test/index.spec.ts @@ -4,6 +4,7 @@ import assert from "assert"; import { AzureKeyCredential } from "../src/azureKeyCredential"; +import { AzureSASCredential } from "../src/azureSASCredential"; import { isTokenCredential } from "../src/tokenCredential"; describe("AzureKeyCredential", () => { @@ -27,6 +28,41 @@ describe("AzureKeyCredential", () => { }); }); +describe("AzureSASCredential", () => { + it("credential constructor throws on invalid signature", () => { + assert.throws(() => { + void new AzureSASCredential(""); + }, /shared access signature must be a non-empty string/); + assert.throws(() => { + void new AzureSASCredential((null as unknown) as string); + }, /shared access signature must be a non-empty string/); + assert.throws(() => { + void new AzureSASCredential((undefined as unknown) as string); + }, /shared access signature must be a non-empty string/); + }); + + it("credential correctly updates", () => { + const credential = new AzureSASCredential("credential1"); + assert.equal(credential.signature, "credential1"); + credential.update("credential2"); + assert.equal(credential.signature, "credential2"); + }); + + it("throws when upadting with an invalid signature", () => { + const credential = new AzureSASCredential("credential1"); + + assert.throws(() => { + credential.update(""); + }, /shared access signature must be a non-empty string/); + assert.throws(() => { + credential.update((null as unknown) as string); + }, /shared access signature must be a non-empty string/); + assert.throws(() => { + credential.update((undefined as unknown) as string); + }, /shared access signature must be a non-empty string/); + }); +}); + describe("isTokenCredential", function() { it("should return true for an object that resembles a TokenCredential", () => { assert.ok(