Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,11 @@ jobs:
strategy:
fail-fast: false
matrix:
ssp-version: ["v2.5.0"]
# SimpleSAMLphp ref to build the OP base image from. Any Composer version works: a released tag
# (e.g. "v2.5.2") or an (unreleased) branch (e.g. "dev-simplesamlphp-2.5"). During v7 development
# the module depends on the unreleased simplesamlphp-2.5 branch, which exposes
# \SimpleSAML\Locale\Language::getAvailableLanguages() used by the ui_locales support.
ssp-composer-version: ["dev-simplesamlphp-2.5"]
env:
SUITE_BASE_URL: https://localhost.emobix.co.uk:8443
VERSION: release-v5.1.45
Expand Down Expand Up @@ -241,11 +245,22 @@ jobs:
run: |
docker compose -f docker-compose-dev.yml up -d
while ! curl -skfail https://localhost.emobix.co.uk:8443/api/runner/available >/dev/null; do sleep 2; done
- name: Build SimpleSAMLphp base image
# SimpleSAMLphp is installed into the base image via Composer (cirrus's SSP_COMPOSER_VERSION path),
# so any tag or branch can be used - here the unreleased simplesamlphp-2.5 branch the module
# currently depends on. The image is built locally each run and not pushed to any registry. The
# cirrus image recipe is pinned to a commit for reproducibility; bump it when needed.
run: |
git clone https://github.com/cirrusidentity/docker-simplesamlphp.git ssp-base-image
git -C ssp-base-image checkout 0bf3ae9df5c0
docker build ssp-base-image/docker \
--build-arg SSP_COMPOSER_VERSION=${{ matrix.ssp-composer-version }} \
-t ssp-base:${{ matrix.ssp-composer-version }}
- name: Start SSP docker
working-directory: ./main
# Must run after conformance suite since they share a docker network.
run: |
SSP_VERSION=${{ matrix.ssp-version }} OIDC_VERSION=@dev docker compose -f docker/docker-compose.yml --project-directory . up -d --build
SSP_IMAGE=ssp-base:${{ matrix.ssp-composer-version }} OIDC_VERSION=@dev docker compose -f docker/docker-compose.yml --project-directory . up -d --build
sleep 30
# while ! curl -skfail https://op.local.stack-dev.cirrusidentity.com/.well-known/openid-configuration >/dev/null; do sleep 2; done
- name: Run Basic conformance tests
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@
"spomky-labs/base64url": "^2.0",
"symfony/cache": "^7.4",
"symfony/expression-language": "^7.4",
"symfony/intl": "^7.4",
"symfony/psr-http-message-bridge": "^7.4",
"web-token/jwt-framework": "^3.4.10"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3",
"rector/rector": "^1.2.10",
"simplesamlphp/simplesamlphp": "2.5.*",
"simplesamlphp/simplesamlphp": "dev-simplesamlphp-2.5",
"simplesamlphp/simplesamlphp-test-framework": "^1.9.3",
"vimeo/psalm": "^6.15.1",
"testcontainers/testcontainers": "^0.2",
Expand Down
8 changes: 5 additions & 3 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
ARG SSP_VERSION="v2.5.0"
FROM cirrusid/simplesamlphp:${SSP_VERSION}
#FROM cicnavi/simplesamlphp:${SSP_VERSION}
# Base SimpleSAMLphp image. Defaults to a published cirrusid/simplesamlphp release tag, but can be
# overridden to run against a different base image, for example one built locally from an unreleased
# SimpleSAMLphp branch (see "Build against an unreleased SimpleSAMLphp version" in docs/4-oidc-docker.md).
ARG SSP_IMAGE="cirrusid/simplesamlphp:v2.5.0"
FROM ${SSP_IMAGE}

