Skip to content

Commit

Permalink
feat: Adds access token authentication to client (#166)
Browse files Browse the repository at this point in the history
  • Loading branch information
geofflamrock authored Aug 22, 2023
1 parent 82df440 commit 7ba6d05
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 7 deletions.
3 changes: 2 additions & 1 deletion getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ const configuration: ClientConfiguration = {
Each parameter serve a specific purpose:

* `agent` (optional) defines an HTTP proxy agent that may be defined for debugging purposes (i.e. Fiddler) -- useful for viewing inbound/outbound messages between the API client and the target instance of Octopus Deploy
* `apiKey` (required) defines the API key to be used to connect to Octopus Deploy (see [How to Create an API Key](https://octopus.com/docs/octopus-rest-api/how-to-create-an-api-key) for more information concerning API keys)
* `apiKey` (optional) defines the API key to be used to connect to Octopus Deploy (see [How to Create an API Key](https://octopus.com/docs/octopus-rest-api/how-to-create-an-api-key) for more information concerning API keys). One of `apiKey` or `accessToken` is required.
* `accessToken` (optional) defines the access token to be used to connect to Octopus Deploy. Access tokens can be obtained using OpenID Connect identities. One of `accessToken` or `apiKey` is required.
* `instanceURL` (required) defines the full URL of target instance of Octopus Deploy (i.e. `'https://demo.octopus.app'`)
* `autoConnect` (optional) informs the `Client` to automatically attempt to connect to the target instance of Octopus Deploy when `Client.create(configuration)` is invoked
* `space`: (optional) defines the target space in Octopus Deploy for API operations -- assumes the default space if undefined
Expand Down
10 changes: 5 additions & 5 deletions src/adapters/axiosAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { AxiosRequestConfig, Method } from "axios";
import type { AxiosRequestConfig, Method, RawAxiosRequestHeaders } from "axios";
import axios from "axios";
import type { Adapter, AdapterResponse } from "../adapter";
import { AdapterError } from "../adapter";
import { ClientOptions } from "../clientOptions";
import { createRequestHeaders } from "./createRequestHeaders";

export class AxiosAdapter<TResource> implements Adapter<TResource> {
public async execute(options: ClientOptions): Promise<AdapterResponse<TResource>> {
Expand All @@ -12,12 +13,10 @@ export class AxiosAdapter<TResource> implements Adapter<TResource> {
url: options.url,
maxContentLength: Infinity,
maxBodyLength: Infinity,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
method: options.method as Method,
data: options.requestBody,
headers: {
"Accept-Encoding": "gzip,deflate,compress", // HACK: required for https://github.com/axios/axios/issues/5346 -- this line can be removed once this bug has been fixed
"X-Octopus-ApiKey": options.configuration.apiKey ?? "",
},
headers: createRequestHeaders(options.configuration),
responseType: "json",
};
if (typeof XMLHttpRequest === "undefined") {
Expand Down Expand Up @@ -51,6 +50,7 @@ export class AxiosAdapter<TResource> implements Adapter<TResource> {
let message = response.data.ErrorMessage;

if (response.data.Errors) {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const errors = response.data.Errors as string[];

for (let i = 0; i < errors.length; i++) {
Expand Down
48 changes: 48 additions & 0 deletions src/adapters/createRequestHeaders.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ClientConfiguration } from "../clientConfiguration";
import { createRequestHeaders } from "./createRequestHeaders";

describe("createRequestHeaders", () => {
test("when api key is provided it is put into the correct request header", () => {
const configuration: ClientConfiguration = {
instanceURL: "https://my.octopus.app",
userAgentApp: "createRequestHeader-tests",
apiKey: "api-key",
};

const headers = createRequestHeaders(configuration);

expect(headers).toEqual({
"Accept-Encoding": "gzip,deflate,compress",
"X-Octopus-ApiKey": "api-key",
});
});

test("when an access token is provided it is put into the correct request header", () => {
const configuration: ClientConfiguration = {
instanceURL: "https://my.octopus.app",
userAgentApp: "createRequestHeader-tests",
accessToken: "access-token",
};

const headers = createRequestHeaders(configuration);

expect(headers).toEqual({
"Accept-Encoding": "gzip,deflate,compress",
Authorization: "Bearer access-token",
});
});

test("when neither an access token or api key is provided then the correct api key header is filled in for backward compatibility", () => {
const configuration: ClientConfiguration = {
instanceURL: "https://my.octopus.app",
userAgentApp: "createRequestHeader-tests",
};

const headers = createRequestHeaders(configuration);

expect(headers).toEqual({
"Accept-Encoding": "gzip,deflate,compress",
"X-Octopus-ApiKey": "",
});
});
});
20 changes: 20 additions & 0 deletions src/adapters/createRequestHeaders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { RawAxiosRequestHeaders } from "axios";
import { ClientConfiguration } from "../clientConfiguration";

export function createRequestHeaders(configuration: ClientConfiguration): RawAxiosRequestHeaders {
const headers: RawAxiosRequestHeaders = {
"Accept-Encoding": "gzip,deflate,compress", // HACK: required for https://github.com/axios/axios/issues/5346 -- this line can be removed once this bug has been fixed
};
if (configuration.apiKey) {
headers["X-Octopus-ApiKey"] = configuration.apiKey;
}
if (configuration.accessToken) {
headers["Authorization"] = `Bearer ${configuration.accessToken}`;
}
if (!configuration.accessToken && !configuration.apiKey) {
// Backward compatibility: Add the api key header in with a blank value
headers["X-Octopus-ApiKey"] = "";
}

return headers;
}
3 changes: 2 additions & 1 deletion src/clientConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Logger } from "./logger";
export interface ClientConfiguration {
userAgentApp: string;
httpsAgent?: Agent;
apiKey: string;
apiKey?: string;
accessToken?: string;
instanceURL: string;
logging?: Logger;
}

0 comments on commit 7ba6d05

Please sign in to comment.