source-cooperative / source-cooperative/data.source.coop

STS roles should support multiple trusted OIDC providers, each with their own audience and subject conditions

Open
#152 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
24
Forks
6
Avg merge
1h 32m
Merged PRs (30d)
1

Description

Context

PR #132 adds the /.sts token-exchange endpoint. Role trust policies come from multistore::types::RoleConfig, which currently models trust as:

pub trusted_oidc_issuers: Vec<String>,      // N issuers
pub required_audience: Option<String>,      // but ONE audience, shared across all of them
pub subject_conditions: Vec<String>,        // and ONE set of sub conditions, shared too

A role can trust multiple OIDC issuers, but the aud and sub constraints apply uniformly across all of them — and required_audience only holds a single value.

Problem

We will definitely want multiple OIDC providers to be able to assume the same role, each with its own audience and subject conditions. In AWS IAM this is the norm: a role's trust policy can contain multiple statements, one per federated provider, each with its own aud/sub conditions. For example, a single product role trusted by both:

  • source.coop web flow (Ory): aud = the web app's OAuth client_id, sub = the Ory user id
  • GitHub Actions OIDC (token.actions.githubusercontent.com): aud = a custom audience, sub matching repo:<org>/<repo>:ref:refs/heads/main

With the current shape this is unrepresentable: an audience valid for one issuer is wrong for the other, and subject patterns for Ory user ids vs GitHub repo: subjects can't be scoped to their issuer.

Proposal

Restructure role trust as a list of per-provider entries, e.g.:

pub struct TrustedProvider {
    pub issuer: String,
    pub audiences: Vec<String>,          // also fixes the single-client_id limitation
    pub subject_conditions: Vec<String>, // glob patterns, scoped to this issuer
}

pub struct RoleConfig {
    // ...
    pub trusted_providers: Vec<TrustedProvider>,
}

Token exchange validates the subject token against the entry matching its iss, then enforces that entry's aud/sub conditions.

Dependencies

  • The type and its enforcement live upstream in the multistore / multistore-sts crates (RoleConfig, JWKS validation), so this needs a crate release first, then adoption here (src/sts.rs builds the _default role; AUTH_AUDIENCE would become that role's first trusted-provider audience).
  • Related: the role registry is currently a single hardcoded _default role (see TODO in src/sts.rs); per-role trust config becomes most useful once roles are served from the Source Cooperative API.

Spun out of review feedback on #132 (finding 1: audience restriction).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the upstream multistore and multistore-sts releases implementing per-provider RoleConfig trust, then inspect src/sts.rs where the _default role is built. Trace how AUTH_AUDIENCE feeds that role and how token exchange performs JWKS and issuer validation. Done means this project adopts the released types so each trusted OIDC provider can have its own audiences and subject conditions.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
authentication, authorization
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.