RUN apt-get update && apt-get --no-install-recommends install -y sqlite3
# Prepopulate the DB with items needed for testing
Expand Down
2 changes: 1 addition & 1 deletion docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ services:
context: .
dockerfile: docker/Dockerfile
args:
SSP_VERSION: "${SSP_VERSION}"
SSP_IMAGE: "${SSP_IMAGE:-cirrusid/simplesamlphp:v2.5.0}"
OIDC_VERSION: "${OIDC_VERSION}"
environment:
- STAGINGCOMPOSERREPOS=oidc
Expand Down
3 changes: 3 additions & 0 deletions docs/1-oidc.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,11 @@ Minor versions listed show which SimpleSAMLphp versions were used during
module development. SimpleSAMLphp follows semantic versioning for its
API since v2.0. PHP version requirements may differ.

TODO mivanci require simplesamlphp/simplesamlphp:^2.5.3 in composer.json

| OIDC module | Tested SimpleSAMLphp | PHP |
|:------------|:---------------------|:------:|
| v7\* | dev-simplesamlphp-2.5| \>=8.3 |
| v6.4.\* | v2.5.\* | \>=8.3 |
| v6.3.\* | v2.3.\*, v2.4.\* | \>=8.2 |
| v5.\* | v2.1.\* | \>=8.1 |
Expand Down
48 changes: 45 additions & 3 deletions docs/4-oidc-docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This document shows how to run and test the module with Docker.
- Local testing with other DBs
- Testing AuthProc filters
- Build image for conformance tests
- Build against an unreleased SimpleSAMLphp version
- Docker Compose

## Run with the current git branch (live mount)
Expand Down Expand Up @@ -117,18 +118,59 @@ docker exec ssp-oidc-dev-image sqlite3 /var/simplesamlphp/data/mydb.sq3 '.dump'

Conformance tests are easier to run locally. See [Conformance](5-oidc-conformance.md).

## Build against an unreleased SimpleSAMLphp version

The OP image is built `FROM` a SimpleSAMLphp base image, selected with the
`SSP_IMAGE` build argument (default: a published `cirrusid/simplesamlphp`
release tag). Published tags only exist for SimpleSAMLphp *releases*, so to run
against an unreleased SimpleSAMLphp branch (or any specific ref) you first build
a base image from that ref and then point `SSP_IMAGE` at it.

> During v7 development the module depends on the unreleased `simplesamlphp-2.5`
> branch (it uses `\SimpleSAML\Locale\Language::getAvailableLanguages()`, added
> there for the `ui_locales` support). Until a SimpleSAMLphp release contains it,
> the OP image must be built from that branch, otherwise the discovery endpoint
> fails.

