providers/oauth2: offline access (#8026)

* improve scope check (log when application requests non-configured scopes)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add offline_access special scope

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* ensure scope is set

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update tests for refresh tokens

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* special handling of scopes for github compat

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix spec

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* attempt to fix oidc tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove hardcoded slug

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* check scope from authorization code instead of request

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix injection for consent stage checking incorrectly

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L
2024-01-04 19:57:11 +01:00
committed by GitHub
parent 1b36cb8331
commit 509b502d3c
15 changed files with 369 additions and 171 deletions

View File

@ -14,6 +14,7 @@ from authentik.lib.generators import generate_id, generate_key
from authentik.policies.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding
from authentik.providers.oauth2.constants import (
SCOPE_OFFLINE_ACCESS,
SCOPE_OPENID,
SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE,
@ -80,7 +81,7 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
slug="default-provider-authorization-implicit-consent"
)
provider = OAuth2Provider.objects.create(
name="grafana",
name=generate_id(),
client_type=ClientTypes.CONFIDENTIAL,
client_id=self.client_id,
client_secret=self.client_secret,
@ -90,12 +91,17 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
scope_name__in=[
SCOPE_OPENID,
SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE,
SCOPE_OFFLINE_ACCESS,
]
)
)
provider.save()
Application.objects.create(
name="Grafana",
name=generate_id(),
slug=self.app_slug,
provider=provider,
)
@ -113,12 +119,8 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
"default/flow-default-authentication-flow.yaml",
"default/flow-default-invalidation-flow.yaml",
)
@apply_blueprint(
"default/flow-default-provider-authorization-implicit-consent.yaml",
)
@apply_blueprint(
"system/providers-oauth2.yaml",
)
@apply_blueprint("default/flow-default-provider-authorization-implicit-consent.yaml")
@apply_blueprint("system/providers-oauth2.yaml")
@reconcile_app("authentik_crypto")
def test_authorization_consent_implied(self):
"""test OpenID Provider flow (default authorization flow with implied consent)"""
@ -128,7 +130,7 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
slug="default-provider-authorization-implicit-consent"
)
provider = OAuth2Provider.objects.create(
name="grafana",
name=generate_id(),
client_type=ClientTypes.CONFIDENTIAL,
client_id=self.client_id,
client_secret=self.client_secret,
@ -138,11 +140,16 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
scope_name__in=[
SCOPE_OPENID,
SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE,
SCOPE_OFFLINE_ACCESS,
]
)
)
Application.objects.create(
name="Grafana",
name=generate_id(),
slug=self.app_slug,
provider=provider,
)
@ -174,12 +181,8 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
"default/flow-default-authentication-flow.yaml",
"default/flow-default-invalidation-flow.yaml",
)
@apply_blueprint(
"default/flow-default-provider-authorization-implicit-consent.yaml",
)
@apply_blueprint(
"system/providers-oauth2.yaml",
)
@apply_blueprint("default/flow-default-provider-authorization-implicit-consent.yaml")
@apply_blueprint("system/providers-oauth2.yaml")
@reconcile_app("authentik_crypto")
def test_authorization_logout(self):
"""test OpenID Provider flow with logout"""
@ -189,7 +192,7 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
slug="default-provider-authorization-implicit-consent"
)
provider = OAuth2Provider.objects.create(
name="grafana",
name=generate_id(),
client_type=ClientTypes.CONFIDENTIAL,
client_id=self.client_id,
client_secret=self.client_secret,
@ -199,12 +202,17 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
scope_name__in=[
SCOPE_OPENID,
SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE,
SCOPE_OFFLINE_ACCESS,
]
)
)
provider.save()
Application.objects.create(
name="Grafana",
name=generate_id(),
slug=self.app_slug,
provider=provider,
)
@ -244,12 +252,8 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
"default/flow-default-authentication-flow.yaml",
"default/flow-default-invalidation-flow.yaml",
)
@apply_blueprint(
"default/flow-default-provider-authorization-explicit-consent.yaml",
)
@apply_blueprint(
"system/providers-oauth2.yaml",
)
@apply_blueprint("default/flow-default-provider-authorization-explicit-consent.yaml")
@apply_blueprint("system/providers-oauth2.yaml")
@reconcile_app("authentik_crypto")
def test_authorization_consent_explicit(self):
"""test OpenID Provider flow (default authorization flow with explicit consent)"""
@ -259,7 +263,7 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
slug="default-provider-authorization-explicit-consent"
)
provider = OAuth2Provider.objects.create(
name="grafana",
name=generate_id(),
authorization_flow=authorization_flow,
client_type=ClientTypes.CONFIDENTIAL,
client_id=self.client_id,
@ -269,12 +273,17 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
scope_name__in=[
SCOPE_OPENID,
SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE,
SCOPE_OFFLINE_ACCESS,
]
)
)
provider.save()
app = Application.objects.create(
name="Grafana",
name=generate_id(),
slug=self.app_slug,
provider=provider,
)
@ -323,12 +332,8 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
"default/flow-default-authentication-flow.yaml",
"default/flow-default-invalidation-flow.yaml",
)
@apply_blueprint(
"default/flow-default-provider-authorization-explicit-consent.yaml",
)
@apply_blueprint(
"system/providers-oauth2.yaml",
)
@apply_blueprint("default/flow-default-provider-authorization-explicit-consent.yaml")
@apply_blueprint("system/providers-oauth2.yaml")
@reconcile_app("authentik_crypto")
def test_authorization_denied(self):
"""test OpenID Provider flow (default authorization with access deny)"""
@ -338,7 +343,7 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
slug="default-provider-authorization-explicit-consent"
)
provider = OAuth2Provider.objects.create(
name="grafana",
name=generate_id(),
authorization_flow=authorization_flow,
client_type=ClientTypes.CONFIDENTIAL,
client_id=self.client_id,
@ -348,12 +353,17 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
scope_name__in=[
SCOPE_OPENID,
SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE,
SCOPE_OFFLINE_ACCESS,
]
)
)
provider.save()
app = Application.objects.create(
name="Grafana",
name=generate_id(),
slug=self.app_slug,
provider=provider,
)