SSB Guardian Client

PyPI Status Python Version License

Documentation Tests Coverage Quality Gate Status

pre-commit Black Ruff Poetry

Features

  • Maskinporten Integration: Seamless integration with Maskinporten for secure API authentication

  • Guardian Token Management: Automatic retrieval and management of Maskinporten access tokens via Guardian

  • Multi-Environment Support: Works across DEV, TEST, and PROD environments in the Dapla platform

  • Simple API: Easy-to-use client interface for calling external APIs with Maskinporten authentication

  • Automatic Token Handling: Fetches personal tokens automatically using dapla-auth-client

Requirements

  • Python 3.10 or higher

  • Access to Statistics Norway’s Dapla platform

  • Valid Maskinporten client credentials

  • DAPLA_ENVIRONMENT environment variable set to one of: DEV, TEST, or PROD

Installation

You can install SSB Guardian Client via pip from PyPI:

pip install ssb-guardian-client

Usage

Basic Usage

The simplest way to call an external API with Maskinporten authentication:

from ssb_guardian_client import GuardianClient

# Create a GuardianClient instance
client = GuardianClient()

# Call an external API with Maskinporten authentication
response = client.call_api(
    api_endpoint_url="https://api.example.com/data",
    maskinporten_client_id="your-maskinporten-client-id",
    scopes="scope1 scope2",  # Space-separated string
)

# The response contains the JSON data from the API
print(response)

The call_api method automatically:

  • Fetches your personal Keycloak token using dapla-auth-client

  • Requests a Maskinporten access token from Guardian

  • Calls the target API with the Maskinporten token

  • Returns the JSON response

Getting Maskinporten Tokens Directly

If you need more control or only want to retrieve the Maskinporten token:

from ssb_guardian_client import GuardianClient

# Create a GuardianClient instance
client = GuardianClient()

# Get a Maskinporten token for custom use
# Scopes can be passed as either a list or a space-separated string
maskinporten_token = client.get_maskinporten_token(
    maskinporten_client_id="your-client-id",
    scopes=["scope1", "scope2"]  # List of scopes
)

# Or with a space-separated string:
maskinporten_token = client.get_maskinporten_token(
    maskinporten_client_id="your-client-id",
    scopes="scope1 scope2"  # Space-separated string
)

# Use the token for custom API calls
import requests
response = requests.get(
    "https://api.example.com/data",
    headers={"Authorization": f"Bearer {maskinporten_token}"}
)

The get_maskinporten_token method automatically fetches your personal Keycloak token and retrieves the appropriate Guardian URL based on your environment.

📝 Note: Scopes Format

The scopes parameter accepts both formats:

  • ✅ List: ["scope1", "scope2"] or ["elhub:publicstakeholder"]

  • ✅ String: "scope1 scope2" or "elhub:publicstakeholder"

Environment Configuration

The client automatically detects the Dapla environment from the DAPLA_ENVIRONMENT environment variable and uses the appropriate Guardian URL:

  • DEV/TEST: https://guardian.intern.test.ssb.no/maskinporten/access-token

  • PROD: https://guardian.intern.ssb.no/maskinporten/access-token

Make sure the DAPLA_ENVIRONMENT variable is set to one of: DEV, TEST, or PROD.

Complete Example

Here’s a complete example showing typical usage:

import os
from ssb_guardian_client import GuardianClient

# Ensure environment is set (usually already set in Dapla notebooks)
# os.environ["DAPLA_ENVIRONMENT"] = "TEST"

# Create a GuardianClient instance
client = GuardianClient()

# Call an external API
try:
    response = client.call_api(
        api_endpoint_url="https://api.external-service.no/v1/data",
        maskinporten_client_id="my-maskinporten-client",
        scopes="nav:some/scope nav:another/scope",  # Space-separated string
    )

    # Process the response
    for item in response.get("data", []):
        print(item)

except RuntimeError as e:
    print(f"API call failed: {e}")

Please see the [Reference Guide] for details.

Contributing

Contributions are very welcome. To learn more, see the Contributor Guide.

Development

Setting Up a Development Environment

  1. Clone the repository:

    git clone https://github.com/statisticsnorway/ssb-guardian-client.git
    cd ssb-guardian-client
    
  2. Install Poetry if you haven’t already.

  3. Install dependencies:

    poetry install
    
  4. Set up pre-commit hooks:

    poetry run pre-commit install
    

Running Tests

Run tests with pytest:

poetry run pytest

Run tests with coverage:

poetry run coverage run -m pytest
poetry run coverage report

Code Quality

This project uses several tools to maintain code quality:

  • Black: Code formatting

  • Ruff: Linting and code quality checks

  • MyPy: Static type checking

  • pre-commit: Git hooks for automated checks

Run all checks:

poetry run pre-commit run --all-files

License

Distributed under the terms of the MIT license, SSB Guardian Client is free and open source software.

Troubleshooting

Common Issues

ValueError: Unknown environment

  • Ensure the DAPLA_ENVIRONMENT environment variable is set to one of: DEV, TEST, or PROD

RuntimeError: Error getting maskinporten access-token from guardian

  • Verify your Maskinporten client ID and scopes are correct

  • Ensure you have the necessary permissions to use the specified Maskinporten client

  • Check that your Keycloak token is valid

RuntimeError: Error calling target API

  • Verify the API endpoint URL is correct

  • Ensure the Maskinporten scopes match what the API requires

  • Check that the API is accessible from your environment

Issues

If you encounter any problems, please file an issue along with a detailed description.

Credits

This project was generated from Statistics Norway’s SSB PyPI Template.