oauth

Oauth Library.

This library is designed to enable applications to register OAuth2/OIDC clients with an OIDC Provider through the oauth interface.

Getting started

To get started using this library you just need to fetch the library using charmcraft.

Note

You also need to add jsonschema to your charm’s requirements.txt.

cd some-charm
charmcraft fetch-lib charms.hydra.v0.oauth

Then, to initialize the library:

# ...
from charms.hydra.v0.oauth import ClientConfig, OAuthRequirer

OAUTH = "oauth"
OAUTH_SCOPES = "openid email"
OAUTH_GRANT_TYPES = ["authorization_code"]

class SomeCharm(CharmBase):
    def __init__(self, *args):
        # ...
        self.oauth = OAuthRequirer(self, client_config, relation_name=OAUTH)

        self.framework.observe(self.oauth.on.oauth_info_changed, self._configure_application)
        # ...

    def _on_ingress_ready(self, event):
        self.external_url = "https://example.com"
        self._set_client_config()

    def _set_client_config(self):
        client_config = ClientConfig(
            urljoin(self.external_url, "/oauth/callback"),
            OAUTH_SCOPES,
            OAUTH_GRANT_TYPES,
        )
        self.oauth.update_client_config(client_config)
class ClientChangedEvent(
handle: Handle,
redirect_uri: str,
scope: str,
grant_types: list[str],
audience: list[str],
token_endpoint_auth_method: str,
relation_id: int,
client_id: str,
)

Bases: EventBase

Event to notify the Provider charm that the client config changed.

snapshot() dict[str, Any]

Save event.

restore(snapshot: dict[str, Any]) None

Restore event.

to_client_config() ClientConfig

Convert the event information to a ClientConfig object.

class ClientConfig(redirect_uri: str | None, scope: str, grant_types: list[str], audience: list[str] = <factory>, token_endpoint_auth_method: str = 'client_secret_basic', client_id: str | None = None)

Bases: object

Helper class containing a client’s configuration.

redirect_uri: str | None
scope: str
grant_types: list[str]
audience: list[str]
token_endpoint_auth_method: str = 'client_secret_basic'
client_id: str | None = None
validate() None

Validate the client configuration.

to_dict() dict[str, Any]

Convert object to dict.

exception ClientConfigError

Bases: Exception

Emitted when invalid client config is provided.

class ClientCreatedEvent(
handle: Handle,
redirect_uri: str,
scope: str,
grant_types: list[str],
audience: list[str],
token_endpoint_auth_method: str,
relation_id: int,
)

Bases: EventBase

Event to notify the Provider charm to create a new client.

snapshot() dict[str, Any]

Save event.

restore(snapshot: dict[str, Any]) None

Restore event.

to_client_config() ClientConfig

Convert the event information to a ClientConfig object.

class ClientDeletedEvent(handle: Handle, relation_id: int)

Bases: EventBase

Event to notify the Provider charm that the client was deleted.

snapshot() dict[str, Any]

Save event.

restore(snapshot: dict[str, Any]) None

Restore event.

exception DataValidationError

Bases: RuntimeError

Raised when data validation fails on relation data.

class InvalidClientConfigEvent(handle: Handle, error: str)

Bases: EventBase

Event to notify the charm that the client configuration is invalid.

snapshot() dict[str, Any]

Save event.

restore(snapshot: dict[str, Any]) None

Restore event.

class OAuthInfoChangedEvent(
handle: Handle,
client_id: str,
client_secret_id: str,
)

Bases: EventBase

Event to notify the charm that the information in the databag changed.

snapshot() dict[str, Any]

Save event.

restore(snapshot: dict[str, Any]) None

Restore event.

class OAuthInfoRemovedEvent(handle: Handle)

Bases: EventBase

Event to notify the charm that the provider data was removed.

snapshot() dict[str, Any]

Save event.

restore(snapshot: dict[str, Any]) None

Restore event.

class OAuthProvider(charm: CharmBase, relation_name: str = 'oauth')

Bases: OAuthRelation

A provider object for OIDC Providers.

on

Event descriptor for events raised by OAuthProviderEvents.

remove_secret(relation: Relation) None
set_provider_info_in_relation_data(
issuer_url: str,
authorization_endpoint: str,
token_endpoint: str,
introspection_endpoint: str,
userinfo_endpoint: str,
jwks_endpoint: str,
scope: str,
groups: str | None = None,
ca_chain: str | None = None,
jwt_access_token: bool | None = False,
) None

