Authentication

FoxNose provides multiple authentication methods to securely access both the Management API and the Flux API. Understanding these methods and choosing the appropriate one for your use case is crucial for maintaining security and efficient access control.

Overview

In FoxNose, authentication is secured through JWT tokens and asymmetric encryption with API keys, each serving distinct purposes.

JWT tokens are primarily for user-based authentication within the Management API. Users authenticate directly using their credentials, receiving short-lived access tokens for routine interactions and refresh tokens for extended access. This method grants user-specific permissions, making it ideal for administrative tasks requiring comprehensive control.

API Key Authentication uses asymmetric encryption and allows external services to interact with both the Management API and Flux API. With each API key, a unique public-private key pair is generated. The private key, used only for signing requests, remains secure and is never shared, ensuring data integrity and authenticity. API keys are linked to specific roles with precise permissions, providing flexible, limited access suitable for service-based interactions.

Key Points

API TypeAuthentication Methods
Management API• JWT Authentication (Bearer Token)
• API Key Authentication (Secure/Simple)
Flux API• API Key Authentication (Secure/Simple)

User Authentication (JWT)

Authenticates on behalf of a user using JSON Web Tokens. Suitable for administrative tasks requiring broader permissions. To authenticate as a user, you need to obtain an access token and a refresh token by providing your user credentials.

Token Rotation

For security purposes, JWT tokens are rotated on each authentication. This means that each time you authenticate, you receive new access and refresh tokens. Ensure that you update stored tokens accordingly.

Properties

  • Name
    access
    Type
    string
    Description

    The access token used for authenticating requests to the API. This token is included in the Authorization header with the prefix Bearer. The access token grants temporary access to the API based on the user's permissions.

    Expiration: Access tokens are short-lived and expire after 10 minutes.

  • Name
    refresh
    Type
    string
    Description

    The refresh token allows for obtaining a new access token once the current one expires. It is sent to the Refresh JWT tokens endpoint to generate fresh access and refresh tokens without requiring re-authentication.

    Expiration: Refresh tokens are valid for 7 days.


POSTapi.foxnose.net/account/auth/

Obtaining JWT Tokens

This endpoint allows users to authenticate by providing their email and password, returning access and refresh tokens for further API usage.

Required attributes

  • Name
    email
    Type
    string
    Required
    required
    Description

    Email address of the user.

  • Name
    password
    Type
    string
    Required
    required
    Description

    Password of the user.

Errors codes

  • Name
    401
    Description

    Invalid credentials.

  • Name
    400
    Description

    One or more required attributes are missing. See detail field for more information.

Request

POST
/account/auth/
curl https://api.foxnose.net/account/auth/ \
-H "Content-Type: application/json" \
-d '{
"email": "your-email@example.com",
"password": "your-password"
}'

Response

{
    "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

POSTapi.foxnose.net/account/refresh-token/

Refresh JWT Tokens

This endpoint allows users to refresh their access token using an existing refresh token. This request generates a new access token and, if the refresh token is still valid, a new refresh token as well.

Required attributes

  • Name
    refresh
    Type
    string
    Required
    required
    Description

    The refresh token that will be used to generate a new access token.

Errors codes

  • Name
    401
    Description

    The refresh token is invalid, expired, or revoked.

  • Name
    400
    Description

    The required refresh attribute is missing.

Request

POST
/account/refresh-token/
curl https://api.foxnose.net/account/refresh-token/ \
-H "Content-Type: application/json" \
-d '{
"refresh": "your-refresh-token"
}'

Response

