API reference

class nameko_keycloak.auth.AuthenticationService(keycloak: keycloak.keycloak_openid.KeycloakOpenID, fetch_user: Callable[[str], Optional[Any]])[source]

Provides a way to retrieve properly authenticated user from a request.

As we store user credentials in an external service (Keycloak), this service checks for two things:

  • first, validate access token found in the request

  • if Keycloak confirms the token is valid, look up local User

Only when the user exists in both Keycloak and local database, we consider them authenticated.

get_user_from_access_token(access_token: str) Optional[Any][source]

Find a local User corresponding to Keycloak access token.

get_user_from_request(request: werkzeug.wrappers.request.Request, **kwargs) Optional[Any][source]

Find a local User corresponding to some token in the HTTP request.

class nameko_keycloak.dependencies.KeycloakProvider(*args, **kwargs)[source]
get_dependency(worker_ctx) keycloak.keycloak_openid.KeycloakOpenID[source]

Called before worker execution. A DependencyProvider should return an object to be injected into the worker instance by the container.

setup() None[source]

Called on bound Extensions before the container starts.

Extensions should do any required initialisation here.

class nameko_keycloak.fakes.FakeKeycloak[source]

Fake to be used wherever tests need to interact with Keycloak.

This class emulates a few APIs of KeycloakOpenID that we use for SSO workflow.

We’re working under a very important assumption here: You need to pass user’s email as code when generating their token. This is obviously not true in real life where Keycloak manages generating secure tokens from one-time codes, but here it simplifies a lot.

The Keycloak user database is simulated by a key-value storage where you insert an item when calling token(), and fetch from storage when calling decode_token() or refresh_token().

class nameko_keycloak.service.HookMethod(value)[source]

An enumeration.

class nameko_keycloak.service.KeycloakSsoServiceMixin[source]

Add this to your nameko service to provide SSO authentication with Keycloak.

Expected service dependencies or class attributes:

  • keycloak which must be an instance of KeycloakProvider

  • sso_cookie_prefix - a string that will be used to namespace cookies (useful when there are multiple SSO-enabled apps hosted on same domain)

  • sso_login_url - absolute URL to handler which delegates to keycloak_login_sso()

  • sso_token_url - absolute URL to handler which delegates to keycloak_token_sso()

  • sso_refresh_token_url - absolute URL to handler which delegates to keycloak_refresh_token_sso()

  • frontend_url - absolute URL to a user-facing web app that communicates with this backend service

keycloak_login_sso(request: werkzeug.wrappers.request.Request) werkzeug.wrappers.response.Response[source]

Redirects to SSO login form configured to return back to HTTP service.

keycloak_logout(request: werkzeug.wrappers.request.Request) werkzeug.wrappers.response.Response[source]

Invalidates session in Keycloak and redirects to login form.

Note

Keycloak logout API invalidates only refresh token, not access token. This is by design, as access tokens should be short lived anyway.

keycloak_refresh_token_sso(request: werkzeug.wrappers.request.Request) werkzeug.wrappers.response.Response[source]

Generates a new access token, given a valid refresh token.

keycloak_token_sso(request: werkzeug.wrappers.request.Request) werkzeug.wrappers.response.Response[source]

Handles redirect from successful login in SSO.

The SSO passes a code query string parameter which we then use to generate a OAuth access token. We make sure that a local User exists before they are allowed to reach frontend URL. If all goes well, the access token and several other metadata are stored in cookies.

keycloak_validate_token_sso(request: werkzeug.wrappers.request.Request, token: str) werkzeug.wrappers.response.Response[source]

Checks that access token is valid and a corresponding local User exists.