The [cirrusid/simplesamlphp image](https://github.com/cirrusidentity/docker-simplesamlphp)
installs SimpleSAMLphp with Composer when given an `SSP_COMPOSER_VERSION` build
argument, which accepts any Composer version — a branch (`dev-<branch>`) or a
tag (`v2.5.2`):

```bash
# 1. Build a SimpleSAMLphp base image from the desired ref (branch or tag).
git clone https://github.com/cirrusidentity/docker-simplesamlphp.git
docker build docker-simplesamlphp/docker \
--build-arg SSP_COMPOSER_VERSION=dev-simplesamlphp-2.5 \
-t ssp-base:dev-simplesamlphp-2.5

# 2. Build and run the OP on top of it. For the docker/Dockerfile-based builds
# (Docker Compose below and the conformance image above) set SSP_IMAGE:
SSP_IMAGE=ssp-base:dev-simplesamlphp-2.5 OIDC_VERSION=@dev \
docker compose -f docker/docker-compose.yml --project-directory . up --build
```

For the live-mount `docker run` example above, use the built base image name
(`ssp-base:dev-simplesamlphp-2.5`) directly in place of
`cirrusid/simplesamlphp:...`. This is exactly what the GitHub Actions conformance
job does: it builds the base image from `matrix.ssp-composer-version` and passes
it as `SSP_IMAGE`.

## Docker Compose

Docker Compose runs multiple containers to ease testing. It builds an
image containing the OIDC module. You can remove `--build` to reuse an
existing container.
existing container. The SimpleSAMLphp base image defaults to a published
`cirrusid/simplesamlphp` release tag; override it with `SSP_IMAGE` to run
against a different base (see "Build against an unreleased SimpleSAMLphp
version" above).

```bash
# Use current branch/git checkout. Composer installs local checkout
OIDC_VERSION=@dev docker-compose -f docker/docker-compose.yml --project-directory . up --build
OIDC_VERSION=@dev docker compose -f docker/docker-compose.yml --project-directory . up --build

# Use a specific module version
OIDC_VERSION=dev-master docker-compose -f docker/docker-compose.yml --project-directory . up --build
OIDC_VERSION=dev-master docker compose -f docker/docker-compose.yml --project-directory . up --build
```

Visit the OP and verify a few clients exist:
Expand Down
22 changes: 15 additions & 7 deletions docs/5-oidc-conformance.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ Clone, build, and run the conformance test suite:
git clone https://gitlab.com/openid/conformance-suite.git
cd conformance-suite
git checkout release-v5.1.45
MAVEN_CACHE=./m2 docker-compose -f builder-compose.yml run builder
docker-compose up
MAVEN_CACHE=./m2 docker compose -f builder-compose.yml run builder
docker compose up
```

This starts the Java conformance app and a MongoDB server. Then:
Expand All @@ -35,8 +35,16 @@ Next, run your SSP OIDC image.
### Run SSP

Run SSP with OIDC on the same Docker network as the conformance tests so
containers can communicate. See the "Docker Compose" section in the
README for details.
containers can communicate. See the "Docker Compose" section in
[Using Docker](4-oidc-docker.md) for details.

The OP image is built on a SimpleSAMLphp base image. During v7 development the
module depends on the unreleased `simplesamlphp-2.5` branch, so the base image
must be built from that branch (or discovery fails); see
"Build against an unreleased SimpleSAMLphp version" in
[Using Docker](4-oidc-docker.md). The GitHub Actions conformance job does this
automatically: it builds the base image from the SimpleSAMLphp ref in its
matrix (`ssp-composer-version`) and passes it to the OP build as `SSP_IMAGE`.

### Run conformance tests (interactive)

Expand Down Expand Up @@ -149,7 +157,7 @@ Because the plan is deterministic, the GitHub Actions step is a blocking gate (n
`continue-on-error`).

Prerequisites: run the docker deploy image for conformance tests (see
README) and the conformance test image first.
[Using Docker](4-oidc-docker.md)) and the conformance test image first.

## Run hosted tests

Expand All @@ -158,8 +166,8 @@ OP must be publicly accessible on the internet.

### Deploy SSP OIDC image

Use the docker image described in the README. It contains a SQLite DB
pre-populated with data for the tests. Build and run the image.
Use the docker image described in [Using Docker](4-oidc-docker.md). It contains
a SQLite DB pre-populated with data for the tests. Build and run the image.

### Register and create conformance tests

Expand Down
23 changes: 23 additions & 0 deletions docs/6-oidc-upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,29 @@ per-field metadata policy (honored / validated / rejected) is documented in
future major version may switch the getters to fall back to the spec defaults.)
DCR is also opt-in (disabled by default), so unless you enable it, nothing changes
for your deployment.
- Support for the `ui_locales` parameter on the authorization and end session
endpoints (previously ignored). The parameter carries the End-User's preferred
UI languages as a space-separated list of BCP47 language tags, ordered by
preference. The most preferred requested language which is also available in
SimpleSAMLphp (per the `language.available` config option) is used to render
the screens shown during the flow. On the authorization endpoint, where the
login page and consent are rendered by SimpleSAMLphp in subsequent requests,
this is done via the standard SimpleSAMLphp language cookie (the same mechanism
as when the user picks a language on any SimpleSAMLphp page); to avoid a
client-supplied parameter silently overwriting a persistent, instance-wide
preference, an already present language cookie (an explicit choice the user
made) is not overridden. On the end session endpoint, the logout page is
rendered directly in the requested language, without setting the language
cookie. Matching includes a fallback to the primary language subtag (for
example, requested `fr-CA` matches available `fr`). Per specification this is
best-effort: if none of the requested languages are available, the parameter is
ignored without raising an error. The available languages are also advertised
in the OP discovery metadata via the `ui_locales_supported` claim (as BCP47
language tags). Note: use the canonical SimpleSAMLphp locale codes in
`language.available` (for example `pt_BR` and `zh_TW`); the deprecated codes
(`pt-br`, `zh-tw`), which SimpleSAMLphp itself warns against, are not fully
supported by `ui_locales` on the authorization endpoint, because the language
cookie is validated against the raw configured codes.
- Logging has been improved for authentication flows. It should now be easier
to find information about what went wrong by looking at the relevant log entries.

Expand Down
1 change: 1 addition & 0 deletions routing/services/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ services:
SimpleSAML\Module\oidc\Utils\Routes: ~
SimpleSAML\Module\oidc\Utils\RequestParamsResolver: ~
SimpleSAML\Module\oidc\Utils\UserIdentifierResolver: ~
SimpleSAML\Module\oidc\Utils\UiLocalesResolver: ~
SimpleSAML\Module\oidc\Utils\ClassInstanceBuilder: ~
SimpleSAML\Module\oidc\Utils\JwksResolver: ~
SimpleSAML\Module\oidc\Utils\AuthenticatedOAuth2ClientResolver: ~
Expand Down
7 changes: 7 additions & 0 deletions src/Bridges/SspBridge.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace SimpleSAML\Module\oidc\Bridges;

use SimpleSAML\Module\oidc\Bridges\SspBridge\Auth;
use SimpleSAML\Module\oidc\Bridges\SspBridge\Locale;
use SimpleSAML\Module\oidc\Bridges\SspBridge\Module;
use SimpleSAML\Module\oidc\Bridges\SspBridge\Utils;

Expand All @@ -17,6 +18,7 @@ class SspBridge
protected static ?Auth $auth = null;
protected static ?Utils $utils = null;
protected static ?Module $module = null;
protected static ?Locale $locale = null;

public function utils(): Utils
{
Expand All @@ -32,4 +34,9 @@ public function auth(): Auth
{
return self::$auth ??= new Auth();
}

public function locale(): Locale
{
return self::$locale ??= new Locale();
}
}
17 changes: 17 additions & 0 deletions src/Bridges/SspBridge/Locale.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\Module\oidc\Bridges\SspBridge;

use SimpleSAML\Module\oidc\Bridges\SspBridge\Locale\Language;

class Locale
{
protected static ?Language $language = null;

public function language(): Language
{
return self::$language ??= new Language();
}
}
35 changes: 35 additions & 0 deletions src/Bridges/SspBridge/Locale/Language.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\Module\oidc\Bridges\SspBridge\Locale;

use SimpleSAML\Configuration;
use SimpleSAML\Locale\Language as SspLanguage;

class Language
{
public function setLanguageCookie(string $language): void
{
SspLanguage::setLanguageCookie($language);
}

public function getLanguageCookie(): ?string
{
return SspLanguage::getLanguageCookie();
}

/**
* Get the languages available in SimpleSAMLphp (configured in language.available and known to the
* translation system), as computed by SimpleSAMLphp itself. The Language instance is created without
* handling the language request parameter, so that querying it does not trigger side effects like
* switching the current language or setting the language cookie.
*
* @return string[]
*/
public function getAvailableLanguages(Configuration $configuration): array
{
return (new SspLanguage($configuration, handleLanguageRequestParameter: false))
->getAvailableLanguages();
}
}
Loading
Loading