{
    "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Code Examples

const axios = require('axios');

// Authenticate and obtain tokens
axios.post('https://api.foxnose.net/account/auth/', {
    email: 'your-email@example.com',
    password: 'your-password'
})
.then(response => {
    const accessToken = response.data.access;
    const refreshToken = response.data.refresh;

    // Use the access token in your requests
    const headers = {
        Authorization: `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
    };
// Make an authenticated request
axios.get('https://api.foxnose.net/secure-endpoint/', {headers})
    .then(res => {
        console.log(res.status);
        console.log(res.data);
    })
    .catch(err => {
        console.error(err.response.status);
        console.error(err.response.data);
    });
})
.catch(error => {
    console.error (error.response.status);
    console.error(error.response.data);
});

API Key Authentication

FoxNose uses a secure system for accessing both the Management API and the Flux API through API keys, leveraging asymmetric encryption. This ensures a high level of security by keeping your private keys confidential and not storing them on our servers. API keys are generated through the Dashboard of your project.

When you create a new key, you receive:

  • Public Key: Used to identify your API key. Can be shared openly and is used to verify signatures.
  • Private Key: Used to sign your requests. Must be kept secret and is used to create digital signatures.

Both keys are already provided in Base64 encoding. No need to encode them again. The private key is displayed only once during creation. Ensure you store it securely, as it cannot be recovered later. You can assign a role to the API key. If you do not assign a role during creation, you can add or change it later.

"Secure" Auth Method

When making a request to the Management API or Flux API, you need to:

  1. Prepare the Data to Sign:
  • URI: The path of the request including API version (/v1/) and without the hostname, e.g. /v1/7c9h4pwu/folders/.
  • Body Hash: SHA-256 hash of the request body. If there's no body, use the SHA-256 hash of an empty string ('').
  • Timestamp: Current time in ISO 8601 format (e.g., 2024-10-26T20:58:45Z).

Concatenate these elements using a pipe (|) character:

data_to_sign = "<uri>|<body_hash>|<timestamp>"
  1. Create the Signature:
  • Use your private key to sign the data_to_sign string using ECDSA with SHA-256.
  1. Set the Headers:
  • Authorization: Include the authentication method (Secure), your public key, and the signature in Base64, separated by colons.
Authorization: Secure <public_key>:<signature>
  • Date: Include the same timestamp used in data_to_sign.
Date: 2024-10-26T20:58:45Z

Code Examples

import base64
import hashlib
import datetime
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec

public_key = 'your-public-key'
secret_key = 'your-private-key'
uri = 'your-uri'
body_str = 'your-body'

private_key_der = base64.b64decode(secret_key)

private_key = load_der_private_key(
    private_key_der,
    password=None,
    backend=default_backend()
)

body_hash = hashlib.sha256(body_str.encode('utf-8')).hexdigest()

timestamp = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')

data_to_sign = f"{uri}|{body_hash}|{timestamp}"

signature = private_key.sign(
    data_to_sign.encode('utf-8'),
    ec.ECDSA(hashes.SHA256())
)

signature_base64 = base64.b64encode(signature).decode('utf-8')

result = {
    'authorization': f'Secure {public_key}:{signature_base64}',
    'date': timestamp,
    'uri': uri,
    'bodyHash': body_hash,
    'dataToSign': data_to_sign,
    'signature': signature_base64
    }

Important Notes

  • Time Synchronization: Ensure that your system clock is accurate. If the timestamp in the Date header differs by more than 10 minutes from the server's time, the request will be rejected.
  • Timestamp Consistency: The timestamp used in the Date header must be the same as the one used in the signature.
  • URI: Use the path of the request without the domain.
  • Body Hash: Calculate the SHA-256 hash of the request body. If there is no body, use the SHA-256 hash of an empty string.
body_hash = hashlib.sha256(''.encode('utf-8')).hexdigest()

"Simple" Auth Method

Alternatively, you can use a simplified authentication method, which doesn't require signature and the Date header.

In the Authorization header, include the authentication method (Simple), your public key, and your private key, separated by colons.

Authorization: Simple <public_key>:<private_key>
const axios = require('axios');

// Your keys (Base64 encoded)
const publicKeyBase64 = 'YourPublicKeyBase64';
const privateKeyBase64 = 'YourPrivateKeyBase64';

// Request details
const uri = '/v1/7c9h4pwu/folders/';
const body = JSON.stringify({name: 'New Folder'});

// Prepare headers
const headers = {
    Authorization: `Simple ${publicKeyBase64}:${privateKeyBase64}`,
    'Content-Type': 'application/json'
};

// Make request
axios
    .post(`https://api.foxnose.net${uri}`, body, {headers})
        .then((response) => {
            console.log (response.status);
            console.log(response.data);
        })
        .catch((error) => {
            console.error (error.response.status);
            console.error(error.response.data);
});

Security Considerations

When working with authentication methods in FoxNose CMS, consider the following security best practices:

  • Store your private keys securely. Do not share them or expose them in code repositories.
  • Keep access and refresh tokens confidential. Do not log them or expose them to unauthorized parties.
  • Always use HTTPS to ensure that your requests and credentials are encrypted during transmission.
  • Ensure that your system clock is accurate to prevent authentication failures due to timestamp discrepancies.
  • Be aware of token expiration times and refresh tokens as needed.
  • Regularly rotate your API keys and tokens to minimize the risk of compromised credentials.
  • Assign the minimal necessary permissions to API keys and users, following the principle of least privilege.

Was this page helpful?