Merge branch 'main' into force-authn-saml-provider

This commit is contained in:
Connor Peshek
2026-06-09 15:42:36 -05:00
committed by GitHub
701 changed files with 16019 additions and 6055 deletions
+25 -17
View File
@@ -20,12 +20,22 @@ runs:
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.token }}
# Untrusted/event-derived values are passed via the environment (never
# interpolated into the script body) to avoid template injection.
EVENT_NAME: ${{ github.event_name }}
REPOSITORY: ${{ github.repository }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
LABEL_NAME_CTX: ${{ github.event.label.name }}
PR_NUMBER_CTX: ${{ github.event.pull_request.number }}
MERGE_COMMIT_SHA_CTX: ${{ github.event.pull_request.merge_commit_sha }}
EVENT_ACTION: ${{ github.event.action }}
PR_MERGED_CTX: ${{ github.event.pull_request.merged }}
run: |
set -e -o pipefail
# For issues events, check if it's actually a PR
if [ "${{ github.event_name }}" = "issues" ]; then
if [ "$EVENT_NAME" = "issues" ]; then
# Check if this issue is actually a PR
PR_DATA=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }} 2>/dev/null || echo "null")
PR_DATA=$(gh api "repos/${REPOSITORY}/pulls/${ISSUE_NUMBER}" 2>/dev/null || echo "null")
if [ "$PR_DATA" = "null" ]; then
echo "should_run=false" >> $GITHUB_OUTPUT
echo "reason=not_a_pr" >> $GITHUB_OUTPUT
@@ -35,11 +45,11 @@ runs:
# Get PR data
PR_MERGED=$(echo "$PR_DATA" | jq -r '.merged')
PR_NUMBER="${{ github.event.issue.number }}"
PR_NUMBER="$ISSUE_NUMBER"
MERGE_COMMIT_SHA=$(echo "$PR_DATA" | jq -r '.merge_commit_sha')
# Check if it's a backport label
LABEL_NAME="${{ github.event.label.name }}"
LABEL_NAME="$LABEL_NAME_CTX"
if [[ "$LABEL_NAME" =~ ^backport/(.+)$ ]]; then
if [ "$PR_MERGED" = "true" ]; then
echo "should_run=true" >> $GITHUB_OUTPUT
@@ -61,11 +71,11 @@ runs:
fi
# For pull_request and pull_request_target events
PR_NUMBER="${{ github.event.pull_request.number }}"
MERGE_COMMIT_SHA="${{ github.event.pull_request.merge_commit_sha }}"
PR_NUMBER="$PR_NUMBER_CTX"
MERGE_COMMIT_SHA="$MERGE_COMMIT_SHA_CTX"
# Case 1: PR was just merged (closed + merged = true)
if [ "${{ github.event.action }}" = "closed" ] && [ "${{ github.event.pull_request.merged }}" = "true" ]; then
if [ "$EVENT_ACTION" = "closed" ] && [ "$PR_MERGED_CTX" = "true" ]; then
echo "should_run=true" >> $GITHUB_OUTPUT
echo "reason=pr_merged" >> $GITHUB_OUTPUT
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
@@ -74,12 +84,12 @@ runs:
fi
# Case 2: Label was added
if [ "${{ github.event.action }}" = "labeled" ]; then
LABEL_NAME="${{ github.event.label.name }}"
if [ "$EVENT_ACTION" = "labeled" ]; then
LABEL_NAME="$LABEL_NAME_CTX"
# Check if it's a backport label
if [[ "$LABEL_NAME" =~ ^backport/(.+)$ ]]; then
# Check if PR is already merged
if [ "${{ github.event.pull_request.merged }}" = "true" ]; then
if [ "$PR_MERGED_CTX" = "true" ]; then
echo "should_run=true" >> $GITHUB_OUTPUT
echo "reason=label_added_to_merged_pr" >> $GITHUB_OUTPUT
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
@@ -117,17 +127,14 @@ runs:
GITHUB_TOKEN: ${{ inputs.token }}
PR_NUMBER: ${{ steps.should_run.outputs.pr_number }}
REASON: ${{ steps.should_run.outputs.reason }}
EVENT_NAME: ${{ github.event_name }}
LABEL_NAME_CTX: ${{ github.event.label.name }}
run: |
set -e -o pipefail
# Determine which labels to process
if [ "${REASON}" = "label_added_to_merged_pr" ]; then
# Only process the specific label that was just added
if [ "${{ github.event_name }}" = "issues" ]; then
LABEL_NAME="${{ github.event.label.name }}"
else
LABEL_NAME="${{ github.event.label.name }}"
fi
LABEL_NAME="$LABEL_NAME_CTX"
if [[ "$LABEL_NAME" =~ ^backport/(.+)$ ]]; then
echo "labels=$LABEL_NAME" >> $GITHUB_OUTPUT
@@ -150,10 +157,11 @@ runs:
PR_TITLE: ${{ github.event.pull_request.title }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
LABELS: '${{ steps.pr_details.outputs.labels }}'
REASON: '${{ steps.should_run.outputs.reason }}'
run: |
set -e -o pipefail
echo "Processing PR #$PR_NUMBER (reason: ${{ steps.should_run.outputs.reason }})"
echo "Processing PR #$PR_NUMBER (reason: ${REASON})"
echo "Found backport labels: $LABELS"
# Process each backport label
+3 -3
View File
@@ -37,7 +37,7 @@ runs:
sudo rsync -a --delete /tmp/empty/ /usr/local/lib/android/
- name: Install uv
if: ${{ contains(inputs.dependencies, 'python') }}
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v5
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v5
with:
enable-cache: true
- name: Setup python
@@ -64,7 +64,7 @@ runs:
rustflags: ""
- name: Setup rust dependencies
if: ${{ contains(inputs.dependencies, 'rust') }}
uses: taiki-e/install-action@f48d2f8ba2b452934c948b7be1a768079c3632ff # v2
uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e # v2
with:
tool: cargo-deny cargo-machete cargo-llvm-cov nextest
- name: Setup node (root, web)
@@ -79,7 +79,7 @@ runs:
go-version-file: "${{ inputs.working-directory }}go.mod"
- name: Setup docker cache
if: ${{ contains(inputs.dependencies, 'runtime') }}
uses: AndreKurait/docker-cache@0fe76702a40db986d9663c24954fc14c6a6031b7
uses: AndreKurait/docker-cache@7a3887908bdb97935395833df69b060cfcca0f7f
with:
key: docker-images-${{ runner.os }}-${{ hashFiles('.github/actions/setup/compose.yml', 'Makefile') }}-${{ inputs.postgresql_version }}
- name: Setup dependencies
+2 -2
View File
@@ -10,12 +10,12 @@ inputs:
runs:
using: "composite"
steps:
- uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v5
- uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v5
with:
files: ${{ inputs.files }}
flags: ${{ inputs.flags }}
use_oidc: true
- uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v5
- uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v5
with:
files: ${{ inputs.files }}
flags: ${{ inputs.flags }}
+13 -25
View File
@@ -1,38 +1,26 @@
<!--
👋 Hi there! Welcome.
👋 Hi there! Welcome. Please check the contributing guidelines: https://docs.goauthentik.io/docs/developer-docs/#how-can-i-contribute
Please check the Contributing guidelines: https://docs.goauthentik.io/docs/developer-docs/#how-can-i-contribute
⚠️ IMPORTANT: Make sure you are opening this PR from a FEATURE BRANCH, not from your main branch!
If you opened this PR from your main branch, please close it and create a new feature branch instead.
For more information, see: https://docs.goauthentik.io/developer-docs/contributing/#always-use-feature-branches
⚠️ Open this PR from a feature branch, not from main: https://docs.goauthentik.io/developer-docs/contributing/#always-use-feature-branches
-->
## Details
<!--
Explain what this PR changes, what the rationale behind the change is, if any new requirements are introduced or any breaking changes caused by this PR.
### What does this PR change?
Ideally also link an Issue for context that this PR will close using `closes #`
### Why is this change needed?
### How was this tested?
### Linked issues
<!--
Use `closes #N` to auto-close an issue on merge. Use `refs #N` for related issues that this PR does not close.
-->
REPLACE ME
---
## Checklist
- [ ] Local tests pass (`ak test authentik/`)
- [ ] The code has been formatted (`make lint-fix`)
If an API change has been made
- [ ] The API schema and clients have been updated (`make gen`)
If changes to the frontend have been made
- [ ] The code has been formatted (`make web`)
If applicable
- [ ] The documentation has been updated
- [ ] The documentation has been formatted (`make docs`)
- [ ] The project has been linted, built, and tested (`make all`)
- [ ] The documentation has been updated and formatted (`make docs`)
@@ -42,8 +42,8 @@ jobs:
# Needed for checkout
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: prepare variables
uses: ./.github/actions/docker-push-variables
+4 -4
View File
@@ -36,7 +36,7 @@ jobs:
with:
image_name: ${{ inputs.image_name }}
image_arch: arm64
runs-on: ubuntu-22.04-arm
runs-on: ubuntu-24.04-arm
registry_dockerhub: ${{ inputs.registry_dockerhub }}
registry_ghcr: ${{ inputs.registry_ghcr }}
release: ${{ inputs.release }}
@@ -49,7 +49,7 @@ jobs:
tags: ${{ steps.ev.outputs.imageTagsJSON }}
shouldPush: ${{ steps.ev.outputs.shouldPush }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev
@@ -69,7 +69,7 @@ jobs:
matrix:
tag: ${{ fromJson(needs.get-tags.outputs.tags) }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev
@@ -90,7 +90,7 @@ jobs:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: int128/docker-manifest-create-action@b9d644eaa3312dd895ffdafb19333a7b266e6ba9 # v2
- uses: int128/docker-manifest-create-action@126c2b2195800ebc112cffe9ad6c2e2cce16eff2 # v2
id: build
with:
tags: ${{ matrix.tag }}
+3 -3
View File
@@ -21,7 +21,7 @@ jobs:
command:
- prettier-check
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: ./.github/actions/setup-node
with:
working-directory: website
@@ -31,7 +31,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: ./.github/actions/setup-node
with:
working-directory: website
@@ -60,7 +60,7 @@ jobs:
- lint
- build
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v5
with:
name: api-docs
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
check-changes-applied:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Setup authentik env
uses: ./.github/actions/setup
- uses: ./.github/actions/setup-node
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Setup authentik env
uses: ./.github/actions/setup
- name: generate docs
+5 -5
View File
@@ -23,7 +23,7 @@ jobs:
command:
- prettier-check
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: ./.github/actions/setup-node
with:
working-directory: website
@@ -34,7 +34,7 @@ jobs:
env:
NODE_ENV: production
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: ./.github/actions/setup-node
name: Setup Node.js
with:
@@ -46,7 +46,7 @@ jobs:
env:
NODE_ENV: production
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: ./.github/actions/setup-node
with:
working-directory: website
@@ -61,11 +61,11 @@ jobs:
id-token: write
attestations: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: prepare variables
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
- version-2026-2
- version-2026-5
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- run: |
set -euo pipefail
current="$(pwd)"
+10 -10
View File
@@ -51,7 +51,7 @@ jobs:
deps: rust-nightly
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Setup authentik env
uses: ./.github/actions/setup
with:
@@ -61,7 +61,7 @@ jobs:
test-gen:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Setup authentik env
@@ -77,7 +77,7 @@ jobs:
test-migrations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Setup authentik env
uses: ./.github/actions/setup
- name: run migrations
@@ -103,7 +103,7 @@ jobs:
- 18-alpine
run_id: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
fetch-depth: 0
- name: checkout stable
@@ -179,7 +179,7 @@ jobs:
- 18-alpine
run_id: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Setup authentik env
uses: ./.github/actions/setup
with:
@@ -199,7 +199,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Create k8s Kind Cluster
@@ -252,7 +252,7 @@ jobs:
glob: tests/e2e/test_endpoints_*
profiles: selenium
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Setup e2e env
@@ -306,7 +306,7 @@ jobs:
- name: ssf_transmitter
glob: tests/openid_conformance/test_ssf_transmitter.py
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Setup e2e env (chrome, etc)
@@ -348,7 +348,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Setup authentik env
uses: ./.github/actions/setup
with:
@@ -407,7 +407,7 @@ jobs:
pull-requests: write
timeout-minutes: 120
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: prepare variables
+5 -5
View File
@@ -21,7 +21,7 @@ jobs:
lint-golint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version-file: "go.mod"
@@ -40,7 +40,7 @@ jobs:
test-unittest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version-file: "go.mod"
@@ -82,11 +82,11 @@ jobs:
id-token: write
attestations: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: prepare variables
@@ -139,7 +139,7 @@ jobs:
goos: [linux]
goarch: [amd64, arm64]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
ref: ${{ github.event.pull_request.head.sha }}
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
+3 -3
View File
@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: ./.github/actions/setup-node
with:
working-directory: web
@@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: ./.github/actions/setup-node
with:
working-directory: web
@@ -59,7 +59,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: ./.github/actions/setup-node
with:
working-directory: web
+2 -2
View File
@@ -31,9 +31,9 @@ jobs:
- id: generate_token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v2
with:
app-id: ${{ secrets.GH_APP_ID }}
client-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIV_KEY }}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
token: ${{ steps.generate_token.outputs.token }}
- name: Compress images
@@ -18,9 +18,9 @@ jobs:
- id: generate_token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v2
with:
app-id: ${{ secrets.GH_APP_ID }}
client-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIV_KEY }}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
token: ${{ steps.generate_token.outputs.token }}
- name: Setup authentik env
+2 -2
View File
@@ -13,11 +13,11 @@ jobs:
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v2
if: ${{ env.GH_APP_ID != '' }}
with:
app-id: ${{ secrets.GH_APP_ID }}
client-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIV_KEY }}
env:
GH_APP_ID: ${{ secrets.GH_APP_ID }}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
if: ${{ steps.app-token.outcome != 'skipped' }}
with:
fetch-depth: 0
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Cleanup
run: |
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
app-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIV_KEY }}
- name: Delete 'dev' containers older than a week
uses: snok/container-retention-policy@3b0972b2276b171b212f8c4efbca59ebba26eceb # v3.0.1
uses: snok/container-retention-policy@d3bdcf5ce9b05f685154e4a16c39233b245e3d53 # v3.1.0
with:
image-names: dev-server,dev-ldap,dev-proxy
image-tags: "!gh-next,!gh-main"
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
- packages/logger-js
- packages/esbuild-plugin-live-reload
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
fetch-depth: 2
- uses: ./.github/actions/setup-node
+4 -4
View File
@@ -24,14 +24,14 @@ jobs:
language: ["go", "javascript", "python"]
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Initialize CodeQL
uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
with:
# Block PRs that introduce a *new* dependency with a known
+1 -1
View File
@@ -26,5 +26,5 @@ jobs:
image: semgrep/semgrep
if: (github.actor != 'dependabot[bot]')
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- run: semgrep ci
+4 -4
View File
@@ -31,10 +31,10 @@ jobs:
name: Generate app token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v2
with:
app-id: ${{ secrets.GH_APP_ID }}
client-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIV_KEY }}
- name: Checkout main
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
ref: main
token: "${{ steps.app-token.outputs.token }}"
@@ -59,10 +59,10 @@ jobs:
- id: generate_token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v2
with:
app-id: ${{ secrets.GH_APP_ID }}
client-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIV_KEY }}
- name: Checkout main
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
ref: main
token: ${{ steps.generate_token.outputs.token }}
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
environment: internal-production
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
ref: main
- run: |
+10 -10
View File
@@ -31,9 +31,9 @@ jobs:
id-token: write
attestations: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: prepare variables
@@ -83,7 +83,7 @@ jobs:
- radius
- rac
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version-file: "go.mod"
@@ -91,7 +91,7 @@ jobs:
with:
working-directory: web
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: prepare variables
@@ -145,7 +145,7 @@ jobs:
goos: [linux, darwin]
goarch: [amd64, arm64]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version-file: "go.mod"
@@ -182,8 +182,8 @@ jobs:
AWS_REGION: eu-central-1
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0
with:
role-to-assume: "arn:aws:iam::016170277896:role/github_goauthentik_authentik"
aws-region: ${{ env.AWS_REGION }}
@@ -198,7 +198,7 @@ jobs:
- build-outpost-binary
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: Run test suite in final docker images
run: |
echo "PG_PASS=$(openssl rand 32 | base64 -w 0)" >> lifecycle/container/.env
@@ -214,7 +214,7 @@ jobs:
- build-outpost-binary
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev
@@ -228,7 +228,7 @@ jobs:
container=$(docker container create ${{ steps.ev.outputs.imageMainName }})
docker cp ${container}:web/ .
- name: Create a Sentry.io release
uses: getsentry/action-release@5657c9e888b4e2cc85f4d29143ea4131fde4a73a # v3
uses: getsentry/action-release@ff07929a6537bac57790c3451cf4d364aca38528 # v3
continue-on-error: true
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
+7 -7
View File
@@ -52,7 +52,7 @@ jobs:
needs:
- check-inputs
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
ref: "version-${{ needs.check-inputs.outputs.major_version }}"
- name: Setup authentik env
@@ -69,14 +69,14 @@ jobs:
name: Generate app token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v2
with:
app-id: ${{ secrets.GH_APP_ID }}
client-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIV_KEY }}
- id: get-user-id
name: Get GitHub app user ID
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: "${{ steps.app-token.outputs.token }}"
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
ref: "version-${{ needs.check-inputs.outputs.major_version }}"
token: "${{ steps.app-token.outputs.token }}"
@@ -121,7 +121,7 @@ jobs:
name: Generate app token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v2
with:
app-id: ${{ secrets.GH_APP_ID }}
client-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIV_KEY }}
repositories: helm
- id: get-user-id
@@ -129,7 +129,7 @@ jobs:
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: "${{ steps.app-token.outputs.token }}"
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
repository: "${{ github.repository_owner }}/helm"
token: "${{ steps.app-token.outputs.token }}"
@@ -163,7 +163,7 @@ jobs:
name: Generate app token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v2
with:
app-id: ${{ secrets.GH_APP_ID }}
client-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIV_KEY }}
repositories: version
- id: get-user-id
@@ -171,7 +171,7 @@ jobs:
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: "${{ steps.app-token.outputs.token }}"
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
with:
repository: "${{ github.repository_owner }}/version"
token: "${{ steps.app-token.outputs.token }}"
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
- id: generate_token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v2
with:
app-id: ${{ secrets.GH_APP_ID }}
client-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIV_KEY }}
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10
with:
@@ -23,13 +23,13 @@ jobs:
if: ${{ github.event_name != 'pull_request' }}
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v2
with:
app-id: ${{ secrets.GH_APP_ID }}
client-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIV_KEY }}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
if: ${{ github.event_name != 'pull_request' }}
with:
token: ${{ steps.generate_token.outputs.token }}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v5
if: ${{ github.event_name == 'pull_request' }}
- name: Setup authentik env
uses: ./.github/actions/setup
+4
View File
@@ -20,6 +20,10 @@ corepack.tgz
.cspellcache
cspell-report.*
# Release generation artifacts
/changelog.md
/diff.md
# If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/
# in your Git repository. Update and uncomment the following line accordingly.
# <django-project-name>/staticfiles/
Generated
+4 -4
View File
@@ -2925,9 +2925,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "reqwest"
version = "0.13.3"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0"
checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3"
dependencies = [
"base64 0.22.1",
"bytes",
@@ -4346,9 +4346,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.23.1"
version = "1.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7"
dependencies = [
"getrandom 0.4.2",
"js-sys",
+2 -2
View File
@@ -51,7 +51,7 @@ pin-project-lite = "= 0.2.17"
pyo3 = "= 0.28.3"
pyo3-build-config = "= 0.28.3"
regex = "= 1.12.3"
reqwest = { version = "= 0.13.3", features = [
reqwest = { version = "= 0.13.4", features = [
"form",
"json",
"multipart",
@@ -112,7 +112,7 @@ tracing-subscriber = { version = "= 0.3.23", features = [
"tracing-log",
] }
url = "= 2.5.8"
uuid = { version = "= 1.23.1", features = ["serde", "v4"] }
uuid = { version = "= 1.23.2", features = ["serde", "v4"] }
which = "= 8.0.2"
ak-axum = { package = "authentik-axum", version = "2026.8.0-rc1", path = "./packages/ak-axum" }
+4 -4
View File
@@ -73,7 +73,7 @@ rust-test: ## Run the Rust tests
$(CARGO) nextest run --workspace
test: ## Run the server tests and produce a coverage report (locally)
$(UV) run coverage run manage.py test --keepdb $(or $(filter-out $@,$(MAKECMDGOALS)),authentik)
$(UV) run coverage run manage.py test --keepdb $(or $(filter-out $@ all,$(MAKECMDGOALS)),authentik)
$(UV) run coverage combine
$(UV) run coverage html
$(UV) run coverage report
@@ -186,7 +186,7 @@ gen-changelog: ## (Release) generate the changelog based from the commits since
git log --pretty=format:"- %s" $(shell git merge-base ${last_version} ${current_commit})...${current_commit} > merged_to_current
git log --pretty=format:"- %s" $(shell git merge-base ${last_version} ${current_commit})...${last_version} > merged_to_last
grep -Eo 'cherry-pick (#\d+)' merged_to_last | cut -d ' ' -f 2 | sed 's/.*/(&)$$/' > cherry_picked_to_last
grep -vf cherry_picked_to_last merged_to_current | sort > changelog.md
grep -vf cherry_picked_to_last merged_to_current | grep -vE '^- (ci:|website)' | sort > changelog.md
rm merged_to_current
rm merged_to_last
rm cherry_picked_to_last
@@ -201,8 +201,8 @@ gen-diff: ## (Release) generate the changelog diff between the current schema a
/local/schema-old.yml \
/local/schema.yml
rm schema-old.yml
$(SED_INPLACE) 's/{/&#123;/g' diff.md
$(SED_INPLACE) 's/}/&#125;/g' diff.md
$(SED_INPLACE) 's/{/\&#123;/g' diff.md
$(SED_INPLACE) 's/}/\&#125;/g' diff.md
npx prettier --write diff.md
gen-client-go: ## Build and install the authentik API for Golang
+39 -1
View File
@@ -323,6 +323,42 @@ class Importer:
serializer.instance = model_instance
return serializer
def _save_with_retry(
self, serializer: BaseSerializer, entry: BlueprintEntry, raise_errors: bool
) -> Model | None:
"""Save a serializer, retrying once on IntegrityError by re-fetching the existing instance.
Returns the saved instance, or None when recovery failed and raise_errors is False.
Raises EntryInvalidError / IntegrityError when raise_errors is True and recovery
is not possible.
"""
try:
with atomic():
return serializer.save()
except IntegrityError:
self.logger.debug(
"Integrity error during save, retrying after re-fetching instance",
entry=entry,
)
# Race condition: another process committed the same object between our
# SELECT and INSERT. Re-validate so we pick up the now-existing instance.
try:
retry_serializer = self._validate_single(entry)
except EntryInvalidError as exc:
self.logger.warning(f"Entry invalid on retry: {exc}", entry=entry, error=exc)
if raise_errors:
raise exc
return None
if not retry_serializer:
return None
try:
return retry_serializer.save()
except IntegrityError:
self.logger.warning("Integrity error persists on retry", entry=entry)
if raise_errors:
raise
return None
def _apply_permissions(self, instance: Model, entry: BlueprintEntry):
"""Apply object-level permissions for an entry"""
for perm in entry.get_permissions(self._import):
@@ -393,7 +429,9 @@ class Importer:
pk=instance.pk,
)
else:
instance = serializer.save()
instance = self._save_with_retry(serializer, entry, raise_errors)
if instance is None:
return False
self.logger.debug("Updated model", model=instance)
if "pk" in entry.identifiers:
self.__pk_map[entry.identifiers["pk"]] = instance.pk
+2
View File
@@ -133,6 +133,7 @@ class UserSourceConnectionSerializer(SourceSerializer):
"last_updated",
]
extra_kwargs = {
"user": {"read_only": True},
"created": {"read_only": True},
"last_updated": {"read_only": True},
}
@@ -173,6 +174,7 @@ class GroupSourceConnectionSerializer(SourceSerializer):
"last_updated",
]
extra_kwargs = {
"group": {"read_only": True},
"created": {"read_only": True},
"last_updated": {"read_only": True},
}
+1 -1
View File
@@ -12,7 +12,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
{# Darkreader breaks the site regardless of theme as its not compatible with webcomponents, and we default to a dark theme based on preferred colour-scheme #}
{# Darkreader breaks the site regardless of theme as its not compatible with webcomponents, and we default to a dark theme based on preferred color-scheme #}
<meta name="darkreader-lock">
<title>{% block title %}{% trans title|default:brand.branding_title %}{% endblock %}</title>
<link rel="icon" href="{{ brand.branding_favicon_url }}">
@@ -7,7 +7,7 @@ from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_sche
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.fields import ChoiceField
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.permissions import IsAuthenticated
from rest_framework.relations import PrimaryKeyRelatedField
from rest_framework.request import Request
from rest_framework.response import Response
@@ -118,8 +118,7 @@ class AgentConnectorViewSet(
methods=["POST"],
detail=False,
authentication_classes=[AgentEnrollmentAuth],
# Permissions are handled via AgentEnrollmentAuth
permission_classes=[AllowAny],
permission_classes=[IsAuthenticated],
)
def enroll(self, request: Request):
token: EnrollmentToken = request.auth
@@ -154,8 +153,7 @@ class AgentConnectorViewSet(
methods=["GET"],
detail=False,
authentication_classes=[AgentAuth],
# Permissions are handled via AgentAuth
permission_classes=[AllowAny],
permission_classes=[IsAuthenticated],
)
def agent_config(self, request: Request):
token: DeviceToken = request.auth
@@ -174,8 +172,7 @@ class AgentConnectorViewSet(
methods=["POST"],
detail=False,
authentication_classes=[AgentAuth],
# Permissions are handled via AgentAuth
permission_classes=[AllowAny],
permission_classes=[IsAuthenticated],
)
def check_in(self, request: Request):
token: DeviceToken = request.auth
@@ -124,6 +124,14 @@ class TestAgentAPI(APITestCase):
)
self.assertEqual(response.status_code, 403)
@reconcile_app("authentik_crypto")
def test_config_none(self):
response = self.client.get(
reverse("authentik_api:agentconnector-agent-config"),
HTTP_AUTHORIZATION="Bearer foo",
)
self.assertEqual(response.status_code, 403)
def test_check_in(self):
response = self.client.post(
reverse("authentik_api:agentconnector-check-in"),
@@ -68,13 +68,16 @@ class SCIMOAuthAuth:
return conn
token = self.retrieve_token(conn)
access_token = token["access_token"]
refresh_token = token.get("refresh_token")
if not refresh_token and conn:
refresh_token = conn.refresh_token
expires_in = int(token.get("expires_in", 0))
token, _ = UserOAuthSourceConnection.objects.update_or_create(
source=self.provider.auth_oauth,
user=self.user,
defaults={
"access_token": access_token,
"refresh_token": token.get("refresh_token"),
"refresh_token": refresh_token,
"expires": now() + timedelta(seconds=expires_in),
# When using `update_or_create`, `last_updated` is not updated
"last_updated": now(),
@@ -104,6 +104,7 @@ class TestSCIMOAuthToken(APITestCase):
source=self.source,
user=self.provider.auth_oauth_user,
).first()
self.assertEqual(conn.refresh_token, refresh_token)
self.assertIsNotNone(conn)
self.assertTrue(conn.is_valid)
auth = (
@@ -65,6 +65,7 @@ class SCIMRedirectCallback(SCIMOAuthViewMixin, OAuthCallback):
"access_token": self.token.get("access_token"),
"refresh_token": self.token.get("refresh_token"),
"expires": now() + timedelta(seconds=expires_in),
"last_updated": now(),
},
)
return redirect("authentik_core:if-admin")
+3 -2
View File
@@ -16,7 +16,7 @@ from authentik.core.sources.flow_manager import (
)
from authentik.core.types import UILoginButton
from authentik.enterprise.stages.source.models import SourceStage
from authentik.flows.challenge import Challenge, ChallengeResponse
from authentik.flows.challenge import Challenge, ChallengeResponse, HttpChallengeResponse
from authentik.flows.models import FlowToken, in_memory_stage
from authentik.flows.planner import PLAN_CONTEXT_IS_REDIRECTED, PLAN_CONTEXT_IS_RESTORED
from authentik.flows.stage import ChallengeStageView, StageView
@@ -84,7 +84,8 @@ class SourceStageView(ChallengeStageView):
return token
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
return self.executor.stage_ok()
# Completion happens via dispatch(), not here.
return HttpChallengeResponse(self._get_challenge())
class SourceStageFinal(StageView):
+1
View File
@@ -258,6 +258,7 @@ class Event(SerializerModel, ExpiringModel):
action=EventAction.CONFIGURATION_WARNING,
context__deprecation=identifier,
)
cause = str(cause)
if cause:
query &= Q(context__cause=cause)
if Event.objects.filter(query).exists():
+11
View File
@@ -225,3 +225,14 @@ class TestEvents(TestCase):
new_count = Event.objects.filter(action=EventAction.PASSWORD_SET, user__pk=user.pk).count()
self.assertEqual(new_count, old_count + 1)
def test_log_deprecation(self):
"""Test Event.log_deprecation"""
Event.log_deprecation(self.__module__, "Test deprecation")
Event.log_deprecation(self.__module__, "Test deprecation")
Event.log_deprecation(self.__module__, "Test deprecation")
Event.log_deprecation(self.__module__, "Test deprecation", cause=create_test_user())
logs = Event.objects.filter(
action=EventAction.CONFIGURATION_WARNING, context__deprecation=self.__module__
)
self.assertEqual(logs.count(), 2)
+1 -1
View File
@@ -196,7 +196,7 @@ class FlowExecutorView(APIView):
return self.handle_invalid_flow(exc)
except EmptyFlowException as exc:
self._logger.warning("f(exec): Flow is empty", exc=exc)
# To match behaviour with loading an empty flow plan from cache,
# To match behavior with loading an empty flow plan from cache,
# we don't show an error message here, but rather call _flow_done()
return self._flow_done()
# We don't save the Plan after getting the next stage
+1 -1
View File
@@ -59,7 +59,7 @@ def avatar_mode_gravatar(user: User, mode: str) -> str | None:
def generate_colors(text: str) -> tuple[str, str]:
"""Generate colours based on `text`"""
"""Generate colors based on `text`"""
color = (
int(md5(text.lower().encode("utf-8"), usedforsecurity=False).hexdigest(), 16) % 0xFFFFFF
) # nosec
+1 -1
View File
@@ -276,7 +276,7 @@ class ConfigLoader:
try:
return int(value)
except (ValueError, TypeError) as exc:
if value is None or (isinstance(value, str) and value.lower() == "null"):
if value is None or (isinstance(value, str) and value.lower() in ("", "null", "none")):
return None
self.log("warning", "Failed to parse config as int", path=path, exc=str(exc))
return default
+1
View File
@@ -22,6 +22,7 @@ postgresql:
port: 5432
password: "env://POSTGRES_PASSWORD"
sslmode: disable
conn_max_age: 0
conn_health_checks: false
use_pool: False
test:
+1 -1
View File
@@ -315,7 +315,7 @@ class TestConfig(TestCase):
{
"default": {
"DISABLE_SERVER_SIDE_CURSORS": True,
"CONN_MAX_AGE": None,
"CONN_MAX_AGE": 0,
"CONN_HEALTH_CHECKS": False,
"ENGINE": "psqlextra.backend",
"HOST": "foo",
+1 -1
View File
@@ -91,7 +91,7 @@ class LDAPOutpostConfigSerializer(ModelSerializer):
unbind_flow_slug = SerializerMethodField()
def get_application_slug(self, instance: LDAPProvider) -> str:
"""Prioritise backchannel slug over direct application slug"""
"""Prioritize backchannel slug over direct application slug"""
if instance.backchannel_application:
return instance.backchannel_application.slug
return instance.application.slug
+6
View File
@@ -88,6 +88,12 @@ class GrantType(models.TextChoices):
DEVICE_CODE = GRANT_TYPE_DEVICE_CODE
# Fallback for decoding previous sessions from 2026.2 to 2026.5
# https://github.com/goauthentik/authentik/issues/22588
# TODO: Remove after 2026.8
GrantTypes = GrantType
class ResponseMode(models.TextChoices):
"""https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#OAuth.Post"""
@@ -84,8 +84,7 @@ class EndSessionView(PolicyAccessView):
"id_token_hint_decode_failed"
) from None
# Validate post_logout_redirect_uri against registered URIs
if request_redirect_uri:
if request_redirect_uri and self.provider.post_logout_redirect_uris:
# OIDC Certification: id_token_hint required with post_logout_redirect_uri
if not id_token_hint:
raise TokenError("invalid_request").with_cause("id_token_hint_missing")
+1 -1
View File
@@ -127,7 +127,7 @@ class SAMLFlowFinalView(ChallengeStageView):
"Redirect binding for Service Provider binding is deprecated "
"and will be removed in a future version. Use Post binding instead."
),
cause=provider,
cause=provider.name,
)
url_args = {
REQUEST_KEY_SAML_RESPONSE: deflate_and_base64_encode(response),
+1 -1
View File
@@ -22,7 +22,7 @@ class ObjectPermissions(DjangoObjectPermissions):
lookup = getattr(view, "lookup_url_kwarg", None) or getattr(view, "lookup_field", None)
if lookup and lookup in view.kwargs:
return True
# Legacy behaviour:
# Legacy behavior:
# Allow creation of objects even without explicit permission
queryset = self._queryset(view)
required_perms = self.get_required_permissions(request.method, queryset.model)
+1 -1
View File
@@ -76,7 +76,7 @@ class GitHubType(SourceType):
chosen_email = info.get("email")
if not chosen_email:
# The GitHub Userprofile API only returns an email address if the profile
# has a public email address set (despite us asking for user:email, this behaviour
# has a public email address set (despite us asking for user:email, this behavior
# doesn't change.). So we fetch all the user's email addresses
emails = client.get_github_emails(token)
for email in emails:
+1 -1
View File
@@ -67,7 +67,7 @@ class OpenIDConnectOAuth2Callback(OAuthCallback):
client_class = OpenIDConnectClient
def get_user_id(self, info: dict[str, str]) -> str:
return info.get("sub", None)
return str(info.get("sub") or info.get("id"))
@registry.register()
+22 -12
View File
@@ -143,9 +143,21 @@ class ResponseProcessor:
if datetime.fromisoformat(on_or_after).replace(tzinfo=UTC) < _now:
raise SAMLException("Assertion is not valid yet or expired.")
def _verify_signature(self, signature_node: _Element):
"""Verify a single signature node"""
xmlsec.tree.add_ids(self._root, ["ID"])
def _verify_signature(self, signature_node: _Element, target: _Element):
"""Verify a single signature node against the given target element."""
target_id = target.attrib.get("ID")
if not target_id:
raise InvalidSignature("Signed element is missing an ID attribute.")
refs = signature_node.xpath("./ds:SignedInfo/ds:Reference", namespaces=NS_MAP)
if len(refs) != 1:
raise InvalidSignature("Signature must contain exactly one Reference.")
ref_uri = refs[0].get("URI", "")
if ref_uri not in ("", f"#{target_id}"):
raise InvalidSignature(
"Signature Reference URI does not match the signed element's ID."
)
xmlsec.tree.add_ids(target, ["ID"])
ctx = xmlsec.SignatureContext()
key = xmlsec.Key.from_memory(
@@ -168,24 +180,22 @@ class ResponseProcessor:
signature_nodes = self._root.xpath("/samlp:Response/ds:Signature", namespaces=NS_MAP)
if len(signature_nodes) != 1:
raise InvalidSignature("No Signature exists in the Response element.")
raise InvalidSignature("Expected exactly one Signature in the Response element.")
self._verify_signature(signature_nodes[0])
self._verify_signature(signature_nodes[0], self._root)
def _verify_assertion_signature(self):
"""Verify SAML Assertion's Signature (after decryption)"""
signature_nodes = self._root.xpath(
"/samlp:Response/saml:Assertion/ds:Signature", namespaces=NS_MAP
)
if len(signature_nodes) != 1:
raise InvalidSignature("No Signature exists in the Assertion element.")
raise InvalidSignature("Expected exactly one signed Assertion in the Response.")
signature_node = signature_nodes[0]
assertion = signature_node.getparent()
self._verify_signature(signature_nodes[0])
parent = signature_nodes[0].getparent()
if parent is None or parent.tag != f"{{{NS_SAML_ASSERTION}}}Assertion":
raise InvalidSignature("No Signature exists in the Assertion element.")
self._assertion = parent
self._verify_signature(signature_node, assertion)
self._assertion = assertion
def _verify_request_id(self):
if self._source.allow_idp_initiated:
@@ -0,0 +1,41 @@
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_resp_assert_uri_empty" Version="2.0" IssueInstant="2014-07-17T01:01:48Z" Destination="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685"><saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><saml:Assertion ID="_assert" Version="2.0" IssueInstant="2014-07-17T01:01:48Z"><saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<DigestValue>6AZlgEwsPEWwPPioj5HiNRStaPAm70zIRSBGnYaRc+E=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>fei+JUaTHlQuy6/icjyZKUh5kx9qvL5xEqUfwOa1kiLtlfCbMCcEFHMEjePb1uPW
fAePa/v9mIl8pV7TrALI1xicdwRPvvM6xgiWe5hQDU+MKd88bHuU/O/0DUktku+e
ANR4kYQUAgkmmMCSPSruD3zIgVTAI8AMEpTtDNuHr8C12phsDkqaRQ1OP/ptC//2
s6eeJ0DizMWkv/UHrqN8PSoTSgIl30Ffq30t/9TY644lBjgcQZD4h0uvpaRo/M0/
yxcgfP6U3ec9ucePFJKprNXvkmNSh/DGbA0BPx1zoB7xf1nhyIYZI76GqC1NP0rh
YQ1BinW++XE19PvY66MnIA==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIC0jCCAbqgAwIBAgIUXHr2/LJAqtsJ4CcXkFjMwJo8HmQwDQYJKoZIhvcNAQEL
BQAwIzEhMB8GA1UEAwwYVVJJLWVtcHR5IGFzc2VydGlvbiB0ZXN0MB4XDTE0MDEw
MTAwMDAwMFoXDTMwMDEwMTAwMDAwMFowIzEhMB8GA1UEAwwYVVJJLWVtcHR5IGFz
c2VydGlvbiB0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArzIB
E4WYhfFNJk2VcvxTX9+cdyJ+v+GCAU4BxSJ1/97BPf3UN4yob23qohnnnMlGAO2x
QBK2VBQKjNZo3qwy2t5xhsa0YLjjWGxAEL1s5K8cQlkYwkciTy+RFpMXmM80kk8p
ZdZFgrjf5ltincH4QuhJcN3/fsEibHQibymWeb/0I3Mba6Uh+gssMN82NYETl677
I+5HV4wgJWMh1vaZFbid+YFBeWWJoIAIdbTQEAwIJriTA43lgbcK0Lo9A8/RCH1O
RVsQSkpA3kfs9yJ9AvKglBIThapR1iRgtVsC9LdiauHmiNU+8POSHXWByXaWOK0o
Izfg/lI+xKSWJerhUwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQA+/3kRE6jYFfgy
vHZdOX2cFOA5Y0N/RZmdt34tsfCiqP2vHtfQUje8gQAhjmV6dFk4wptPF1FsP601
bMp+9LsRsb4y6pxy5m7xKVK9P/EI33N2zZZL9tlJ7CPIA81DPi53lYOvX54UIi2I
GpF6QyYMX2HTs/KVxo4gYnOnkyqPw6QrKaWpJLQndQd1rTn4/ybWW/9XU46RYf7/
7Z8H8t4n4lhPYm5WGer4eG+k+F3R04yhwSm3Wi91gkQwQdGPgFSPe1z8TusDw/Q/
1ax1a/mNoN9NCcZgg3L0xZgbtDnzBr/Gd/MWBQdDgRM7DpcWaVVcXq5GRLLeAvwM
uF73araE
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">test_user</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2024-01-18T06:21:48Z" Recipient="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z"><saml:AudienceRestriction><saml:Audience>http://sp.example.com/demo1/metadata.php</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionIndex="_session"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion></samlp:Response>
@@ -0,0 +1,72 @@
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_8e8dc5f69a98cc4c1ff3427e5ce34606fd672f91e6" Version="2.0" IssueInstant="2014-07-17T01:01:48Z" Destination="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685">
<saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_evil" Version="2.0" IssueInstant="2014-07-17T01:01:48Z">
<saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#pfxa06693ef-cec7-f4a6-cb7f-ad074445a1a3"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>zNDuGxwP4gVkv/Dzt7kiKo/4gzk=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>GLP/vE8uxerB0uDpPslUgLPBL6ePQB619MoQ0I2Y5lAtFE6CB1zh8BnzChRx/bFjNy4byfOe8mFfM0r7WUi1PJOFWyUPoatdLl7wHHBIRTnPpYmu3Tb2Gz0sOP0F8wW7JkBft5gJfVw49nk5si9/3Q3o52jnJZ7dPtqfIOh8uNeopikK0HLF6sU05qCCtjcXfniEnLQFNBFMo9uY5GQqmR5n3nqPz1wYyyfFOAbVmGgBIoO2PfGX2GVLQhltc9qf2JMhks4jgZsZ8iLUIiH1lcLGWZEEs94k8k0P6gSv1uZ7Vbhksd/N9Jq9pCVuEJ/jRPcAdVjzbxqKQAj6ELwr8O6fepTzA+CAdwEolBnx/C6TmSbVZ+IWk6QUGe4x4+IAukC+0hkKENlO0ELOScksvyhpgHbxNA4rp+DhGupCaO/I2RrsQkmvavbqm+wSEspK7scK112SDunjDvqPHsPYgukD33T/97PxTLorg2kKP9HHJwPJKoXXeyOGcA6vwK+RqrAlZ2dLGAgcXo+sJcdCLuvxDNz9VXofBjBZIKVKdmYhm0QJaPYHtuQsAyFavQhdOBOmGHb7QX3YE3Xy4dX4LymtT+Jlb1I4FJSht/9HUIHW1FdhfDak4f7gUgjuMamMddLD0jVgeESupSREzFv/gj2IrctkbgjAO0iuuiBgKMg=</ds:SignatureValue>
<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIFUzCCAzugAwIBAgIRAL6tbNcE9Ej9gNlbGKswfFMwDQYJKoZIhvcNAQELBQAwHTEbMBkGA1UEAwwSYXV0aGVudGlrIDIwMjUuNi4zMB4XDTI1MDcxNTE4MDQzNloXDTI2MDcxNjE4MDQzNlowVjEqMCgGA1UEAwwhYXV0aGVudGlrIFNlbGYtc2lnbmVkIENlcnRpZmljYXRlMRIwEAYDVQQKDAlhdXRoZW50aWsxFDASBgNVBAsMC1NlbGYtc2lnbmVkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjmut/+bBRLlyrbf+WIfg8ZTw9t6VnsiU1n04nPTulpRAz4nBOoOHNRIruSpZyFeFa6x9jwn4Ma5EFUH7HqnRvhoujm8U17OglXWZt0DLCZ6S5xPmdMogFXjJDmg9okIcI/cb9VbR6I8uvm1oiaOWCr36RTiqZ6rmdjQcuUPLr1+V/LxWQI463S+5QA2HZxAGalp45MJAz2sa9iczktKMgyYlfjj1cruFARxxeheu5qIK7aQWfyPj1QlMb9mi4VQaxUwGrAui4Tq614ivRJY2SkZb0Aq/LLSQoQWYHtYyQIasrOXJm0JuPDqhINPBDowyhu8DihC3uzOpmTXLKc5UoIQk+Q1h5iH74A3/kxOJUw13FXzRiDxC/yGthPYLyFHsDiJolscMKSCqlDvEMcpM4mxFeud9sKUb71SZr8sqmJl3qtvZmKpkR4y8pN2c00p10t0htqONmr5kyPxmhz0HCrosiPYB4olNjaydKviNTtPJ7TtnPyeA3iXGzCP1e80XzUoJrDqON5/GcpYgqsP/kGj8Qvqesa4Fez+1+5pAGHN2VzQbkHAgK3s4YRXrGLTs7wg27F9T0RE28Mm0RYBkYpdp4/5PuTTulthB9mkUBSJMgENmQAYkapvonFDsJkTi39qnsddbZusOLT4z3hsA38eFEwRqnbNZVUGPIp/O1SsCAwEAAaNVMFMwUQYDVR0RAQH/BEcwRYJDRUZ4QXVLRzV6SlVUTWpWNTJoMkRJMUQ5MXdLblZKaXFwNmpwRTRTTy5zZWxmLXNpZ25lZC5nb2F1dGhlbnRpay5pbzANBgkqhkiG9w0BAQsFAAOCAgEAYLThxDVpA1OIAVK/buueRJExIWr6y4s6NtpuR8UQEcfq5hfoc4zMFGHR5+u1WFIb5siK25xh/OnS7bLdLic6AkjZSrx91+0v2Jn9gfUqbs5AJ040XzAAdx/Mb4s0+537yhB+/JXPylR1QxhGbO7koXQ5JDhAXWKCw2O1C+80mN8dbhQvDkEtsXrHrtXclcqf2TT89XAzc5HAC8NmP4SF+FafAREQB1KdaG4QAbc/gnjsX2YJD89SDL+3jMp6F7R1Ym+bWt5oWqx2tkm6HGXd3fbpfQlnfrRN60tMjjLmw1cDMhOhpdragY5zokniEUL2pKVtrxFp7V1ZpoMI0Kt5MKkOXrezi542NWSgkGehlsDLD9wtuCNem2arR0mNnMLdYkMG7G0dpAq3Tl32dgfMfyKnNyE2O/6/EeEuzUH2NfTU1p7AUQfLrf4rtNcJEs9OAPuC9vy7w9YEpF997T+FhR2Ub1C423NQj4bwlS/9f7MIBkSi1EgnQuiSGB5epxAKI3oOVrmzOpTuvr6wZXV9pM3zdfbcoGuFWP6Ix7W8G5vg+0WvoSjc2fwGXYlidEK3xlQSMAaQ4CMClpPsKLScRq1nrQGzPYoiL1DYubsOWx9ohll6+jNjKI6f79WwbHYrW4EeRIOz38+m46EDjAWZBMgrE7J/3DhgeLEVJYBA5K0=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature>
<saml:Subject>
<saml:NameID SPNameQualifier="http://sp.example.com/demo1/metadata.php" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">ATTACKER_FORGED_NAMEID</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2024-01-18T06:21:48Z" Recipient="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z">
<saml:AudienceRestriction>
<saml:Audience>http://sp.example.com/demo1/metadata.php</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionNotOnOrAfter="2024-07-17T09:01:48Z" SessionIndex="_be9967abd904ddcae3c0eb4189adbe3f71e327cf93">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">ATTACKER_FORGED</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">ATTACKER_FORGED</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">ATTACKER_FORGED</saml:AttributeValue>
<saml:AttributeValue xsi:type="xs:string">ATTACKER_FORGED</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
<saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="pfxa06693ef-cec7-f4a6-cb7f-ad074445a1a3" Version="2.0" IssueInstant="2014-07-17T01:01:48Z">
<saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>
<saml:Subject>
<saml:NameID SPNameQualifier="http://sp.example.com/demo1/metadata.php" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2024-01-18T06:21:48Z" Recipient="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z">
<saml:AudienceRestriction>
<saml:Audience>http://sp.example.com/demo1/metadata.php</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionNotOnOrAfter="2024-07-17T09:01:48Z" SessionIndex="_be9967abd904ddcae3c0eb4189adbe3f71e327cf93">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">test@example.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>
<saml:AttributeValue xsi:type="xs:string">examplerole1</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>
@@ -0,0 +1,35 @@
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_resp" Version="2.0" IssueInstant="2014-07-17T01:01:48Z" Destination="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685"><saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><saml:Assertion ID="pfxa06693ef-cec7-f4a6-cb7f-ad074445a1a3" Version="2.0" IssueInstant="2014-07-17T01:01:48Z"><saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#pfxa06693ef-cec7-f4a6-cb7f-ad074445a1a3"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>zNDuGxwP4gVkv/Dzt7kiKo/4gzk=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>GLP/vE8uxerB0uDpPslUgLPBL6ePQB619MoQ0I2Y5lAtFE6CB1zh8BnzChRx/bFjNy4byfOe8mFfM0r7WUi1PJOFWyUPoatdLl7wHHBIRTnPpYmu3Tb2Gz0sOP0F8wW7JkBft5gJfVw49nk5si9/3Q3o52jnJZ7dPtqfIOh8uNeopikK0HLF6sU05qCCtjcXfniEnLQFNBFMo9uY5GQqmR5n3nqPz1wYyyfFOAbVmGgBIoO2PfGX2GVLQhltc9qf2JMhks4jgZsZ8iLUIiH1lcLGWZEEs94k8k0P6gSv1uZ7Vbhksd/N9Jq9pCVuEJ/jRPcAdVjzbxqKQAj6ELwr8O6fepTzA+CAdwEolBnx/C6TmSbVZ+IWk6QUGe4x4+IAukC+0hkKENlO0ELOScksvyhpgHbxNA4rp+DhGupCaO/I2RrsQkmvavbqm+wSEspK7scK112SDunjDvqPHsPYgukD33T/97PxTLorg2kKP9HHJwPJKoXXeyOGcA6vwK+RqrAlZ2dLGAgcXo+sJcdCLuvxDNz9VXofBjBZIKVKdmYhm0QJaPYHtuQsAyFavQhdOBOmGHb7QX3YE3Xy4dX4LymtT+Jlb1I4FJSht/9HUIHW1FdhfDak4f7gUgjuMamMddLD0jVgeESupSREzFv/gj2IrctkbgjAO0iuuiBgKMg=</ds:SignatureValue>
<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIFUzCCAzugAwIBAgIRAL6tbNcE9Ej9gNlbGKswfFMwDQYJKoZIhvcNAQELBQAwHTEbMBkGA1UEAwwSYXV0aGVudGlrIDIwMjUuNi4zMB4XDTI1MDcxNTE4MDQzNloXDTI2MDcxNjE4MDQzNlowVjEqMCgGA1UEAwwhYXV0aGVudGlrIFNlbGYtc2lnbmVkIENlcnRpZmljYXRlMRIwEAYDVQQKDAlhdXRoZW50aWsxFDASBgNVBAsMC1NlbGYtc2lnbmVkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjmut/+bBRLlyrbf+WIfg8ZTw9t6VnsiU1n04nPTulpRAz4nBOoOHNRIruSpZyFeFa6x9jwn4Ma5EFUH7HqnRvhoujm8U17OglXWZt0DLCZ6S5xPmdMogFXjJDmg9okIcI/cb9VbR6I8uvm1oiaOWCr36RTiqZ6rmdjQcuUPLr1+V/LxWQI463S+5QA2HZxAGalp45MJAz2sa9iczktKMgyYlfjj1cruFARxxeheu5qIK7aQWfyPj1QlMb9mi4VQaxUwGrAui4Tq614ivRJY2SkZb0Aq/LLSQoQWYHtYyQIasrOXJm0JuPDqhINPBDowyhu8DihC3uzOpmTXLKc5UoIQk+Q1h5iH74A3/kxOJUw13FXzRiDxC/yGthPYLyFHsDiJolscMKSCqlDvEMcpM4mxFeud9sKUb71SZr8sqmJl3qtvZmKpkR4y8pN2c00p10t0htqONmr5kyPxmhz0HCrosiPYB4olNjaydKviNTtPJ7TtnPyeA3iXGzCP1e80XzUoJrDqON5/GcpYgqsP/kGj8Qvqesa4Fez+1+5pAGHN2VzQbkHAgK3s4YRXrGLTs7wg27F9T0RE28Mm0RYBkYpdp4/5PuTTulthB9mkUBSJMgENmQAYkapvonFDsJkTi39qnsddbZusOLT4z3hsA38eFEwRqnbNZVUGPIp/O1SsCAwEAAaNVMFMwUQYDVR0RAQH/BEcwRYJDRUZ4QXVLRzV6SlVUTWpWNTJoMkRJMUQ5MXdLblZKaXFwNmpwRTRTTy5zZWxmLXNpZ25lZC5nb2F1dGhlbnRpay5pbzANBgkqhkiG9w0BAQsFAAOCAgEAYLThxDVpA1OIAVK/buueRJExIWr6y4s6NtpuR8UQEcfq5hfoc4zMFGHR5+u1WFIb5siK25xh/OnS7bLdLic6AkjZSrx91+0v2Jn9gfUqbs5AJ040XzAAdx/Mb4s0+537yhB+/JXPylR1QxhGbO7koXQ5JDhAXWKCw2O1C+80mN8dbhQvDkEtsXrHrtXclcqf2TT89XAzc5HAC8NmP4SF+FafAREQB1KdaG4QAbc/gnjsX2YJD89SDL+3jMp6F7R1Ym+bWt5oWqx2tkm6HGXd3fbpfQlnfrRN60tMjjLmw1cDMhOhpdragY5zokniEUL2pKVtrxFp7V1ZpoMI0Kt5MKkOXrezi542NWSgkGehlsDLD9wtuCNem2arR0mNnMLdYkMG7G0dpAq3Tl32dgfMfyKnNyE2O/6/EeEuzUH2NfTU1p7AUQfLrf4rtNcJEs9OAPuC9vy7w9YEpF997T+FhR2Ub1C423NQj4bwlS/9f7MIBkSi1EgnQuiSGB5epxAKI3oOVrmzOpTuvr6wZXV9pM3zdfbcoGuFWP6Ix7W8G5vg+0WvoSjc2fwGXYlidEK3xlQSMAaQ4CMClpPsKLScRq1nrQGzPYoiL1DYubsOWx9ohll6+jNjKI6f79WwbHYrW4EeRIOz38+m46EDjAWZBMgrE7J/3DhgeLEVJYBA5K0=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">FORGED_VICTIM</saml:NameID></saml:Subject><saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z"><saml:AudienceRestriction><saml:Audience>http://sp.example.com/demo1/metadata.php</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:Advice><saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="pfxa06693ef-cec7-f4a6-cb7f-ad074445a1a3" Version="2.0" IssueInstant="2014-07-17T01:01:48Z">
<saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>
<saml:Subject>
<saml:NameID SPNameQualifier="http://sp.example.com/demo1/metadata.php" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2024-01-18T06:21:48Z" Recipient="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z">
<saml:AudienceRestriction>
<saml:Audience>http://sp.example.com/demo1/metadata.php</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionNotOnOrAfter="2024-07-17T09:01:48Z" SessionIndex="_be9967abd904ddcae3c0eb4189adbe3f71e327cf93">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">test@example.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>
<saml:AttributeValue xsi:type="xs:string">examplerole1</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion></saml:Advice></saml:Assertion></samlp:Response>
@@ -0,0 +1,40 @@
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_resp_uri_empty" Version="2.0" IssueInstant="2014-07-17T01:01:48Z" Destination="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685"><saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<DigestValue>h6La1VQZ6VO/Bi/a3g2Uhkp27kV1ijJvIB6xlgLGu7M=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>ItqDe3xfN9sN44z9pudYI+GdVEz7MnLXvG3+afjS8ws52c8fUryoK0lgH3l0i3mY
cFKiQwiuRx86AB6uGH13ToOoXq3peK911PeGZ/fCt15x14x6v69r9vG+Mw4KAc+y
7J/a3BOltEoU9SfNHBAIkEgbHP35bF5iYSVlIfLho8BRCVT4rMv/K/n65Hd88Fas
Es2oxS95hYUf1of9pHDOuvEYM+VpMZw3OuMci7X8ZszCxdJbgP6D4m7w9wWBbAAi
xWWuLnU2sFkLNeBh5KuumLNLG1Dreqiz0d4/tu+P9F4NcP2FAdG79/Y+Ga9d0Wf7
yf05WcieZgV4hhHNwQcauw==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIICvjCCAaagAwIBAgIUGjmjYk5z7ya8VH2Faah5vvVmEHIwDQYJKoZIhvcNAQEL
BQAwGTEXMBUGA1UEAwwOVVJJLWVtcHR5IHRlc3QwHhcNMTQwMTAxMDAwMDAwWhcN
MzAwMTAxMDAwMDAwWjAZMRcwFQYDVQQDDA5VUkktZW1wdHkgdGVzdDCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKEuJi9Gny9OfQScZEG1R9Gy5pqbM7it
pGda6gm4PXuFQisMapdg0DwO3odY1grTQE6gFEjSCYtEoGyuJMSUNdILvc7sfCWa
QkuXCnkx7nXgyiHLNuhgkhw6kDXgRMzdaI/B7IlZkZYnfyXWi6A6lQ6dLJRU1p0o
C+JawKngvmOAAKvhaC1keEbfUh//8UhK/YkjJShV1c0ijFlucj4eYDQyf9x9lYw7
oukjnVFKmhqiRO/SxwhYjYbyTppVRzC4sCJz0KRn4qwnGV5x2+jDqUvFUxJc5W7f
N+utrfNWeszmP5Elw+ezIsq+3D9ss+nHmtXIDxVNA3dp8tZQKzQ4WzcCAwEAATAN
BgkqhkiG9w0BAQsFAAOCAQEART2PW/rXPU5d+NTJnP2mdIi5Ft01gpaRgY1iBsFm
+D6zXT/k9wr56GEDLWUf2qOJeXsNc+f9FKI0BCVb/5vVoB60AAMHKbb+NxwoXLHi
dT6DaEPK1VGdEBnpL5uOII3pO42FMPewBUNuoUmb9zipyPoL6zbc7khRcBBIYMlr
05Y2tqJqECNAtGQ9+v5CBcECP3QI4L0UmCJMwpj7XH5TrfKfLPZuUEvQaET63dXb
ioi+P6KEpuxblOL0Uj2e2erhJYavqCnoxt+0eUDDBsrwuk7/sRtbBO0XjkgEtJZ8
n3OS74cjqIwTx+PqObGThECnyBYwONY7RWU5G4r6kqMXBg==
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><saml:Assertion ID="_assert" Version="2.0" IssueInstant="2014-07-17T01:01:48Z"><saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">test_user</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2024-01-18T06:21:48Z" Recipient="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z"><saml:AudienceRestriction><saml:Audience>http://sp.example.com/demo1/metadata.php</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionIndex="_session"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion></samlp:Response>
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC0jCCAbqgAwIBAgIUXHr2/LJAqtsJ4CcXkFjMwJo8HmQwDQYJKoZIhvcNAQEL
BQAwIzEhMB8GA1UEAwwYVVJJLWVtcHR5IGFzc2VydGlvbiB0ZXN0MB4XDTE0MDEw
MTAwMDAwMFoXDTMwMDEwMTAwMDAwMFowIzEhMB8GA1UEAwwYVVJJLWVtcHR5IGFz
c2VydGlvbiB0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArzIB
E4WYhfFNJk2VcvxTX9+cdyJ+v+GCAU4BxSJ1/97BPf3UN4yob23qohnnnMlGAO2x
QBK2VBQKjNZo3qwy2t5xhsa0YLjjWGxAEL1s5K8cQlkYwkciTy+RFpMXmM80kk8p
ZdZFgrjf5ltincH4QuhJcN3/fsEibHQibymWeb/0I3Mba6Uh+gssMN82NYETl677
I+5HV4wgJWMh1vaZFbid+YFBeWWJoIAIdbTQEAwIJriTA43lgbcK0Lo9A8/RCH1O
RVsQSkpA3kfs9yJ9AvKglBIThapR1iRgtVsC9LdiauHmiNU+8POSHXWByXaWOK0o
Izfg/lI+xKSWJerhUwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQA+/3kRE6jYFfgy
vHZdOX2cFOA5Y0N/RZmdt34tsfCiqP2vHtfQUje8gQAhjmV6dFk4wptPF1FsP601
bMp+9LsRsb4y6pxy5m7xKVK9P/EI33N2zZZL9tlJ7CPIA81DPi53lYOvX54UIi2I
GpF6QyYMX2HTs/KVxo4gYnOnkyqPw6QrKaWpJLQndQd1rTn4/ybWW/9XU46RYf7/
7Z8H8t4n4lhPYm5WGer4eG+k+F3R04yhwSm3Wi91gkQwQdGPgFSPe1z8TusDw/Q/
1ax1a/mNoN9NCcZgg3L0xZgbtDnzBr/Gd/MWBQdDgRM7DpcWaVVcXq5GRLLeAvwM
uF73araE
-----END CERTIFICATE-----
@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICvjCCAaagAwIBAgIUGjmjYk5z7ya8VH2Faah5vvVmEHIwDQYJKoZIhvcNAQEL
BQAwGTEXMBUGA1UEAwwOVVJJLWVtcHR5IHRlc3QwHhcNMTQwMTAxMDAwMDAwWhcN
MzAwMTAxMDAwMDAwWjAZMRcwFQYDVQQDDA5VUkktZW1wdHkgdGVzdDCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKEuJi9Gny9OfQScZEG1R9Gy5pqbM7it
pGda6gm4PXuFQisMapdg0DwO3odY1grTQE6gFEjSCYtEoGyuJMSUNdILvc7sfCWa
QkuXCnkx7nXgyiHLNuhgkhw6kDXgRMzdaI/B7IlZkZYnfyXWi6A6lQ6dLJRU1p0o
C+JawKngvmOAAKvhaC1keEbfUh//8UhK/YkjJShV1c0ijFlucj4eYDQyf9x9lYw7
oukjnVFKmhqiRO/SxwhYjYbyTppVRzC4sCJz0KRn4qwnGV5x2+jDqUvFUxJc5W7f
N+utrfNWeszmP5Elw+ezIsq+3D9ss+nHmtXIDxVNA3dp8tZQKzQ4WzcCAwEAATAN
BgkqhkiG9w0BAQsFAAOCAQEART2PW/rXPU5d+NTJnP2mdIi5Ft01gpaRgY1iBsFm
+D6zXT/k9wr56GEDLWUf2qOJeXsNc+f9FKI0BCVb/5vVoB60AAMHKbb+NxwoXLHi
dT6DaEPK1VGdEBnpL5uOII3pO42FMPewBUNuoUmb9zipyPoL6zbc7khRcBBIYMlr
05Y2tqJqECNAtGQ9+v5CBcECP3QI4L0UmCJMwpj7XH5TrfKfLPZuUEvQaET63dXb
ioi+P6KEpuxblOL0Uj2e2erhJYavqCnoxt+0eUDDBsrwuk7/sRtbBO0XjkgEtJZ8
n3OS74cjqIwTx+PqObGThECnyBYwONY7RWU5G4r6kqMXBg==
-----END CERTIFICATE-----
+114 -2
View File
@@ -196,10 +196,122 @@ class TestResponseProcessor(TestCase):
self.assertNotEqual(parser._get_name_id()[1], "bad")
self.assertEqual(parser._get_name_id()[1], "_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7")
@freeze_time("2022-10-14T14:15:00")
@freeze_time("2014-07-17T01:02:18Z")
def test_verification_assertion_xsw_nested_duplicate_id(self):
"""Nested-duplicate-ID XSW: a forged outer Assertion shares its ID with a
nested copy of the original signed Assertion (placed inside <saml:Advice>),
so the Signature's Reference URI (#ORIG_ID) matches the outer Assertion's
ID *and* dereferences to legitimately-signed content. Must be rejected."""
key = load_fixture("fixtures/signature_cert.pem")
kp = CertificateKeyPair.objects.create(
name=generate_id(),
certificate_data=key,
)
self.source.verification_kp = kp
self.source.signed_assertion = True
self.source.signed_response = False
request = self.factory.post(
"/",
data={
"SAMLResponse": b64encode(
load_fixture("fixtures/response_signed_assertion_xsw_nested.xml").encode()
).decode()
},
)
parser = ResponseProcessor(self.source, request)
with self.assertRaises(InvalidSignature):
parser.parse()
@freeze_time("2014-07-17T01:02:18Z")
def test_verification_response_uri_empty(self):
"""Some real-world IdPs (notably some Okta dev-tenant configurations
observed in the gosaml2 testdata corpus at saml.oktadev.com) sign the
Response with ds:Reference URI="" instead of URI="#<ID>". Per xmldsig
§4.4.3.2, URI="" covers the entire enclosing document via the
enveloped-signature transform strictly more attested content than
"#<ID>" so consuming the target is a subset of what was signed."""
key = load_fixture("fixtures/signature_cert_uri_empty.pem")
kp = CertificateKeyPair.objects.create(
name=generate_id(),
certificate_data=key,
)
self.source.verification_kp = kp
self.source.signed_response = True
self.source.signed_assertion = False
request = self.factory.post(
"/",
data={
"SAMLResponse": b64encode(
load_fixture("fixtures/response_signed_response_uri_empty.xml").encode()
).decode()
},
)
parser = ResponseProcessor(self.source, request)
parser.parse()
@freeze_time("2014-07-17T01:02:18Z")
def test_verification_assertion_uri_empty(self):
"""Symmetric to test_verification_response_uri_empty but for an
Assertion-level signature: the same xmldsig "this document" semantics
still cover the whole enclosing document, so the Assertion we then
consume is part of the attested content. We have no real-world IdP
samples emitting this configuration, but the pre-fix code accepted it
and the cryptographic guarantee holds, so keep accepting it rather
than risk breaking an IdP we haven't sampled."""
key = load_fixture("fixtures/signature_cert_assertion_uri_empty.pem")
kp = CertificateKeyPair.objects.create(
name=generate_id(),
certificate_data=key,
)
self.source.verification_kp = kp
self.source.signed_assertion = True
self.source.signed_response = False
request = self.factory.post(
"/",
data={
"SAMLResponse": b64encode(
load_fixture("fixtures/response_signed_assertion_uri_empty.xml").encode()
).decode()
},
)
parser = ResponseProcessor(self.source, request)
parser.parse()
@freeze_time("2014-07-17T01:02:18Z")
def test_verification_assertion_xsw3(self):
"""XSW-3 (signature relocation): a forged Assertion contains a Signature whose
ds:Reference URI points to a second Assertion in the document. The signature
verifies (because the digest matches the legitimate referenced Assertion),
but the verifier must NOT then consume the forged Assertion as if it were
signed."""
key = load_fixture("fixtures/signature_cert.pem")
kp = CertificateKeyPair.objects.create(
name=generate_id(),
certificate_data=key,
)
self.source.verification_kp = kp
self.source.signed_assertion = True
self.source.signed_response = False
request = self.factory.post(
"/",
data={
"SAMLResponse": b64encode(
load_fixture("fixtures/response_signed_assertion_xsw3.xml").encode()
).decode()
},
)
parser = ResponseProcessor(self.source, request)
with self.assertRaises(InvalidSignature):
parser.parse()
@freeze_time("2014-07-17T01:02:18Z")
def test_name_id_comment(self):
"""Test comment in name ID"""
fixture = load_fixture("fixtures/response_signed_assertion_dup.xml")
fixture = load_fixture("fixtures/response_signed_assertion.xml")
fixture = fixture.replace(
"_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7",
"_ce3d2948b4cf20146dee0a0b3dd6f<!--x-->69b6cf86f62d7",
+1 -1
View File
@@ -291,7 +291,7 @@ class VerifyNotAllowed:
class ThrottlingMixin(models.Model):
"""
Mixin class for models that want throttling behaviour.
Mixin class for models that want throttling behavior.
This implements exponential back-off for verifying tokens. Subclasses must
implement :meth:`get_throttle_factor`, and must use the
+1 -1
View File
@@ -362,7 +362,7 @@ class AuthenticatorSMSStageTests(FlowTestCase):
class TestSMSDeviceThrottling(ThrottlingTestMixin, TestCase):
"""Test ThrottlingMixin behaviour on SMSDevice.verify_token"""
"""Test ThrottlingMixin behavior on SMSDevice.verify_token"""
def setUp(self):
super().setUp()
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -18,7 +18,7 @@ PLAN_CONTEXT_INVITATION = "invitation"
class InvitationStageView(StageView):
"""Finalise Authentication flow by logging the user in"""
"""Finalize Authentication flow by logging the user in"""
def get_token(self) -> str | None:
"""Get token from saved get-arguments or prompt_data"""
+1 -1
View File
@@ -10,7 +10,7 @@ from authentik.flows.stage import StageView
class UserDeleteStageView(StageView):
"""Finalise unenrollment flow by deleting the user object."""
"""Finalize unenrollment flow by deleting the user object."""
def dispatch(self, request: HttpRequest) -> HttpResponse:
"""Delete currently pending user"""
+1 -1
View File
@@ -50,7 +50,7 @@ class UserLoginChallengeResponse(ChallengeResponse):
class UserLoginStageView(ChallengeStageView):
"""Finalise Authentication flow by logging the user in"""
"""Finalize Authentication flow by logging the user in"""
response_class = UserLoginChallengeResponse
+1 -1
View File
@@ -30,7 +30,7 @@ PLAN_CONTEXT_USER_PATH = "user_path"
class UserWriteStageView(StageView):
"""Finalise Enrollment flow by creating a user object."""
"""Finalize Enrollment flow by creating a user object."""
def __init__(self, executor: FlowExecutorView, **kwargs):
super().__init__(executor, **kwargs)
-54
View File
@@ -12110,11 +12110,6 @@
"model_authentik_sources_kerberos.groupkerberossourceconnection": {
"type": "object",
"properties": {
"group": {
"type": "string",
"format": "uuid",
"title": "Group"
},
"source": {
"type": "string",
"format": "uuid",
@@ -12408,10 +12403,6 @@
"model_authentik_sources_kerberos.userkerberossourceconnection": {
"type": "object",
"properties": {
"user": {
"type": "integer",
"title": "User"
},
"source": {
"type": "string",
"format": "uuid",
@@ -12454,11 +12445,6 @@
"model_authentik_sources_ldap.groupldapsourceconnection": {
"type": "object",
"properties": {
"group": {
"type": "string",
"format": "uuid",
"title": "Group"
},
"source": {
"type": "string",
"format": "uuid",
@@ -12783,10 +12769,6 @@
"model_authentik_sources_ldap.userldapsourceconnection": {
"type": "object",
"properties": {
"user": {
"type": "integer",
"title": "User"
},
"source": {
"type": "string",
"format": "uuid",
@@ -12829,11 +12811,6 @@
"model_authentik_sources_oauth.groupoauthsourceconnection": {
"type": "object",
"properties": {
"group": {
"type": "string",
"format": "uuid",
"title": "Group"
},
"source": {
"type": "string",
"format": "uuid",
@@ -13151,10 +13128,6 @@
"model_authentik_sources_oauth.useroauthsourceconnection": {
"type": "object",
"properties": {
"user": {
"type": "integer",
"title": "User"
},
"source": {
"type": "string",
"format": "uuid",
@@ -13209,11 +13182,6 @@
"model_authentik_sources_plex.groupplexsourceconnection": {
"type": "object",
"properties": {
"group": {
"type": "string",
"format": "uuid",
"title": "Group"
},
"source": {
"type": "string",
"format": "uuid",
@@ -13454,10 +13422,6 @@
"model_authentik_sources_plex.userplexsourceconnection": {
"type": "object",
"properties": {
"user": {
"type": "integer",
"title": "User"
},
"source": {
"type": "string",
"format": "uuid",
@@ -13505,11 +13469,6 @@
"model_authentik_sources_saml.groupsamlsourceconnection": {
"type": "object",
"properties": {
"group": {
"type": "string",
"format": "uuid",
"title": "Group"
},
"source": {
"type": "string",
"format": "uuid",
@@ -13837,10 +13796,6 @@
"model_authentik_sources_saml.usersamlsourceconnection": {
"type": "object",
"properties": {
"user": {
"type": "integer",
"title": "User"
},
"source": {
"type": "string",
"format": "uuid",
@@ -14003,11 +13958,6 @@
"model_authentik_sources_telegram.grouptelegramsourceconnection": {
"type": "object",
"properties": {
"group": {
"type": "string",
"format": "uuid",
"title": "Group"
},
"source": {
"type": "string",
"format": "uuid",
@@ -14234,10 +14184,6 @@
"model_authentik_sources_telegram.usertelegramsourceconnection": {
"type": "object",
"properties": {
"user": {
"type": "integer",
"title": "User"
},
"source": {
"type": "string",
"format": "uuid",
+2
View File
@@ -269,6 +269,8 @@
".docusaurus/**", // Cache
"./{docs,website}/build", // Topic docs build output
"./{docs,website}/**/build", // Workspaces output
"_redirects", // Redirects file
"_headers", // Headers file
//#endregion
//#region Golang
"go.mod", // Go module file
+13 -13
View File
@@ -10,7 +10,7 @@ require (
github.com/getsentry/sentry-go v0.46.2
github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1
github.com/go-ldap/ldap/v3 v3.4.13
github.com/go-openapi/runtime v0.31.0
github.com/go-openapi/runtime v0.32.3
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/google/uuid v1.6.0
github.com/gorilla/handlers v1.5.2
@@ -18,7 +18,7 @@ require (
github.com/gorilla/securecookie v1.1.2
github.com/gorilla/sessions v1.4.0
github.com/gorilla/websocket v1.5.3
github.com/grafana/pyroscope-go v1.3.0
github.com/grafana/pyroscope-go v1.3.1
github.com/jackc/pgx/v5 v5.9.2
github.com/jellydator/ttlcache/v3 v3.4.0
github.com/mitchellh/mapstructure v1.5.0
@@ -51,14 +51,14 @@ require (
github.com/go-jose/go-jose/v4 v4.1.4 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/analysis v0.25.0 // indirect
github.com/go-openapi/analysis v0.25.2 // indirect
github.com/go-openapi/errors v0.22.7 // indirect
github.com/go-openapi/jsonpointer v0.23.1 // indirect
github.com/go-openapi/jsonreference v0.21.5 // indirect
github.com/go-openapi/jsonreference v0.21.6 // indirect
github.com/go-openapi/loads v0.23.3 // indirect
github.com/go-openapi/runtime/server-middleware v0.30.0 // indirect
github.com/go-openapi/spec v0.22.4 // indirect
github.com/go-openapi/strfmt v0.26.2 // indirect
github.com/go-openapi/spec v0.22.5 // indirect
github.com/go-openapi/strfmt v0.26.3 // indirect
github.com/go-openapi/swag/conv v0.26.0 // indirect
github.com/go-openapi/swag/fileutils v0.26.0 // indirect
github.com/go-openapi/swag/jsonname v0.26.0 // indirect
@@ -68,9 +68,9 @@ require (
github.com/go-openapi/swag/stringutils v0.26.0 // indirect
github.com/go-openapi/swag/typeutils v0.26.0 // indirect
github.com/go-openapi/swag/yamlutils v0.26.0 // indirect
github.com/go-openapi/validate v0.25.2 // indirect
github.com/go-openapi/validate v0.25.3 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.10 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.11 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
@@ -86,14 +86,14 @@ require (
github.com/prometheus/procfs v0.16.1 // indirect
github.com/spf13/pflag v1.0.9 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel v1.43.0 // indirect
go.opentelemetry.io/otel/metric v1.43.0 // indirect
go.opentelemetry.io/otel/trace v1.43.0 // indirect
go.opentelemetry.io/otel v1.44.0 // indirect
go.opentelemetry.io/otel/metric v1.44.0 // indirect
go.opentelemetry.io/otel/trace v1.44.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.51.0 // indirect
golang.org/x/net v0.54.0 // indirect
golang.org/x/sys v0.44.0 // indirect
golang.org/x/net v0.55.0 // indirect
golang.org/x/sys v0.45.0 // indirect
golang.org/x/text v0.37.0 // indirect
google.golang.org/protobuf v1.36.8 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+34 -34
View File
@@ -41,24 +41,24 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/analysis v0.25.0 h1:EnjAq1yO8wEO9HbPmY8vLPEIkdZuuFhCAKBPvCB7bCs=
github.com/go-openapi/analysis v0.25.0/go.mod h1:5WFTRE43WLkPG9r9OtlMfqkkvUTYLVVCIxLlEpyF8kE=
github.com/go-openapi/analysis v0.25.2 h1:I0vy4n3alz+DHTiN1PRhCb7QZxkK6g5YmswZKv2TKuw=
github.com/go-openapi/analysis v0.25.2/go.mod h1:Uhs1t/2XR10EnwONYILGEzw8gcfGIG5Xk5K2AxnhqDo=
github.com/go-openapi/errors v0.22.7 h1:JLFBGC0Apwdzw3484MmBqspjPbwa2SHvpDm0u5aGhUA=
github.com/go-openapi/errors v0.22.7/go.mod h1://QW6SD9OsWtH6gHllUCddOXDL0tk0ZGNYHwsw4sW3w=
github.com/go-openapi/jsonpointer v0.23.1 h1:1HBACs7XIwR2RcmItfdSFlALhGbe6S92p0ry4d1GWg4=
github.com/go-openapi/jsonpointer v0.23.1/go.mod h1:iWRmZTrGn7XwYhtPt/fvdSFj1OfNBngqRT2UG3BxSqY=
github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE=
github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw=
github.com/go-openapi/jsonreference v0.21.6 h1:NZ5nGfnaM1n4I43Xjm1e5/M2GjOwQwndQz22uhxwD+Y=
github.com/go-openapi/jsonreference v0.21.6/go.mod h1:xzbgtQ3ZbWxvET3AxdzCJlJt6vkovbf+IfSPJjD0tUY=
github.com/go-openapi/loads v0.23.3 h1:g5Xap1JfwKkUnZdn+S0L3SzBDpcTIYzZ5Qaag0YDkKQ=
github.com/go-openapi/loads v0.23.3/go.mod h1:NOH07zLajXo8y55hom0omlHWDVVvCwBM/S+csCK8LqA=
github.com/go-openapi/runtime v0.31.0 h1:vhmlo1LMjGXYTlYB0eFm0tTVuAidDHtmrL1nAABzUCg=
github.com/go-openapi/runtime v0.31.0/go.mod h1:fZnoje1YWt7IrH/fHBOS1h9+VzeS1d0cHj8TTkZOaRc=
github.com/go-openapi/runtime v0.32.3 h1:J7Ycy5DJmhhP1By3NifhRUjnkXTrk21qbeqSULjwX8U=
github.com/go-openapi/runtime v0.32.3/go.mod h1:/WTQi0fa5DiGnnCXQKsTkSm15OzJp8Uz3H2t+67TBr4=
github.com/go-openapi/runtime/server-middleware v0.30.0 h1:8rPoJ/xv7JL8BsovaqboKETlpWBArVh8n+0L/GyePog=
github.com/go-openapi/runtime/server-middleware v0.30.0/go.mod h1:OYNT/TxNvB/VK5oe4htM2jDTwlEXuejVJmu0DVZfAMs=
github.com/go-openapi/spec v0.22.4 h1:4pxGjipMKu0FzFiu/DPwN3CTBRlVM2yLf/YTWorYfDQ=
github.com/go-openapi/spec v0.22.4/go.mod h1:WQ6Ai0VPWMZgMT4XySjlRIE6GP1bGQOtEThn3gcWLtQ=
github.com/go-openapi/strfmt v0.26.2 h1:ysjheCh4i1rmFEo2LanhELDNucNzfWTZhUDKgWWPaFM=
github.com/go-openapi/strfmt v0.26.2/go.mod h1:fXh1e449cyUn2NYuz+wb3wARBUdMl7qPEZwX00nqivY=
github.com/go-openapi/spec v0.22.5 h1:KhO7RBlKQfonUWX2WzQCoLIXVA6AcNqDGZ3a1Dutdlo=
github.com/go-openapi/spec v0.22.5/go.mod h1:vxpOtMya5TXtENXKE5bKqv5NjocVhyhxHrlZfvKnZ74=
github.com/go-openapi/strfmt v0.26.3 h1:rzmslHarJgBbf2qfGge+X3htclQfmXqBZMm0Too0HhU=
github.com/go-openapi/strfmt v0.26.3/go.mod h1:a5nsUw0oRpQzZeOwx8bi6cKbzFZslpbCKt1LEot+KnQ=
github.com/go-openapi/swag/conv v0.26.0 h1:5yGGsPYI1ZCva93U0AoKi/iZrNhaJEjr324YVsiD89I=
github.com/go-openapi/swag/conv v0.26.0/go.mod h1:tpAmIL7X58VPnHHiSO4uE3jBeRamGsFsfdDeDtb5ECE=
github.com/go-openapi/swag/fileutils v0.26.0 h1:WJoPRvsA7QRiiWluowkLJa9jaYR7FCuxmDvnCgaRRxU=
@@ -79,12 +79,12 @@ github.com/go-openapi/swag/typeutils v0.26.0 h1:2kdEwdiNWy+JJdOvu5MA2IIg2SylWAFu
github.com/go-openapi/swag/typeutils v0.26.0/go.mod h1:oovDuIUvTrEHVMqWilQzKzV4YlSKgyZmFh7AlfABNVE=
github.com/go-openapi/swag/yamlutils v0.26.0 h1:H7O8l/8NJJQ/oiReEN+oMpnGMyt8G0hl460nRZxhLMQ=
github.com/go-openapi/swag/yamlutils v0.26.0/go.mod h1:1evKEGAtP37Pkwcc7EWMF0hedX0/x3Rkvei2wtG/TbU=
github.com/go-openapi/testify/enable/yaml/v2 v2.5.0 h1:3hZD1fwydvCx/cc1R2uYNQirHqf2s6lqpKV3FcNTURA=
github.com/go-openapi/testify/enable/yaml/v2 v2.5.0/go.mod h1:TvDZKBH7ZbMaF3EqH2AwTvNQCmzyZq8K1agRjf1B+Nk=
github.com/go-openapi/testify/v2 v2.5.0 h1:UOCr63aAsMIDydZbZGqo5Ev01D4eydItRbekDuZMJLw=
github.com/go-openapi/testify/v2 v2.5.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
github.com/go-openapi/validate v0.25.2 h1:12NsfLAwGegqbGWr2CnvT65X/Q2USJipmJ9b7xDJZz0=
github.com/go-openapi/validate v0.25.2/go.mod h1:Pgl1LpPPGFnZ+ys4/hTlDiRYQdI1ocKypgE+8Q8BLfY=
github.com/go-openapi/testify/enable/yaml/v2 v2.5.1 h1:q9NtHwK4qHF7yZziBPvZyv7zWAIk8ok88Gh2mR6Jpc8=
github.com/go-openapi/testify/enable/yaml/v2 v2.5.1/go.mod h1:JW0MXIotCYps/XsgJnG3a8Q7rE5xAiBwoOD5OfaIQBk=
github.com/go-openapi/testify/v2 v2.5.1 h1:TMdhCaw8fUNraVSf3Omoob1dO/AzBfhtFAPW0an6sBo=
github.com/go-openapi/testify/v2 v2.5.1/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
github.com/go-openapi/validate v0.25.3 h1:4nzAIavcJ7WveHK2+V1UAkZK3kWcjzxZCzjfZAfavKs=
github.com/go-openapi/validate v0.25.3/go.mod h1:GemfuGMyYpIaBoKpX3z8sLywrmxpzWVOoJ7R0VeAVuk=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
@@ -107,10 +107,10 @@ github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2e
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grafana/pyroscope-go v1.3.0 h1:t3Jehad8vvqN4oRAB0LdmfQ5ZSUXQw3asoft+K4GAT8=
github.com/grafana/pyroscope-go v1.3.0/go.mod h1:XA7I3usNx+UdjOZfQnl1WV8y924vsJo9KIVrKB+9jx4=
github.com/grafana/pyroscope-go/godeltaprof v0.1.10 h1:dvhndEbyavTb59vFCd6PsrAG5qi69/qZZtegh/TJKSY=
github.com/grafana/pyroscope-go/godeltaprof v0.1.10/go.mod h1:XnWRGg2XO5uxZdiz1rfeJH6w1eZ+YICCBVXNWOfH86g=
github.com/grafana/pyroscope-go v1.3.1 h1:Eb9h55+vtLezn/DQ4iXz+SJrOz8CNghDk9xx8XQ4tc0=
github.com/grafana/pyroscope-go v1.3.1/go.mod h1:vjZr7UNVSvbpVH+G9SBy8K0fATjfYwl+W12xLNOx9Xg=
github.com/grafana/pyroscope-go/godeltaprof v0.1.11 h1:el5LYpXissAiCKZ5/6yjlr6mhYVV6Cp5lahTocxraXM=
github.com/grafana/pyroscope-go/godeltaprof v0.1.11/go.mod h1:jl1V8M4cWsXciROCPIDDG7CtjSjT/ECbp6eLVuMxYRI=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -189,8 +189,8 @@ github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -201,14 +201,14 @@ github.com/wwt/guac v1.3.2/go.mod h1:eKm+NrnK7A88l4UBEcYNpZQGMpZRryYKoz4D/0/n1C0
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo=
go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58=
go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0=
go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk=
go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
@@ -229,8 +229,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w=
golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ=
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -247,8 +247,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+1 -1
View File
@@ -55,7 +55,7 @@ type APIController struct {
instanceUUID uuid.UUID
}
// NewAPIController initialise new API Controller instance from URL and API token
// NewAPIController initialize new API Controller instance from URL and API token
func NewAPIController(akURL url.URL, token string) *APIController {
rsp := sentry.StartSpan(context.Background(), "authentik.outposts.init")
log := log.WithField("logger", "authentik.outpost.ak-api-controller")
+1 -1
View File
@@ -60,7 +60,7 @@ func doGlobalSetup(outpost api.Outpost, globalConfig *api.Config) {
},
})
if err != nil {
l.WithField("env", globalConfig.ErrorReporting.Environment).WithError(err).Warning("Failed to initialise sentry")
l.WithField("env", globalConfig.ErrorReporting.Environment).WithError(err).Warning("Failed to initialize sentry")
}
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ func NewDirectBinder(si server.LDAPServerInstance) *DirectBinder {
si: si,
log: log.WithField("logger", "authentik.outpost.ldap.binder.direct"),
}
db.log.Info("initialised direct binder")
db.log.Info("initialized direct binder")
return db
}
+2 -2
View File
@@ -32,14 +32,14 @@ func NewSessionBinder(si server.LDAPServerInstance, oldBinder bind.Binder) *Sess
if oldSb, ok := oldBinder.(*SessionBinder); ok {
sb.DirectBinder = oldSb.DirectBinder
sb.sessions = oldSb.sessions
sb.log.Debug("re-initialised session binder")
sb.log.Debug("re-initialized session binder")
return sb
}
}
sb.sessions = ttlcache.New(ttlcache.WithDisableTouchOnHit[Credentials, ldap.LDAPResultCode]())
sb.DirectBinder = *direct.NewDirectBinder(si)
go sb.sessions.Start()
sb.log.Debug("initialised session binder")
sb.log.Debug("initialized session binder")
return sb
}
@@ -42,12 +42,12 @@ func NewMemorySearcher(si server.LDAPServerInstance, existing search.Searcher) *
if ems, ok := existing.(*MemorySearcher); ok {
ems.si = si
ems.fetch()
ems.log.Debug("re-initialised memory searcher")
ems.log.Debug("re-initialized memory searcher")
return ems
}
}
ms.fetch()
ms.log.Debug("initialised memory searcher")
ms.log.Debug("initialized memory searcher")
return ms
}
+4 -4
View File
@@ -9,7 +9,7 @@
"version": "0.0.0",
"license": "MIT",
"devDependencies": {
"aws-cdk": "^2.1123.0",
"aws-cdk": "^2.1125.0",
"cross-env": "^10.1.0"
},
"engines": {
@@ -25,9 +25,9 @@
"license": "MIT"
},
"node_modules/aws-cdk": {
"version": "2.1123.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1123.0.tgz",
"integrity": "sha512-s4kN0Dk75TMAqnITGuWk39hzGeHAUhCcYx4Yf2eWT1QSMsOnHs4seOmeL8eXpk8oSp19NJOyF4m6XBP6fux+7A==",
"version": "2.1125.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1125.0.tgz",
"integrity": "sha512-QAvsE2XQMcyNOjMMqAS7eDADR9t6vcFcMQvhOmtLfDqgfJXSyTkHvzM5zgwZCdJ4FNqWr5Y/zXvL1Cv5ECKXwQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
+1 -1
View File
@@ -7,7 +7,7 @@
"aws-cfn": "cross-env CI=false cdk synth --version-reporting=false > template.yaml"
},
"devDependencies": {
"aws-cdk": "^2.1123.0",
"aws-cdk": "^2.1125.0",
"cross-env": "^10.1.0"
},
"engines": {
+4 -4
View File
@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Stage: Build webui
FROM --platform=${BUILDPLATFORM} docker.io/library/node:26-trixie-slim@sha256:1e738cb88890a15c71880323fbc35a739b7bbc703d72e8bfd1613128f8182f78 AS node-builder
FROM --platform=${BUILDPLATFORM} docker.io/library/node:26-trixie-slim@sha256:aa27a5fbf5acb298116a38133794f080406c6f8dfe52e2e2836bb55dc7cae8f0 AS node-builder
ARG GIT_BUILD_HASH
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
@@ -41,7 +41,7 @@ RUN npm run build && \
npm run build:sfe
# Stage: Build go proxy
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.3-trixie@sha256:0f6b034c99663ea8957e7dae99124e37374cbe7fcb5b5646f19b185f8f976279 AS go-builder
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.4-trixie@sha256:0dcba0d95dbfb072e9917a106b9e07d7cc298097dc83e9307056ef1889de654d AS go-builder
ARG TARGETOS
ARG TARGETARCH
@@ -116,9 +116,9 @@ RUN --mount=type=bind,target=rust-toolchain.toml,src=rust-toolchain.toml \
RUN cat /root/.rustup/settings.toml
# Stage: Download uv
FROM ghcr.io/astral-sh/uv:0.11.16@sha256:440fd6477af86a2f1b38080c539f1672cd22acb1b1a47e321dba5158ab08864d AS uv
FROM ghcr.io/astral-sh/uv:0.11.19@sha256:b46b03ddfcfbf8f547af7e9eaefdf8a39c8cebcba7c98858d3162bd28cf536f6 AS uv
# Stage: Base python image
FROM ghcr.io/goauthentik/fips-python:3.14.5-slim-trixie-fips@sha256:33d1ed94f2766b893018c038482873aca6e678fb0d4bc053483a4008c574e3c2 AS python-base
FROM ghcr.io/goauthentik/fips-python:3.14.5-slim-trixie-fips@sha256:dc515b79d2c76d12adae52116c655f6cf3f8a217f88afa103278cf036bda8597 AS python-base
ENV VENV_PATH="/ak-root/.venv" \
PATH="/lifecycle:/ak-root/.venv/bin:$PATH" \
+1 -1
View File
@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Stage 1: Build
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.3-trixie@sha256:0f6b034c99663ea8957e7dae99124e37374cbe7fcb5b5646f19b185f8f976279 AS builder
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.4-trixie@sha256:0dcba0d95dbfb072e9917a106b9e07d7cc298097dc83e9307056ef1889de654d AS builder
ARG TARGETOS
ARG TARGETARCH
+1 -1
View File
@@ -32,7 +32,7 @@ COPY web .
RUN npm run build-proxy
# Stage 2: Build
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.3-trixie@sha256:0f6b034c99663ea8957e7dae99124e37374cbe7fcb5b5646f19b185f8f976279 AS builder
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.4-trixie@sha256:0dcba0d95dbfb072e9917a106b9e07d7cc298097dc83e9307056ef1889de654d AS builder
ARG TARGETOS
ARG TARGETARCH
+1 -1
View File
@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Stage 1: Build
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.3-trixie@sha256:0f6b034c99663ea8957e7dae99124e37374cbe7fcb5b5646f19b185f8f976279 AS builder
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.4-trixie@sha256:0dcba0d95dbfb072e9917a106b9e07d7cc298097dc83e9307056ef1889de654d AS builder
ARG TARGETOS
ARG TARGETARCH
+1 -1
View File
@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Stage 1: Build
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.3-trixie@sha256:0f6b034c99663ea8957e7dae99124e37374cbe7fcb5b5646f19b185f8f976279 AS builder
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.4-trixie@sha256:0dcba0d95dbfb072e9917a106b9e07d7cc298097dc83e9307056ef1889de654d AS builder
ARG TARGETOS
ARG TARGETARCH
+4
View File
@@ -1,4 +1,5 @@
# Integrations
ADOM
appflowy
Ascensio
Authy
@@ -8,6 +9,7 @@ Budibase
Doki
Doku
dokuwiki
Dozzle
Engomo
Espo
espocrm
@@ -25,6 +27,7 @@ Gravitee
grommunio
HACS
Homarr
Icinga
Informatique
Jellyseerr
Kimai
@@ -36,6 +39,7 @@ Kubeconfig
Mautic
Mobilizon
myabsorb
Nexterm
Observium
Ofair
Ollama
@@ -93,6 +93,7 @@ frie
gcsp
geoip
glpi
gosaml
grecaptcha
guac
guacd
@@ -113,6 +114,7 @@ microsoft
mmdb
noopener
noreferrer
oktadev
openidc
ouia
ouid
Binary file not shown.
+26 -7
View File
@@ -15,7 +15,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-05-06 00:27+0000\n"
"POT-Creation-Date: 2026-05-22 00:36+0000\n"
"PO-Revision-Date: 2025-12-01 19:09+0000\n"
"Last-Translator: Sp P, 2026\n"
"Language-Team: French (France) (https://app.transifex.com/authentik/teams/119923/fr_FR/)\n"
@@ -118,11 +118,11 @@ msgstr "Le fichier de plan n'existe pas"
#: authentik/blueprints/api.py
msgid "Context must be valid JSON"
msgstr ""
msgstr "Le contexte doit être un JSON valide"
#: authentik/blueprints/api.py
msgid "Context must be a JSON object"
msgstr ""
msgstr "Le contexte doit être un objet JSON"
#: authentik/blueprints/api.py
msgid "Failed to validate blueprint"
@@ -261,6 +261,11 @@ msgstr ""
"Le slug '{slug}' est réservé et ne peut pas être utilisé pour les "
"applications."
#: authentik/core/api/groups.py
msgid "User does not have permission to add members to this group."
msgstr ""
"L'utilisateur n'a pas la permission d'ajouter des membres à ce groupe."
#: authentik/core/api/providers.py
msgid ""
"When not set all providers are returned. When set to true, only backchannel "
@@ -303,6 +308,16 @@ msgid "Setting a user to internal service account is not allowed."
msgstr ""
"Définir un utilisateur comme compte de service interne n'est pas autorisé."
#: authentik/core/api/users.py
msgid "User does not have permission to add members to a superuser group."
msgstr ""
"L'utilisateur n'a pas la permission d'ajouter des membres à un groupe de "
"super-utilisateurs."
#: authentik/core/api/users.py
msgid "User does not have permission to assign roles."
msgstr "L'utilisateur n'a pas la permission d'assigner des rôles."
#: authentik/core/api/users.py
msgid "Can't modify internal service account users"
msgstr "Impossible de modifier les utilisateurs du compte de service interne"
@@ -1549,11 +1564,11 @@ msgstr ""
#: authentik/events/models.py
msgid ""
"When set, the selected ceritifcate is used to validate the certificate of "
"When set, the selected certificate is used to validate the certificate of "
"the webhook server."
msgstr ""
"Quand défini, le certificat sélectionné est utilisé pour valider le "
"certificat du serveur de Webhook."
"certificat du serveur de Webhook"
#: authentik/events/models.py
msgid ""
@@ -3123,8 +3138,12 @@ msgid "SAML Sessions"
msgstr "Sessions SAML"
#: authentik/providers/scim/models.py
msgid "OAuth"
msgstr "OAuth"
msgid "OAuth (Silent)"
msgstr "OAuth (silencieux)"
#: authentik/providers/scim/models.py
msgid "OAuth (interactive)"
msgstr "OAuth (en interactif)"
#: authentik/providers/scim/models.py
msgid "Default"
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
+59 -30
View File
@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-05-06 00:27+0000\n"
"POT-Creation-Date: 2026-05-22 00:36+0000\n"
"PO-Revision-Date: 2025-12-01 19:09+0000\n"
"Last-Translator: Raphael Cancelliere, 2026\n"
"Language-Team: Norwegian (Norway) (https://app.transifex.com/authentik/teams/119923/no_NO/)\n"
@@ -111,11 +111,11 @@ msgstr "Blueprint-filen eksisterer ikke"
#: authentik/blueprints/api.py
msgid "Context must be valid JSON"
msgstr ""
msgstr "Konteksten må være gyldig JSON"
#: authentik/blueprints/api.py
msgid "Context must be a JSON object"
msgstr ""
msgstr "Konteksten må være et JSON-objekt"
#: authentik/blueprints/api.py
msgid "Failed to validate blueprint"
@@ -189,7 +189,7 @@ msgid ""
"When set, external users will be redirected to this application after "
"authenticating."
msgstr ""
"Når den er angitt, vil eksterne brukere bli omdirigert til denne "
"Når dette er angitt, blir eksterne brukere omdirigert til denne "
"applikasjonen etter autentisering."
#: authentik/brands/models.py
@@ -245,6 +245,11 @@ msgstr "Brukeren har ikke tilgang til applikasjonen."
msgid "The slug '{slug}' is reserved and cannot be used for applications."
msgstr "Slug-en '{slug}' er reservert og kan ikke brukes for applikasjoner."
#: authentik/core/api/groups.py
msgid "User does not have permission to add members to this group."
msgstr ""
"Brukeren har ikke tillatelse til å legge til medlemmer i denne gruppen."
#: authentik/core/api/providers.py
msgid ""
"When not set all providers are returned. When set to true, only backchannel "
@@ -258,10 +263,11 @@ msgstr ""
#: authentik/core/api/users.py
msgid "Invalid password hash format. Must be a valid Django password hash."
msgstr ""
"Ugyldig format for passord-hash. Må være en gyldig Django-passord-hash."
#: authentik/core/api/users.py
msgid "Cannot set both password and password_hash. Use only one."
msgstr ""
msgstr "Kan ikke angi både password og password_hash. Bruk bare én."
#: authentik/core/api/users.py
msgid "No leading or trailing slashes allowed."
@@ -279,6 +285,16 @@ msgstr "Kan ikke endre intern tjenestekonto til annen brukertype."
msgid "Setting a user to internal service account is not allowed."
msgstr "Det er ikke tillatt å sette en bruker til intern tjenestekonto."
#: authentik/core/api/users.py
msgid "User does not have permission to add members to a superuser group."
msgstr ""
"Brukeren har ikke tillatelse til å legge til medlemmer i en "
"superbrukergruppe."
#: authentik/core/api/users.py
msgid "User does not have permission to assign roles."
msgstr "Brukeren har ikke tillatelse til å tildele roller."
#: authentik/core/api/users.py
msgid "Can't modify internal service account users"
msgstr "Kan ikke endre brukere med intern tjenestekonto"
@@ -439,7 +455,7 @@ msgstr "Åpne start-URL i en ny nettleserfane eller -vindu."
#: authentik/core/models.py
msgid "Hide this application from the user's My applications page."
msgstr ""
msgstr "Skjul denne applikasjonen fra brukerens side Mine applikasjoner."
#: authentik/core/models.py
msgid "Application"
@@ -969,6 +985,8 @@ msgstr "Gå til {self._get_model_name()}"
msgid ""
"Access review is due for {self.content_type.name.lower()} {object_label}"
msgstr ""
"Tilgangsgjennomgang for {self.content_type.name.lower()} {object_label} "
"forfaller"
#: authentik/enterprise/lifecycle/models.py
msgid ""
@@ -985,7 +1003,7 @@ msgstr ""
#: authentik/enterprise/lifecycle/tasks.py
msgid "Dispatch tasks to apply lifecycle rules."
msgstr ""
msgstr "Send oppgaver for å bruke livssyklusregler."
#: authentik/enterprise/lifecycle/tasks.py
msgid "Apply lifecycle rule."
@@ -1324,74 +1342,79 @@ msgstr "Generer eksport av data."
#: authentik/enterprise/stages/account_lockdown/api.py
msgid "User to lock. If omitted, locks the current user (self-service)."
msgstr ""
"Bruker som skal låses. Hvis utelatt, låses gjeldende bruker (selvbetjening)."
#: authentik/enterprise/stages/account_lockdown/api.py
msgid "No lockdown flow configured."
msgstr ""
msgstr "Ingen låseflyt er konfigurert."
#: authentik/enterprise/stages/account_lockdown/api.py
msgid "Lockdown flow is not applicable."
msgstr ""
msgstr "Låseflyten er ikke relevant."
#: authentik/enterprise/stages/account_lockdown/api.py
msgid "Choose the target account, then return a flow link."
msgstr ""
msgstr "Velg målkontoen, og returner deretter en flytlenke."
#: authentik/enterprise/stages/account_lockdown/api.py
msgid "No lockdown flow configured or the flow is not applicable"
msgstr ""
msgstr "Ingen låseflyt er konfigurert, eller flyten er ikke relevant"
#: authentik/enterprise/stages/account_lockdown/api.py
msgid "Permission denied (when targeting another user)"
msgstr ""
msgstr "Tilgang nektet (ved målretting mot en annen bruker)"
#: authentik/enterprise/stages/account_lockdown/models.py
msgid "Deactivate the user account (set is_active to False)"
msgstr ""
msgstr "Deaktiver brukerkontoen (sett is_active til False)"
#: authentik/enterprise/stages/account_lockdown/models.py
msgid "Set an unusable password for the user"
msgstr ""
msgstr "Angi et ubrukelig passord for brukeren"
#: authentik/enterprise/stages/account_lockdown/models.py
msgid "Delete all active sessions for the user"
msgstr ""
msgstr "Slett alle aktive økter for brukeren"
#: authentik/enterprise/stages/account_lockdown/models.py
msgid ""
"Revoke all tokens for the user (API, app password, recovery, verification, "
"OAuth)"
msgstr ""
"Tilbakekall alle tokener for brukeren (API, app-passord, gjenoppretting, "
"verifisering, OAuth)"
#: authentik/enterprise/stages/account_lockdown/models.py
msgid ""
"Flow to redirect users to after self-service lockdown. This flow should not "
"require authentication since the user's session is deleted."
msgstr ""
"Flyt brukere videresendes til etter kontolåsing via selvbetjening. Denne "
"flyten bør ikke kreve autentisering siden brukerens økt er slettet."
#: authentik/enterprise/stages/account_lockdown/models.py
msgid "Account Lockdown Stage"
msgstr ""
msgstr "Trinn for kontolåsing"
#: authentik/enterprise/stages/account_lockdown/models.py
msgid "Account Lockdown Stages"
msgstr ""
msgstr "Trinn for kontolåsing"
#: authentik/enterprise/stages/account_lockdown/stage.py
msgid "No target user specified for account lockdown"
msgstr ""
msgstr "Ingen målbruker er angitt for kontolåsing"
#: authentik/enterprise/stages/account_lockdown/stage.py
msgid "You do not have permission to lock down this account."
msgstr ""
msgstr "Du har ikke tillatelse til å låse denne kontoen."
#: authentik/enterprise/stages/account_lockdown/stage.py
msgid "Account lockdown failed for this account."
msgstr ""
msgstr "Kontolåsing mislyktes for denne kontoen."
#: authentik/enterprise/stages/account_lockdown/stage.py
msgid "Self-service account lockdown requires a completion flow."
msgstr ""
msgstr "Kontolåsing via selvbetjening krever en fullføringsflyt."
#: authentik/enterprise/stages/authenticator_endpoint_gdtc/models.py
msgid "Endpoint Authenticator Google Device Trust Connector Stage"
@@ -1494,10 +1517,10 @@ msgstr ""
#: authentik/events/models.py
msgid ""
"When set, the selected ceritifcate is used to validate the certificate of "
"When set, the selected certificate is used to validate the certificate of "
"the webhook server."
msgstr ""
"Når det er angitt, brukes det valgte sertifikatet til å validere "
"Hvis dette er konfigurert, brukes det valgte sertifikatet til å validere "
"sertifikatet til webhook-serveren."
#: authentik/events/models.py
@@ -2797,6 +2820,8 @@ msgid ""
"Also known as EntityID. Providing a value overrides the default issuer "
"generated by authentik."
msgstr ""
"Også kjent som EntityID. Hvis du angir en verdi, overstyres "
"standardutstederen generert av authentik."
#: authentik/providers/saml/models.py
msgid "SLS URL"
@@ -3016,7 +3041,7 @@ msgstr "SAML NameID-format"
#: authentik/providers/saml/models.py
msgid "SAML Issuer used for this session"
msgstr ""
msgstr "SAML-utsteder brukt for denne økten"
#: authentik/providers/saml/models.py
msgid "SAML Session"
@@ -3027,8 +3052,12 @@ msgid "SAML Sessions"
msgstr "SAML-økter"
#: authentik/providers/scim/models.py
msgid "OAuth"
msgstr "OAuth"
msgid "OAuth (Silent)"
msgstr "OAuth (stille)"
#: authentik/providers/scim/models.py
msgid "OAuth (interactive)"
msgstr "OAuth (interaktiv)"
#: authentik/providers/scim/models.py
msgid "Default"
@@ -3052,7 +3081,7 @@ msgstr "Webex"
#: authentik/providers/scim/models.py
msgid "vCenter"
msgstr ""
msgstr "vCenter"
#: authentik/providers/scim/models.py
msgid "Group filters used to define sync-scope for groups."
@@ -4930,15 +4959,15 @@ msgstr "Statisk: Statisk verdi, vises som den er."
#: authentik/stages/prompt/models.py
msgid "Alert (Info): Static alert box with info styling"
msgstr ""
msgstr "Varsel (Info): Statisk varselboks med infostil"
#: authentik/stages/prompt/models.py
msgid "Alert (Warning): Static alert box with warning styling"
msgstr ""
msgstr "Varsel (Advarsel): Statisk varselboks med advarselsstil"
#: authentik/stages/prompt/models.py
msgid "Alert (Danger): Static alert box with danger styling"
msgstr ""
msgstr "Varsel (Fare): Statisk varselboks med farestil"
#: authentik/stages/prompt/models.py
msgid "authentik: Selection of locales authentik supports"
+3 -3
View File
@@ -22552,9 +22552,9 @@
}
},
"node_modules/tmp": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
"integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==",
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz",
"integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==",
"license": "MIT",
"engines": {
"node": ">=14.14"
+2 -2
View File
@@ -210,7 +210,7 @@ impl Arbiter {
/// Consumers listening on this must also listen on [`Arbiter::graceful_shutdown`], as only one
/// of those is set upon shutdown.
///
/// It is also possible to use [`Arbiter::shutdown`] when the behaviour is the same between a
/// It is also possible to use [`Arbiter::shutdown`] when the behavior is the same between a
/// fast and a graceful shutdown.
pub fn fast_shutdown(&self) -> WaitForCancellationFuture<'_> {
self.fast_shutdown.cancelled()
@@ -221,7 +221,7 @@ impl Arbiter {
/// Consumers listening on this must also listen on [`Arbiter::fast_shutdown`], as only one
/// of those is set upon shutdown.
///
/// It is also possible to use [`Arbiter::shutdown`] when the behaviour is the same between a
/// It is also possible to use [`Arbiter::shutdown`] when the behavior is the same between a
/// fast and a graceful shutdown.
pub fn graceful_shutdown(&self) -> WaitForCancellationFuture<'_> {
self.graceful_shutdown.cancelled()
+28 -1
View File
@@ -1,7 +1,7 @@
use std::{collections::HashMap, net::SocketAddr, num::NonZeroUsize};
use ipnet::IpNet;
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize, de::Error as _};
pub(super) const KEYS_TO_PARSE_AS_LIST: [&str; 4] = [
"listen.http",
@@ -10,6 +10,32 @@ pub(super) const KEYS_TO_PARSE_AS_LIST: [&str; 4] = [
"log.http_headers",
];
fn deserialize_optional_u64<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
where
D: Deserializer<'de>,
{
// The value comes as a number from config files but as a string from env vars.
#[derive(Deserialize)]
#[serde(untagged)]
enum NumOrStr {
Num(u64),
Str(String),
}
match Option::<NumOrStr>::deserialize(deserializer)? {
None => Ok(None),
Some(NumOrStr::Num(n)) => Ok(Some(n)),
Some(NumOrStr::Str(s)) => {
let s = s.trim();
if s.is_empty() || s.eq_ignore_ascii_case("none") || s.eq_ignore_ascii_case("null") {
Ok(None)
} else {
s.parse().map(Some).map_err(D::Error::custom)
}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub postgresql: PostgreSQLConfig,
@@ -50,6 +76,7 @@ pub struct PostgreSQLConfig {
pub sslcert: Option<String>,
pub sslkey: Option<String>,
#[serde(deserialize_with = "deserialize_optional_u64")]
pub conn_max_age: Option<u64>,
pub conn_health_checks: bool,
+19 -8
View File
@@ -5,6 +5,7 @@ use sqlx::{
ConnectOptions as _, Executor as _, PgConnection, PgPool,
postgres::{PgConnectOptions, PgPoolOptions, PgSslMode},
};
use tokio::fs::read_to_string;
use tracing::{info, log::LevelFilter, trace};
use crate::{
@@ -15,7 +16,7 @@ use crate::{
static DB: OnceLock<PgPool> = OnceLock::new();
fn get_connect_opts() -> Result<PgConnectOptions> {
async fn get_connect_opts() -> Result<PgConnectOptions> {
let config = config::get();
let mut opts = PgConnectOptions::new()
.application_name(&format!(
@@ -30,13 +31,19 @@ fn get_connect_opts() -> Result<PgConnectOptions> {
.database(&config.postgresql.name)
.ssl_mode(PgSslMode::from_str(&config.postgresql.sslmode)?);
if let Some(sslrootcert) = &config.postgresql.sslrootcert {
opts = opts.ssl_root_cert_from_pem(sslrootcert.as_bytes().to_vec());
let from_fs = read_to_string(sslrootcert).await;
let data = from_fs.as_ref().unwrap_or(sslrootcert).as_bytes().to_vec();
opts = opts.ssl_root_cert_from_pem(data);
}
if let Some(sslcert) = &config.postgresql.sslcert {
opts = opts.ssl_client_cert_from_pem(sslcert.as_bytes());
let from_fs = read_to_string(sslcert).await;
let data = from_fs.as_ref().unwrap_or(sslcert).as_bytes();
opts = opts.ssl_client_cert_from_pem(data);
}
if let Some(sslkey) = &config.postgresql.sslkey {
opts = opts.ssl_client_key_from_pem(sslkey.as_bytes());
let from_fs = read_to_string(sslkey).await;
let data = from_fs.as_ref().unwrap_or(sslkey).as_bytes();
opts = opts.ssl_client_key_from_pem(data);
}
Ok(opts)
}
@@ -49,7 +56,7 @@ async fn update_connect_opts_on_config_change(arbiter: Arbiter) -> Result<()> {
Ok(Event::ConfigChanged) = events_rx.recv() => {
trace!("config change received, refreshing database connection options");
let db = get();
db.set_connect_options(get_connect_opts()?);
db.set_connect_options(get_connect_opts().await?);
},
() = arbiter.shutdown() => {
info!("stopping database watcher for config changes");
@@ -61,14 +68,13 @@ async fn update_connect_opts_on_config_change(arbiter: Arbiter) -> Result<()> {
pub async fn init(tasks: &mut Tasks) -> Result<()> {
info!("initializing database pool");
let options = get_connect_opts()?;
let options = get_connect_opts().await?;
let config = config::get();
let pool_options = PgPoolOptions::new()
.min_connections(1)
.max_connections(4)
.acquire_time_level(LevelFilter::Trace)
.max_lifetime(config.postgresql.conn_max_age.map(Duration::from_secs))
.test_before_acquire(config.postgresql.conn_health_checks)
.after_connect(|conn, _meta| {
Box::pin(async move {
@@ -84,6 +90,11 @@ pub async fn init(tasks: &mut Tasks) -> Result<()> {
})
});
let pool_options = match config.postgresql.conn_max_age {
Some(0) => pool_options.after_release(|_conn, _meta| Box::pin(async { Ok(false) })),
other => pool_options.max_lifetime(other.map(Duration::from_secs)),
};
let pool = pool_options.connect_with(options).await?;
DB.get_or_init(|| pool);
@@ -106,7 +117,7 @@ pub fn get() -> &'static PgPool {
}
pub async fn create_conn() -> Result<PgConnection> {
let options = get_connect_opts()?;
let options = get_connect_opts().await?;
let conn = options.connect().await?;
Ok(conn)
}

Some files were not shown because too many files have changed in this diff Show More