Compare commits

...

6 Commits

Author SHA1 Message Date
f059b998cc release: 2023.3.1 2023-03-16 18:09:53 +01:00
3f48202dfe web/flows: fix authenticator selector in dark mode (#4974)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-03-16 16:57:15 +01:00
2a3ebb616b providers/oauth2: fix response for response_type code and response_mode fragment (#4975) 2023-03-16 16:57:09 +01:00
ceab1f732d providers/ldap: fix duplicate attributes (#4972)
closes #4971

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-03-16 12:14:57 +01:00
01d2cce9ca Merge branch 'main' into version-2023.3 2023-03-15 20:20:51 +01:00
72f85defb8 release: 2023.3.0 2023-03-13 18:30:48 +01:00
14 changed files with 87 additions and 17 deletions

View File

@ -1,5 +1,5 @@
[bumpversion] [bumpversion]
current_version = 2023.3.0 current_version = 2023.3.1
tag = True tag = True
commit = True commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+) parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)

View File

@ -12,3 +12,6 @@ indent_size = 2
[*.{yaml,yml}] [*.{yaml,yml}]
indent_size = 2 indent_size = 2
[*.go]
indent_style = tab

View File

@ -2,7 +2,7 @@
from os import environ from os import environ
from typing import Optional from typing import Optional
__version__ = "2023.3.0" __version__ = "2023.3.1"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -355,6 +355,62 @@ class TestAuthorize(OAuthTestCase):
delta=5, delta=5,
) )
def test_full_fragment_code(self):
"""Test full authorization"""
flow = create_test_flow()
provider: OAuth2Provider = OAuth2Provider.objects.create(
name=generate_id(),
client_id="test",
client_secret=generate_key(),
authorization_flow=flow,
redirect_uris="http://localhost",
signing_key=self.keypair,
)
Application.objects.create(name="app", slug="app", provider=provider)
state = generate_id()
user = create_test_admin_user()
self.client.force_login(user)
with patch(
"authentik.providers.oauth2.id_token.get_login_event",
MagicMock(
return_value=Event(
action=EventAction.LOGIN,
context={PLAN_CONTEXT_METHOD: "password"},
created=now(),
)
),
):
# Step 1, initiate params and get redirect to flow
self.client.get(
reverse("authentik_providers_oauth2:authorize"),
data={
"response_type": "code",
"response_mode": "fragment",
"client_id": "test",
"state": state,
"scope": "openid",
"redirect_uri": "http://localhost",
"nonce": generate_id(),
},
)
response = self.client.get(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
)
code: AuthorizationCode = AuthorizationCode.objects.filter(user=user).first()
self.assertJSONEqual(
response.content.decode(),
{
"component": "xak-flow-redirect",
"type": ChallengeTypes.REDIRECT.value,
"to": (f"http://localhost#code={code.code}" f"&state={state}"),
},
)
self.assertAlmostEqual(
code.expires.timestamp() - now().timestamp(),
timedelta_from_string(provider.access_code_validity).total_seconds(),
delta=5,
)
def test_full_form_post_id_token(self): def test_full_form_post_id_token(self):
"""Test full authorization (form_post response)""" """Test full authorization (form_post response)"""
flow = create_test_flow() flow = create_test_flow()

View File

@ -514,7 +514,12 @@ class OAuthFulfillmentStage(StageView):
return urlunsplit(uri) return urlunsplit(uri)
if self.params.response_mode == ResponseMode.FRAGMENT: if self.params.response_mode == ResponseMode.FRAGMENT:
query_fragment = self.create_implicit_response(code) query_fragment = {}
if self.params.grant_type in [GrantTypes.AUTHORIZATION_CODE]:
query_fragment["code"] = code.code
query_fragment["state"] = [str(self.params.state) if self.params.state else ""]
else:
query_fragment = self.create_implicit_response(code)
uri = uri._replace( uri = uri._replace(
fragment=uri.fragment + urlencode(query_fragment, doseq=True), fragment=uri.fragment + urlencode(query_fragment, doseq=True),

View File

@ -32,7 +32,7 @@ services:
volumes: volumes:
- redis:/data - redis:/data
server: server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.3.0} image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.3.1}
restart: unless-stopped restart: unless-stopped
command: server command: server
environment: environment:
@ -50,7 +50,7 @@ services:
- "${AUTHENTIK_PORT_HTTP:-9000}:9000" - "${AUTHENTIK_PORT_HTTP:-9000}:9000"
- "${AUTHENTIK_PORT_HTTPS:-9443}:9443" - "${AUTHENTIK_PORT_HTTPS:-9443}:9443"
worker: worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.3.0} image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.3.1}
restart: unless-stopped restart: unless-stopped
command: worker command: worker
environment: environment:

View File

@ -29,4 +29,4 @@ func UserAgent() string {
return fmt.Sprintf("authentik@%s", FullVersion()) return fmt.Sprintf("authentik@%s", FullVersion())
} }
const VERSION = "2023.3.0" const VERSION = "2023.3.1"