Put the provider information in the databag.

set_client_credentials_in_relation_data(
relation_id: int,
client_id: str,
client_secret: str,
) None

Put the client credentials in the databag.

class OAuthProviderEvents(
parent: Object | None = None,
key: str | None = None,
)

Bases: ObjectEvents

Event descriptor for events raised by OAuthProviderEvents.

client_created

EventSource wraps an event type with a descriptor to facilitate observing and emitting.

It is generally used as:

class SomethingHappened(ops.EventBase):
    pass

class SomeObject(Object):
    something_happened = ops.EventSource(SomethingHappened)

With that, instances of that type will offer the someobj.something_happened attribute which is a BoundEvent, and may be used to emit and observe the event.

client_changed

EventSource wraps an event type with a descriptor to facilitate observing and emitting.

It is generally used as:

class SomethingHappened(ops.EventBase):
    pass

class SomeObject(Object):
    something_happened = ops.EventSource(SomethingHappened)

With that, instances of that type will offer the someobj.something_happened attribute which is a BoundEvent, and may be used to emit and observe the event.

client_deleted

EventSource wraps an event type with a descriptor to facilitate observing and emitting.

It is generally used as:

class SomethingHappened(ops.EventBase):
    pass

class SomeObject(Object):
    something_happened = ops.EventSource(SomethingHappened)

With that, instances of that type will offer the someobj.something_happened attribute which is a BoundEvent, and may be used to emit and observe the event.

class OAuthRequirer(
charm: CharmBase,
client_config: ClientConfig | None = None,
relation_name: str = 'oauth',
)

Bases: OAuthRelation

Register an oauth client.

on

Event descriptor for events raised by OAuthRequirerEvents.

is_client_created(relation_id: int | None = None) bool | None

Check if the client has been created.

get_provider_info(
relation_id: int | None = None,
) OauthProviderConfig | None

Get the provider information from the databag.

get_client_secret(client_secret_id: str) Secret

Get the client_secret.

update_client_config(
client_config: ClientConfig,
relation_id: int | None = None,
) None

Update the client config stored in the object.

class OAuthRequirerEvents(
parent: Object | None = None,
key: str | None = None,
)

Bases: ObjectEvents

Event descriptor for events raised by OAuthRequirerEvents.

oauth_info_changed

EventSource wraps an event type with a descriptor to facilitate observing and emitting.

It is generally used as:

class SomethingHappened(ops.EventBase):
    pass

class SomeObject(Object):
    something_happened = ops.EventSource(SomethingHappened)

With that, instances of that type will offer the someobj.something_happened attribute which is a BoundEvent, and may be used to emit and observe the event.

oauth_info_removed

EventSource wraps an event type with a descriptor to facilitate observing and emitting.

It is generally used as:

class SomethingHappened(ops.EventBase):
    pass

class SomeObject(Object):
    something_happened = ops.EventSource(SomethingHappened)

With that, instances of that type will offer the someobj.something_happened attribute which is a BoundEvent, and may be used to emit and observe the event.

invalid_client_config

EventSource wraps an event type with a descriptor to facilitate observing and emitting.

It is generally used as:

class SomethingHappened(ops.EventBase):
    pass

class SomeObject(Object):
    something_happened = ops.EventSource(SomethingHappened)

With that, instances of that type will offer the someobj.something_happened attribute which is a BoundEvent, and may be used to emit and observe the event.

class OauthProviderConfig(
issuer_url: str,
authorization_endpoint: str,
token_endpoint: str,
introspection_endpoint: str,
userinfo_endpoint: str,
jwks_endpoint: str,
scope: str,
client_id: str | None = None,
client_secret: str | None = None,
groups: str | None = None,
ca_chain: str | None = None,
jwt_access_token: bool | None = False,
)

Bases: object

Helper class containing provider’s configuration.

issuer_url: str
authorization_endpoint: str
token_endpoint: str
introspection_endpoint: str
userinfo_endpoint: str
jwks_endpoint: str
scope: str
client_id: str | None = None
client_secret: str | None = None
groups: str | None = None
ca_chain: str | None = None
jwt_access_token: bool | None = False
classmethod from_dict(
dic: dict[str, Any],
) OauthProviderConfig

Generate OauthProviderConfig instance from dict.