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
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ build: setup
cd repos/auth.proxy && pnpm install && pnpm run build
cd repos/auth.policy-verifier && pnpm install && pnpm run build

# One definition of the shared HS256 secret, interpolated into the containers
# by docker compose and exported to the test processes, which mint their own
# tokens with it. Defining it twice is how the suite drifted before: the tests
# fell back to a stale literal and every negative case failed as a 401 that
# read like a policy failure. auth.provider#282 requires >=32 decoded bytes.
export OAUTH_JWT_SECRET := qmV+afsq/SMZ7hPGs9edVQDvPzNmjXemJNjqti181v0=

.PHONY: test-e2e
test-e2e: build
docker compose -f tests/docker-compose.yml up -d --build --wait
Expand Down
9 changes: 7 additions & 2 deletions tests/abac/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,19 @@ function signToken(claims, options = {}) {

/** Grant carrying `read:project`. */
let projectGrant;
/** Grant carrying only `read:project_member` — used for the deny case. */
/**
* Grant carrying only `read:project.member` — used for the deny case, and for
* the nested-resource allow. The scope name tracks the resource type the
* verifier derives: auth.policy-verifier#117 stopped rewriting the `.`
* separator to `_`, so `project:1.member:2` now derives `project.member`.
*/
let memberGrant;

beforeAll(async () => {
const session = await login();
expect(session.status).toBe(200);
projectGrant = await codeFlow({ cookie: session.cookie, scope: 'openid read:project' });
memberGrant = await codeFlow({ cookie: session.cookie, scope: 'openid read:project_member' });
memberGrant = await codeFlow({ cookie: session.cookie, scope: 'openid read:project.member' });
}, 30_000);

describe('ABAC: POST /verify with provider-issued access tokens', () => {
Expand Down
20 changes: 17 additions & 3 deletions tests/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,24 @@ services:
- ./provider/clients.yaml:/home/node/templates/standalone/config/clients.yaml:ro
- ./provider/users.yaml:/home/node/templates/standalone/config/users.yaml:ro
environment:
- OAUTH_JWT_SECRET=test-secret-for-e2e
# auth.provider#282 made EdDSA the default and removed the HS256
# fallback, so the algorithm must be named explicitly. The E2E stays on
# HS256 deliberately: the verifier requires https for a JWKS URI, with an
# http carve-out only for loopback (auth.policy-verifier#109), and here it
# would reach the provider at http://provider:3000 — a compose service
# name, not loopback. A JWKS-based E2E would fail the verifier's boot
# check, so the two services share a secret instead.
- OAUTH_JWT_ALGORITHM=HS256
# #282 also put a >=32-byte floor on the decoded secret, measured at the
# smallest plausible reading. The value is defined once in the Makefile
# and interpolated here, because the ABAC tests mint tokens with the same
# secret — a second literal is how the two drifted apart before.
- OAUTH_JWT_SECRET=${OAUTH_JWT_SECRET:?run via make test-e2e}
# auth.provider requires a canonical issuer and never derives one from the
# request (auth.provider#266). It is an identifier, not a URL anything
# fetches, so the E2E pins a fixed one both services agree on.
- OAUTH_JWT_ISSUER=https://auth.e2e.test
- SESSION_SECRET=test-session-secret
- SESSION_SECRET=lO0QH09fuKSGuViZ9myJbH3jsgai99A2GpC3RYRuy6Y=
- SESSION_SECURE=false
# __Host- prefixed default requires secure=true; plain-HTTP E2E needs both overrides
- SESSION_NAME=auth.session
Expand Down Expand Up @@ -138,7 +150,9 @@ services:
volumes:
- ./abac/application.conf:/home/node/templates/standalone/config/application.conf:ro
environment:
- OAUTH_JWT_SECRET=test-secret-for-e2e
# Same interpolated secret as the provider — under HS256 the verifier
# holds the shared secret it verifies with.
- OAUTH_JWT_SECRET=${OAUTH_JWT_SECRET:?run via make test-e2e}
# auth.policy-verifier validates iss / aud / typ per RFC 9068 §4 and
# refuses to boot without them (auth.policy-verifier#105). The issuer must
# match what the provider stamps, and the audience must match what the
Expand Down
2 changes: 1 addition & 1 deletion tests/provider/clients.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ e2e-app:
- "openid"
- "email"
- "read:project"
- "read:project_member"
- "read:project.member"
allowedAudiences:
- "https://api.e2e.test"
allowedGrantTypes:
Expand Down
20 changes: 19 additions & 1 deletion tests/shared/oauthFlow.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,25 @@ export const VERIFIER_URL = process.env.VERIFIER_URL || 'http://localhost:3097';

export const ISSUER = process.env.OAUTH_JWT_ISSUER || 'https://auth.e2e.test';
export const AUDIENCE = process.env.OAUTH_JWT_AUDIENCE || 'https://api.e2e.test';
export const JWT_SECRET = process.env.OAUTH_JWT_SECRET || 'test-secret-for-e2e';
/**
* Must equal the containers' `OAUTH_JWT_SECRET` in tests/docker-compose.yml.
* The negative ABAC tests mint their own tokens with it, so a value that
* merely looks plausible produces 401s that read like a policy failure.
* There is deliberately no fallback: auth.provider#282 put a >=32-byte floor
* on the secret, and a default here would silently drift from compose again
* the next time the floor or the value changes.
*/
export const JWT_SECRET = requireEnv('OAUTH_JWT_SECRET');

function requireEnv(name) {
const value = process.env[name];
if (!value) {
throw new Error(
`${name} is not set. Run the suite through \`make test-e2e\`, which exports it from tests/docker-compose.yml.`,
);
Comment on lines +36 to +38
}
return value;
}

/** Marked `firstParty: true` in tests/provider/clients.yaml. */
export const CLIENT_ID = 'e2e-app';
Expand Down
Loading