View File

@ -30,11 +30,15 @@ func (pi *ProviderInstance) UserEntry(u api.User) *ldap.Entry {
// Only append attributes that don't already exist // Only append attributes that don't already exist
// TODO: Remove in 2023.3 // TODO: Remove in 2023.3
for _, rawAttr := range rawAttrs { for _, rawAttr := range rawAttrs {
exists := false
for _, attr := range attrs { for _, attr := range attrs {
if !strings.EqualFold(attr.Name, rawAttr.Name) { if strings.EqualFold(attr.Name, rawAttr.Name) {
attrs = append(attrs, rawAttr) exists = true
} }
} }
if !exists {
attrs = append(attrs, rawAttr)
}
} }
if u.IsActive == nil { if u.IsActive == nil {

View File

@ -36,11 +36,15 @@ func (lg *LDAPGroup) Entry() *ldap.Entry {
// Only append attributes that don't already exist // Only append attributes that don't already exist
// TODO: Remove in 2023.3 // TODO: Remove in 2023.3
for _, rawAttr := range rawAttrs { for _, rawAttr := range rawAttrs {
exists := false
for _, attr := range attrs { for _, attr := range attrs {
if !strings.EqualFold(attr.Name, rawAttr.Name) { if strings.EqualFold(attr.Name, rawAttr.Name) {
attrs = append(attrs, rawAttr) exists = true
} }
} }
if !exists {
attrs = append(attrs, rawAttr)
}
} }
objectClass := []string{constants.OCGroup, constants.OCGroupOfUniqueNames, constants.OCGroupOfNames, constants.OCAKGroup, constants.OCPosixGroup} objectClass := []string{constants.OCGroup, constants.OCGroupOfUniqueNames, constants.OCGroupOfNames, constants.OCAKGroup, constants.OCPosixGroup}

View File

@ -105,7 +105,7 @@ filterwarnings = [
[tool.poetry] [tool.poetry]
name = "authentik" name = "authentik"
version = "2023.3.0" version = "2023.3.1"
description = "" description = ""
authors = ["authentik Team <hello@goauthentik.io>"] authors = ["authentik Team <hello@goauthentik.io>"]

View File

@ -1,7 +1,7 @@
openapi: 3.0.3 openapi: 3.0.3
info: info:
title: authentik title: authentik
version: 2023.3.0 version: 2023.3.1
description: Making authentication simple. description: Making authentication simple.
contact: contact:
email: hello@goauthentik.io email: hello@goauthentik.io

View File

@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
export const ERROR_CLASS = "pf-m-danger"; export const ERROR_CLASS = "pf-m-danger";
export const PROGRESS_CLASS = "pf-m-in-progress"; export const PROGRESS_CLASS = "pf-m-in-progress";
export const CURRENT_CLASS = "pf-m-current"; export const CURRENT_CLASS = "pf-m-current";
export const VERSION = "2023.3.0"; export const VERSION = "2023.3.1";
export const TITLE_DEFAULT = "authentik"; export const TITLE_DEFAULT = "authentik";
export const ROUTE_SEPARATOR = ";"; export const ROUTE_SEPARATOR = ";";

View File

@ -37,7 +37,6 @@ import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";
import PFList from "@patternfly/patternfly/components/List/list.css"; import PFList from "@patternfly/patternfly/components/List/list.css";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
import PFTitle from "@patternfly/patternfly/components/Title/title.css"; import PFTitle from "@patternfly/patternfly/components/Title/title.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { import {
ChallengeChoices, ChallengeChoices,
@ -120,7 +119,7 @@ export class FlowExecutor extends Interface implements StageHost {
ws: WebsocketClient; ws: WebsocketClient;
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [PFBase, PFLogin, PFDrawer, PFButton, PFTitle, PFList, PFBackgroundImage].concat(css` return [PFLogin, PFDrawer, PFButton, PFTitle, PFList, PFBackgroundImage].concat(css`
.pf-c-background-image::before { .pf-c-background-image::before {
--pf-c-background-image--BackgroundImage: var(--ak-flow-background); --pf-c-background-image--BackgroundImage: var(--ak-flow-background);
--pf-c-background-image--BackgroundImage-2x: var(--ak-flow-background); --pf-c-background-image--BackgroundImage-2x: var(--ak-flow-background);

View File

@ -16,7 +16,6 @@ import PFForm from "@patternfly/patternfly/components/Form/form.css";
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
import PFTitle from "@patternfly/patternfly/components/Title/title.css"; import PFTitle from "@patternfly/patternfly/components/Title/title.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { import {
AuthenticatorValidationChallenge, AuthenticatorValidationChallenge,
@ -77,7 +76,7 @@ export class AuthenticatorValidateStage
} }
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton].concat(css` return [PFLogin, PFForm, PFFormControl, PFTitle, PFButton].concat(css`
ul { ul {
padding-top: 1rem; padding-top: 1rem;
} }