Skip to content

Commit

Permalink
Add new Javascript sdk for browser based application and Guidelines a…
Browse files Browse the repository at this point in the history
…nd Recommendations for handling Oauth API Token
  • Loading branch information
noyb34 committed Jan 17, 2024
1 parent d53c080 commit a8ae776
Show file tree
Hide file tree
Showing 5 changed files with 470 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@

# Guidelines and Recommendations for Handling OAuth API Access Tokens

- [Guidelines and Recommendations for Handling OAuth API Access Tokens](#guidelines-and-recommendations-for-handling-oauth-api-access-tokens)
- [Introduction](#introduction)
- [General Guidelines](#general-guidelines)
- [1. **Secure Storage of Consumer Key and Secret**](#1-secure-storage-of-consumer-key-and-secret)
- [2. **Token Encryption**](#2-token-encryption)
- [3. **Token Transmission**](#3-token-transmission)
- [4. **Token Validation**](#4-token-validation)
- [Frequent Refreshing of OAuth Tokens](#frequent-refreshing-of-oauth-tokens)
- [1. **Short-Lived Access Tokens**](#1-short-lived-access-tokens)
- [2. **Token Rotation**](#2-token-rotation)
- [3. **Automated Refresh Mechanism**](#3-automated-refresh-mechanism)
- [4. **Handling Refresh Errors**](#4-handling-refresh-errors)
- [5. **Monitoring and Logging**](#5-monitoring-and-logging)
- [6. **Consider User Experience**](#6-consider-user-experience)
- [7. **Compliance with Provider Guidelines**](#7-compliance-with-provider-guidelines)
- [Conclusion](#conclusion)

## Introduction

This document provides guidelines and recommendations for handling OAuth API tokens for the Metadata Bank API. Security is paramount, and the following practices ensure that tokens are managed securely and efficiently. This document is in adherence to CISA/DOD and the IETF best practice documentation [^1].This guideline will mitigate OWASP's top 10 CI/CD security risks [^1]. While the majority of the content was authored by the Metadata Bank API Team, it incorporates valuable contributions and expert security guidance from our Cybersecurity Team.

## General Guidelines

### 1. **Secure Storage of Consumer Key and Secret**

- **Environment Variables:** Store the consumer key and secret in environment variables or a secure configuration manager.
- **Automate the discovery of secrets:** Use a centralized management tool and a secret vault to store various credentials[^1].
- **Avoid Hardcoding and embedded secrets:** Never hardcode these values within your codebase.
- **Use Encryption:** If storing in a file, make sure the file is encrypted and accessible only to authorized applications and users.

### 2. **Token Encryption**

- **Use Strong Encryption Algorithms:** Encrypt tokens using robust algorithms like AES.
- **Key Management:** Manage encryption keys securely, rotating them periodically.

### 3. **Token Transmission**

- **Use HTTPS:** Always transmit tokens over HTTPS to ensure they are encrypted during transit[^2].
- **Use TLS:** Use a minimum of TLS 1.2 to send keys, secrets, and tokens[^1].

### 4. **Token Validation**

- **Validate Tokens:** Validate tokens on the server-side to ensure they are not tampered with.

## Frequent Refreshing of OAuth Tokens

### 1. **Short-Lived Access Tokens**

- **Use Short Expiration Times:** Set short expiration times (e.g., one hour).
- **Implement Refresh Tokens:** Use refresh tokens for obtaining new access tokens.
- **Privilege Limitation:** Access tokens should have the minimum privileges required for the specific application or use case[^1].
- **Resource & Action Restriction:** Access tokens should be limited to particular resource servers and actions on those resources[^1].

### 2. **Token Rotation**

- **Rotate and Revoke:** Rotate tokens regularly and revoke old ones.

### 3. **Automated Refresh Mechanism**

- **Auto-Refresh Logic:** Implement logic to refresh tokens automatically.
- **Dynamic Token Refresh:** Implement dynamic token refresh[^1].

### 4. **Handling Refresh Errors**

- **Graceful Error Handling:** Handle refresh errors gracefully.

### 5. **Monitoring and Logging**

- **Monitor and Log Securely:** Monitor token refresh activities and log securely.

### 6. **Consider User Experience**

- **Balance Security with Usability** Ensure a smooth user experience.

### 7. **Compliance with Provider Guidelines**

- **Follow Provider's Recommendations:** Adhere to specific OAuth provider guidelines.

## Conclusion

By following these guidelines and recommendations, you can ensure that OAuth API access tokens are handled securely and efficiently. Frequent token refreshing, secure storage, encryption, and compliance with best practices are essential to maintaining the integrity and confidentiality of the tokens.

[^1]: Cybersecurity Team
[^2]: [Token Best Practices](https://auth0.com/docs/secure/tokens/token-best-practices)
Binary file not shown.
153 changes: 153 additions & 0 deletions sdk-web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# getApiTokenForWebApp.js Documentation

## Overview

The `getApiTokenForWebApp.js` module provides functionality to retrieve an API token from a specified endpoint. This token is necessary for authenticating subsequent API requests from a web application. The module includes error handling through retries and securely stores the token in the browser's local storage.

## Functions

### `async fetchToken(url, headers, params)`

Fetches an API token using HTTP POST request.

**Parameters:**

- `url` (string): The URL to the token endpoint.
- `headers` (Headers): Request headers.
- `params` (URLSearchParams): Body parameters for the request.

**Returns:**

- `Promise<Object>`: A promise that resolves to the JSON response containing the token.

**Throws:**

- `Error`: If the fetch request fails or the server response is not OK.

### `async retryFetchToken(retries, interval, fetchTokenFunc, attempt)`

Retries the token fetch request if it fails, with a specified number of attempts and delay between them.

**Parameters:**

- `retries` (number): The maximum number of retry attempts.
- `interval` (number): The delay between retry attempts in milliseconds.
- `fetchTokenFunc` (Function): The fetchToken function to retry.
- `attempt` (number): Current attempt number, defaults to 0.

**Returns:**

- `Promise<Object>`: A promise that resolves to the JSON response containing the token.

**Throws:**

- `Error`: If all retries fail.

### `async refreshToken(retries, interval)`

Main function to retrieve and locally store an API token, with optional retry logic.

**Parameters:**

- `retries` (number): The number of retries, defaults to 2.
- `interval` (number): The interval between retries in milliseconds, defaults to 1000.

**Returns:**

- `Promise<Object>`: A promise that resolves to the token data.

**Usage:**

This function should be called to initiate the token retrieval process. It will store the token in local storage under the key `'authToken'`.

## Usage

To use this module, import it into your Vue.js component and call the `refreshToken()` function to retrieve and store the API token.

```javascript
import apiTokenService from './getApiTokenForWebApp';

// Call this function when you need to get a new API token
apiTokenService.refreshToken()
.then(data => {
// Use the token from data.access_token
})
.catch(error => {
console.error('Error fetching the API token:', error);
});
```

## Local Storage

The module stores the retrieved token in the browser's local storage under the key `'authToken'`. The token will persist across browser tabs and windows until the browser is closed.

**Note:** It is important to ensure that the application runs over HTTPS to prevent potential security risks associated with token handling.

## Runtime Environment Variables

The module uses placeholders for runtime environment variables that must be replaced with actual values when the Docker container starts. These variables include:

- `API_URL`: The base URL to the API.
- `CONSUMER_KEY`: The consumer key for the API.
- `CONSUMER_SECRET`: The consumer secret for the API.
- `SCOPE`: The scope for the API token request.

The runtime environment will not directly use the variables `API_URL`, `CONSUMER_KEY`, `CONSUMER_SECRET`, and `SCOPE`. Instead, they are to be used for generating configuration files or scripts during the Docker build, which will subsequently be executed at runtime to inject the necessary values.

Ensure these variables are securely passed and replaced at runtime.

### Docker Build-Time Configuration

This module relies on certain critical values that must be provided at build time:

- `API_URL`: The base URL for the API from which the token will be fetched.
- `CONSUMER_KEY`: The API consumer key.
- `CONSUMER_SECRET`: The API consumer secret.
- `SCOPE`: The scope of access requested from the API.

These values should be stored as secrets in the GitHub repository or other repository and passed to the Docker build process via the `ARG` instruction. They will be utilized during the build to create a proper configuration file or script that will be executed at runtime.

### Dockerfile ARG Instructions

Include the following in your Dockerfile to accept the build-time arguments:

```Dockerfile
ARG API_URL
ARG CONSUMER_KEY
ARG CONSUMER_SECRET
ARG SCOPE
```

### GitHub Actions Secrets

In your GitHub Actions workflow, make sure to pass these arguments using the secrets you have stored in your repository:

```yaml
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
file: ./Dockerfile
push: true
tags: user/appname:latest
build-args: |
API_URL=${{ secrets.API_URL }}
CONSUMER_KEY=${{ secrets.CONSUMER_KEY }}
CONSUMER_SECRET=${{ secrets.CONSUMER_SECRET }}
SCOPE=${{ secrets.SCOPE }}
```

## Contributing

Feel free to open issues or submit pull requests if you find any problems or have suggestions.

## License

These modules are licensed under the GPLv3. Please see the [LICENSE](../LICENSE.txt) file in the root directory for more information.

---
Author: Patrick Roch
145 changes: 145 additions & 0 deletions sdk-web/documentation/sdk-getApiTokenForWebApp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# getApiTokenForWebApp.js Documentation

## Overview

The `getApiTokenForWebApp.js` module provides functionality to retrieve an API token from a specified endpoint. This token is necessary for authenticating subsequent API requests from a web application. The module includes error handling through retries and securely stores the token in the browser's local storage.

## Functions

### `async fetchToken(url, headers, params)`

Fetches an API token using HTTP POST request.

**Parameters:**

- `url` (string): The URL to the token endpoint.
- `headers` (Headers): Request headers.
- `params` (URLSearchParams): Body parameters for the request.

**Returns:**

- `Promise<Object>`: A promise that resolves to the JSON response containing the token.

**Throws:**

- `Error`: If the fetch request fails or the server response is not OK.

### `async retryFetchToken(retries, interval, fetchTokenFunc, attempt)`

Retries the token fetch request if it fails, with a specified number of attempts and delay between them.

**Parameters:**

- `retries` (number): The maximum number of retry attempts.
- `interval` (number): The delay between retry attempts in milliseconds.
- `fetchTokenFunc` (Function): The fetchToken function to retry.
- `attempt` (number): Current attempt number, defaults to 0.

**Returns:**

- `Promise<Object>`: A promise that resolves to the JSON response containing the token.

**Throws:**

- `Error`: If all retries fail.

### `async refreshToken(retries, interval)`

Main function to retrieve and locally store an API token, with optional retry logic.

**Parameters:**

- `retries` (number): The number of retries, defaults to 2.
- `interval` (number): The interval between retries in milliseconds, defaults to 1000.

**Returns:**

- `Promise<Object>`: A promise that resolves to the token data.

**Usage:**

This function should be called to initiate the token retrieval process. It will store the token in local storage under the key `'authToken'`.

## Usage

To use this module, import it into your Vue.js component and call the `refreshToken()` function to retrieve and store the API token.

```javascript
import apiTokenService from './getApiTokenForWebApp';

// Call this function when you need to get a new API token
apiTokenService.refreshToken()
.then(data => {
// Use the token from data.access_token
})
.catch(error => {
console.error('Error fetching the API token:', error);
});
```

## Local Storage

The module stores the retrieved token in the browser's local storage under the key `'authToken'`. The token will persist across browser tabs and windows until the browser is closed.

**Note:** It is important to ensure that the application runs over HTTPS to prevent potential security risks associated with token handling.

## Runtime Environment Variables

The module uses placeholders for runtime environment variables that must be replaced with actual values when the Docker container starts. These variables include:

- `API_URL`: The base URL to the API.
- `CONSUMER_KEY`: The consumer key for the API.
- `CONSUMER_SECRET`: The consumer secret for the API.
- `SCOPE`: The scope for the API token request.

The runtime environment will not directly use the variables `API_URL`, `CONSUMER_KEY`, `CONSUMER_SECRET`, and `SCOPE`. Instead, they are to be used for generating configuration files or scripts during the Docker build, which will subsequently be executed at runtime to inject the necessary values.

Ensure these variables are securely passed and replaced at runtime.

### Docker Build-Time Configuration

This module relies on certain critical values that must be provided at build time:

- `API_URL`: The base URL for the API from which the token will be fetched.
- `CONSUMER_KEY`: The API consumer key.
- `CONSUMER_SECRET`: The API consumer secret.
- `SCOPE`: The scope of access requested from the API.

These values should be stored as secrets in the GitHub repository or other repository and passed to the Docker build process via the `ARG` instruction. They will be utilized during the build to create a proper configuration file or script that will be executed at runtime.

### Dockerfile ARG Instructions

Include the following in your Dockerfile to accept the build-time arguments:

```Dockerfile
ARG API_URL
ARG CONSUMER_KEY
ARG CONSUMER_SECRET
ARG SCOPE
```

### GitHub Actions Secrets

In your GitHub Actions workflow, make sure to pass these arguments using the secrets you have stored in your repository:

```yaml
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
file: ./Dockerfile
push: true
tags: user/appname:latest
build-args: |
API_URL=${{ secrets.API_URL }}
CONSUMER_KEY=${{ secrets.CONSUMER_KEY }}
CONSUMER_SECRET=${{ secrets.CONSUMER_SECRET }}
SCOPE=${{ secrets.SCOPE }}
```

---
Author: Patrick Roch
Loading

0 comments on commit a8ae776

Please sign in to comment.