diff --git a/docs/auth.rst b/docs/auth.rst index 12f08964..311f6524 100644 --- a/docs/auth.rst +++ b/docs/auth.rst @@ -107,6 +107,22 @@ See Okta `Okta OAuth API`_ docs for more info. .. _Okta: https://developer.okta.com/docs/guides/add-an-external-idp/openidconnect/main/ .. _Okta OAuth API: https://developer.okta.com/docs/reference/api/oidc/ +.. _authelia-oauth: + +Authelia OAuth +-------------- + +Flower also supports Authelia OAuth. Before getting started, you need to register Flower in `Authelia`_. +Authelia OAuth is activated by setting :ref:`auth_provider` option to `flower.views.auth.AutheliaLoginHandler`. + +Authelia OAuth requires `oauth2_key`, `oauth2_secret` and `oauth2_redirect_uri` options which should be obtained from Authelia. +Authelia OAuth also uses `FLOWER_OAUTH2_AUTHELIA_BASE_URL` environment variable. + +See Authelia `Authelia OIDC API`_ docs for more info. + +.. _Authelia: https://www.authelia.com/integration/prologue/introduction/ +.. _Authelia OIDC API: https://www.authelia.com/integration/openid-connect/introduction/ + .. _gitlab-oauth: GitLab OAuth diff --git a/flower/views/auth.py b/flower/views/auth.py index b93ad185..f9af98d5 100644 --- a/flower/views/auth.py +++ b/flower/views/auth.py @@ -1,3 +1,4 @@ +from abc import abstractmethod import json import os import re @@ -252,25 +253,29 @@ async def _on_auth(self, user): self.redirect(next_) -class OktaLoginHandler(BaseHandler, tornado.auth.OAuth2Mixin): +class AuthorizationServerLoginHandlerBase(BaseHandler, tornado.auth.OAuth2Mixin): _OAUTH_NO_CALLBACKS = False _OAUTH_SETTINGS_KEY = 'oauth' @property + @abstractmethod def base_url(self): - return os.environ.get('FLOWER_OAUTH2_OKTA_BASE_URL') + pass @property + @abstractmethod def _OAUTH_AUTHORIZE_URL(self): - return f"{self.base_url}/v1/authorize" + pass @property + @abstractmethod def _OAUTH_ACCESS_TOKEN_URL(self): - return f"{self.base_url}/v1/token" + pass @property + @abstractmethod def _OAUTH_USER_INFO_URL(self): - return f"{self.base_url}/v1/userinfo" + pass async def get_access_token(self, redirect_uri, code): body = urlencode({ @@ -349,3 +354,41 @@ async def _on_auth(self, access_token_response): if self.application.options.url_prefix and next_[0] != '/': next_ = '/' + next_ self.redirect(next_) + + +class OktaLoginHandler(AuthorizationServerLoginHandlerBase, tornado.auth.OAuth2Mixin): + + @property + def base_url(self): + return os.environ.get('FLOWER_OAUTH2_OKTA_BASE_URL') + + @property + def _OAUTH_AUTHORIZE_URL(self): + return f"{self.base_url}/v1/authorize" + + @property + def _OAUTH_ACCESS_TOKEN_URL(self): + return f"{self.base_url}/v1/token" + + @property + def _OAUTH_USER_INFO_URL(self): + return f"{self.base_url}/v1/userinfo" + + +class AutheliaLoginHandler(AuthorizationServerLoginHandlerBase, tornado.auth.OAuth2Mixin): + + @property + def base_url(self): + return os.environ.get('FLOWER_OAUTH2_AUTHELIA_BASE_URL') + + @property + def _OAUTH_AUTHORIZE_URL(self): + return f"{self.base_url}/api/oidc/authorization" + + @property + def _OAUTH_ACCESS_TOKEN_URL(self): + return f"{self.base_url}/api/oidc/token" + + @property + def _OAUTH_USER_INFO_URL(self): + return f"{self.base_url}/api/oidc/userinfo"