providers/oauth2: accept token as post param

This commit is contained in:
Jens Langhammer 2020-09-16 23:31:16 +02:00
parent 818f417fd8
commit 4b39c71de0
8 changed files with 50 additions and 22 deletions

View File

@ -1,6 +1,8 @@
"""Proxy and Outpost e2e tests""" """Proxy and Outpost e2e tests"""
from sys import platform
from time import sleep from time import sleep
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
from unittest.case import skipUnless
from docker.client import DockerClient, from_env from docker.client import DockerClient, from_env
from docker.models.containers import Container from docker.models.containers import Container
@ -14,6 +16,7 @@ from passbook.outposts.models import Outpost, OutpostDeploymentType, OutpostType
from passbook.providers.proxy.models import ProxyProvider from passbook.providers.proxy.models import ProxyProvider
@skipUnless(platform.startswith("linux"), "requires local docker")
class TestProviderProxy(SeleniumTestCase): class TestProviderProxy(SeleniumTestCase):
"""Proxy and Outpost e2e tests""" """Proxy and Outpost e2e tests"""

View File

@ -17,7 +17,6 @@ from docker.models.containers import Container
from selenium import webdriver from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.remote.webdriver import WebDriver from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from structlog import get_logger from structlog import get_logger
@ -91,7 +90,7 @@ class SeleniumTestCase(StaticLiveServerTestCase):
def wait_for_url(self, desired_url): def wait_for_url(self, desired_url):
"""Wait until URL is `desired_url`.""" """Wait until URL is `desired_url`."""
self.wait.until( self.wait.until(
ec.url_to_be(desired_url), lambda driver: driver.current_url == desired_url,
f"URL {self.driver.current_url} doesn't match expected URL {desired_url}", f"URL {self.driver.current_url} doesn't match expected URL {desired_url}",
) )

View File

@ -3,6 +3,8 @@ from django.apps.registry import Apps
from django.db import migrations, models from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor from django.db.backends.base.schema import BaseDatabaseSchemaEditor
import passbook.core.models
def create_default_admin_group(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): def create_default_admin_group(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
db_alias = schema_editor.connection.alias db_alias = schema_editor.connection.alias
@ -42,9 +44,6 @@ class Migration(migrations.Migration):
), ),
migrations.RunPython(create_default_admin_group), migrations.RunPython(create_default_admin_group),
migrations.AlterModelManagers( migrations.AlterModelManagers(
name='user', name="user", managers=[("objects", passbook.core.models.UserManager()),],
managers=[
('objects', passbook.core.models.UserManager()),
],
), ),
] ]

View File

@ -6,18 +6,39 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('passbook_providers_oauth2', '0002_oauth2provider_sub_mode'), ("passbook_providers_oauth2", "0002_oauth2provider_sub_mode"),
] ]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='oauth2provider', model_name="oauth2provider",
name='client_type', name="client_type",
field=models.CharField(choices=[('confidential', 'Confidential'), ('public', 'Public')], default='confidential', help_text='Confidential clients are capable of maintaining the confidentiality\n of their credentials. Public clients are incapable.', max_length=30, verbose_name='Client Type'), field=models.CharField(
choices=[("confidential", "Confidential"), ("public", "Public")],
default="confidential",
help_text="Confidential clients are capable of maintaining the confidentiality\n of their credentials. Public clients are incapable.",
max_length=30,
verbose_name="Client Type",
),
), ),
migrations.AlterField( migrations.AlterField(
model_name='oauth2provider', model_name="oauth2provider",
name='response_type', name="response_type",
field=models.TextField(choices=[('code', 'code (Authorization Code Flow)'), ('code_adfs', 'code (ADFS Compatibility Mode, sends id_token as access_token)'), ('id_token', 'id_token (Implicit Flow)'), ('id_token token', 'id_token token (Implicit Flow)'), ('code token', 'code token (Hybrid Flow)'), ('code id_token', 'code id_token (Hybrid Flow)'), ('code id_token token', 'code id_token token (Hybrid Flow)')], default='code', help_text='Response Type required by the client.'), field=models.TextField(
choices=[
("code", "code (Authorization Code Flow)"),
(
"code_adfs",
"code (ADFS Compatibility Mode, sends id_token as access_token)",
),
("id_token", "id_token (Implicit Flow)"),
("id_token token", "id_token token (Implicit Flow)"),
("code token", "code token (Hybrid Flow)"),
("code id_token", "code id_token (Hybrid Flow)"),
("code id_token token", "code id_token token (Hybrid Flow)"),
],
default="code",
help_text="Response Type required by the client.",
),
), ),
] ]

View File

@ -70,7 +70,10 @@ class ResponseTypes(models.TextChoices):
"""Response Type required by the client.""" """Response Type required by the client."""
CODE = "code", _("code (Authorization Code Flow)") CODE = "code", _("code (Authorization Code Flow)")
CODE_ADFS = "code_adfs", _("code (ADFS Compatibility Mode, sends id_token as access_token)") CODE_ADFS = (
"code_adfs",
_("code (ADFS Compatibility Mode, sends id_token as access_token)"),
)
ID_TOKEN = "id_token", _("id_token (Implicit Flow)") ID_TOKEN = "id_token", _("id_token (Implicit Flow)")
ID_TOKEN_TOKEN = "id_token token", _("id_token token (Implicit Flow)") ID_TOKEN_TOKEN = "id_token token", _("id_token token (Implicit Flow)")
CODE_TOKEN = "code token", _("code token (Hybrid Flow)") CODE_TOKEN = "code token", _("code token (Hybrid Flow)")

View File

@ -61,11 +61,12 @@ def extract_access_token(request: HttpRequest) -> str:
auth_header = request.META.get("HTTP_AUTHORIZATION", "") auth_header = request.META.get("HTTP_AUTHORIZATION", "")
if re.compile(r"^[Bb]earer\s{1}.+$").match(auth_header): if re.compile(r"^[Bb]earer\s{1}.+$").match(auth_header):
access_token = auth_header.split()[1] return auth_header.split()[1]
else: if "access_token" in request.POST:
access_token = request.GET.get("access_token", "") return request.POST.get("access_token")
if "access_token" in request.GET:
return access_token return request.GET.get("access_token")
return ""
def extract_client_auth(request: HttpRequest) -> Tuple[str, str]: def extract_client_auth(request: HttpRequest) -> Tuple[str, str]:

View File

@ -17,7 +17,8 @@ from passbook.providers.oauth2.errors import TokenError, UserAuthError
from passbook.providers.oauth2.models import ( from passbook.providers.oauth2.models import (
AuthorizationCode, AuthorizationCode,
OAuth2Provider, OAuth2Provider,
RefreshToken, ResponseTypes, RefreshToken,
ResponseTypes,
) )
from passbook.providers.oauth2.utils import TokenResponse, extract_client_auth from passbook.providers.oauth2.utils import TokenResponse, extract_client_auth

View File

@ -6605,8 +6605,8 @@ definitions:
client_type: client_type:
title: Client Type title: Client Type
description: |- description: |-
<b>Confidential</b> clients are capable of maintaining the confidentiality Confidential clients are capable of maintaining the confidentiality
of their credentials. <b>Public</b> clients are incapable. of their credentials. Public clients are incapable.
type: string type: string
enum: enum:
- confidential - confidential
@ -6626,6 +6626,7 @@ definitions:
type: string type: string
enum: enum:
- code - code
- code_adfs
- id_token - id_token
- id_token token - id_token token
- code token - code token