🚀 Feature: Workload identity federation #554

Open
opened 2026-02-04 20:26:47 +03:00 by OVERLORD · 9 comments
Owner

Originally created by @yyuemii on GitHub (Nov 29, 2025).

Feature description

Workload identity federation would allow for automation to authenticate with Pocket through an OIDC identity from another provider. An admin could create an OIDC Client and define a federated issuer, acceptable claims/subjects, and an audience (example of Azure Entra ID setup with AWS Cognito):
Image

This is somewhat related to #902 where this seemingly used to be possible before federation was brought more in line with RFC 7523 (using sub as client_id). While you could workaround this by setting a custom client ID in some cases, several providers include invalid characters in their sub such as GitHub:

{
  "sub": "repo:octo-org/octo-repo:environment:prod"
  ...
}

I'd be happy to contribute to implementing this since it would benefit my personal use case significantly. Apologies if this is out of scope!

Pitch

Workload identity federation would simplify the process of accessing services from automation (ci/cd, cloud machines) while at the same time improving security by reducing the need for storing secrets. For example:

  • A GitHub Workflow could request a GitHub OIDC identity signed by GitHub's identity provider. It would then call Pocket with this identity, which would validate that the iss, sub (or claims), and aud matches, before finally exchanging the identity a client token with access to internal services, kubernetes, etc.
  • Tailscale allows automation to authenticate and connect to Tailent from an OIDC identity: https://tailscale.com/kb/1581/workload-identity-federation

Providers like AWS, Azure, and Google Cloud have also implemented similar solutions for exchanging OIDC identities for access to their resources:

Originally created by @yyuemii on GitHub (Nov 29, 2025). ### Feature description Workload identity federation would allow for automation to authenticate with Pocket through an OIDC identity from another provider. An admin could create an OIDC Client and define a federated issuer, acceptable claims/subjects, and an audience (example of Azure Entra ID setup with AWS Cognito): <img width="894" height="550" alt="Image" src="https://github.com/user-attachments/assets/320766a9-f5b8-487c-a677-aff376701986" /> This is somewhat related to #902 where this seemingly used to be possible before federation was brought more in line with RFC 7523 (using `sub` as `client_id`). While you could workaround this by setting a custom client ID in some cases, several providers include invalid characters in their `sub` such as [GitHub](https://docs.github.com/en/actions/concepts/security/openid-connect#understanding-the-oidc-token): ```json { "sub": "repo:octo-org/octo-repo:environment:prod" ... } ``` I'd be happy to contribute to implementing this since it would benefit my personal use case significantly. Apologies if this is out of scope! ### Pitch Workload identity federation would simplify the process of accessing services from automation (ci/cd, cloud machines) while at the same time improving security by reducing the need for storing secrets. For example: - A GitHub Workflow could request a [GitHub OIDC identity](https://docs.github.com/en/actions/concepts/security/openid-connect#understanding-the-oidc-token) signed by GitHub's identity provider. It would then call Pocket with this identity, which would validate that the `iss`, `sub` (or claims), and `aud` matches, before finally exchanging the identity a client token with access to internal services, kubernetes, etc. - Tailscale allows automation to authenticate and connect to Tailent from an OIDC identity: https://tailscale.com/kb/1581/workload-identity-federation Providers like AWS, Azure, and Google Cloud have also implemented similar solutions for exchanging OIDC identities for access to their resources: - AWS: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html - Azure: https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust - Google Cloud: https://docs.cloud.google.com/iam/docs/workload-identity-federation-with-other-providers
Author
Owner

@vsarunas commented on GitHub (Dec 3, 2025):

Yes also just tried to authenticate a CLI tool using a Federated GitHub OIDC Token that can be retrieved using:

      - name: Get and decode OIDC token
        run: |
          TOKEN=$(curl -sS -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
            "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://PocketID.domain.com" | jq -r '.value')
          echo "token:"
          echo "$TOKEN" | base64

Decode token and try to authenticate locally:

export TOKEN=$(cat gh-token | base64 -d)

curl -v -X POST https://PocketID.domain.com/api/oidc/token \
  -d "grant_type=client_credentials" \
  -d "client_id=$CLIENT_ID" \
  -d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
  -d "client_assertion=$TOKEN"

Results in logs:

record not found app=pocket-id version=1.15.0 error="record not found" query="SELECT * FROM `oidc_clients` WHERE id = \"repo:octo-org/octo-repo:ref:refs/heads/oidc\" ORDER BY `oidc_clients`.`id` LIMIT 1" duration=145.473µs rows=0 file=github.com/pocket-id/pocket-id/backend/internal/service/oidc_service.go:1667
@vsarunas commented on GitHub (Dec 3, 2025): Yes also just tried to authenticate a CLI tool using a Federated GitHub OIDC Token that can be retrieved using: ```yaml - name: Get and decode OIDC token run: | TOKEN=$(curl -sS -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \ "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://PocketID.domain.com" | jq -r '.value') echo "token:" echo "$TOKEN" | base64 ``` Decode token and try to authenticate locally: ``` export TOKEN=$(cat gh-token | base64 -d) curl -v -X POST https://PocketID.domain.com/api/oidc/token \ -d "grant_type=client_credentials" \ -d "client_id=$CLIENT_ID" \ -d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \ -d "client_assertion=$TOKEN" ``` Results in logs: ``` record not found app=pocket-id version=1.15.0 error="record not found" query="SELECT * FROM `oidc_clients` WHERE id = \"repo:octo-org/octo-repo:ref:refs/heads/oidc\" ORDER BY `oidc_clients`.`id` LIMIT 1" duration=145.473µs rows=0 file=github.com/pocket-id/pocket-id/backend/internal/service/oidc_service.go:1667 ```
Author
Owner

@michaelbeaumont commented on GitHub (Dec 18, 2025):

How is this different than the existing federated identity feature? See https://pocket-id.org/docs/guides/oidc-client-authentication#using-federated-client-credentials

#902 is about violation of the RFC along with a bug that has gone unsolved.

There is no new feature here, it's about solving existing bugs

@michaelbeaumont commented on GitHub (Dec 18, 2025): How is this different than the existing federated identity feature? See https://pocket-id.org/docs/guides/oidc-client-authentication#using-federated-client-credentials #902 is about violation of the RFC along with a bug that has gone unsolved. There is no new feature here, it's about solving existing bugs
Author
Owner

@yyuemii commented on GitHub (Dec 18, 2025):

How is this different than the existing federated identity feature? See https://pocket-id.org/docs/guides/oidc-client-authentication#using-federated-client-credentials

#902 is about violation of the RFC along with a bug that has gone unsolved.

There is no new feature here, it's about solving existing bugs

I mentioned this in the description of this request; it seemingly used to be possible with the existing federated identity feature before it was brought closer in line with the RFC, which was highlighted in that issue:

It looks previously we allowed client_id and the sub to be different but https://github.com/pocket-id/pocket-id/pull/704/files#diff-25f504aed465ee11d0481b80d78561cabe0dff6d344ab071732760841bac5db8R1392 broke this.

Workload identity federation is different than RFC 7523 as the sub value will likely always be different then the client_id since it's more for identifying a running workload. As an example a GitHub Actions ID token contains a sub with the organization, repo, and environment it's running for.

@yyuemii commented on GitHub (Dec 18, 2025): > How is this different than the existing federated identity feature? See https://pocket-id.org/docs/guides/oidc-client-authentication#using-federated-client-credentials > > [#902](https://github.com/pocket-id/pocket-id/issues/902) is about violation of the RFC along with a bug that has gone unsolved. > > There is no new feature here, it's about solving existing bugs I mentioned this in the description of this request; it seemingly used to be possible with the existing federated identity feature before it was brought closer in line with the RFC, which was highlighted in that issue: > It looks previously we allowed client_id and the sub to be different but https://github.com/pocket-id/pocket-id/pull/704/files#diff-25f504aed465ee11d0481b80d78561cabe0dff6d344ab071732760841bac5db8R1392 broke this. Workload identity federation is different than RFC 7523 as the `sub` value will likely always be different then the `client_id` since it's more for identifying a running workload. As an example a GitHub Actions ID token contains a `sub` with the organization, repo, and environment it's running for.
Author
Owner

@michaelbeaumont commented on GitHub (Dec 18, 2025):

That breakage was unintentional, it was not intentionally brought closer to the RFC, that's the discussion in #902. It's completely broken at the moment anyway, even for RFC 7523.

What you're asking for is basically what the original feature was actually intended to do/how it was originally implemented https://github.com/pocket-id/pocket-id/issues/361

@michaelbeaumont commented on GitHub (Dec 18, 2025): That breakage was unintentional, it was not intentionally brought closer to the RFC, that's the discussion in #902. It's completely broken at the moment anyway, even for RFC 7523. What you're asking for is basically what the original feature was actually intended to do/how it was originally implemented https://github.com/pocket-id/pocket-id/issues/361
Author
Owner

@michaelbeaumont commented on GitHub (Dec 18, 2025):

before finally exchanging the identity a client token with access to internal services, kubernetes, etc.

To clarify, how exactly do you want to interact with Pocket ID using this token?

@michaelbeaumont commented on GitHub (Dec 18, 2025): > before finally exchanging the identity a client token with access to internal services, kubernetes, etc. To clarify, how exactly do you want to interact with Pocket ID using this token?
Author
Owner

@yyuemii commented on GitHub (Dec 19, 2025):

before finally exchanging the identity a client token with access to internal services, kubernetes, etc.

To clarify, how exactly do you want to interact with Pocket ID using this token?

Pocket would validate the incoming workload identity token and return a client credentials access token, without the need for the source of the workload (ex: github actions workflow) to store a client/secret pair. I linked a few articles in the original description that explain the concept.

@yyuemii commented on GitHub (Dec 19, 2025): > > before finally exchanging the identity a client token with access to internal services, kubernetes, etc. > > To clarify, how exactly do you want to interact with Pocket ID using this token? Pocket would validate the incoming workload identity token and return a client credentials access token, without the need for the source of the workload (ex: github actions workflow) to store a client/secret pair. I linked a few articles in the original description that explain the concept.
Author
Owner

@michaelbeaumont commented on GitHub (Dec 19, 2025):

Yeah this is just a duplicate of the existing issues. There's no reason to not follow RFC7523 except that pocket ID doesn't allow you to authenticate an (issuer, sub), one of the suggestions from #902. The only reason one even imagines needing a separate client ID is to use as a pointer to a configuration in pocket ID.

@michaelbeaumont commented on GitHub (Dec 19, 2025): Yeah this is just a duplicate of the existing issues. There's no reason to not follow RFC7523 except that pocket ID doesn't allow you to authenticate an `(issuer, sub)`, one of the suggestions from #902. The only reason one even imagines needing a separate client ID is to use as a pointer to a configuration in pocket ID.
Author
Owner

@yyuemii commented on GitHub (Dec 19, 2025):

Yeah this is just a duplicate of the existing issues. There's no reason to not follow RFC7523 except that pocket ID doesn't allow you to authenticate an (issuer, sub), one of the suggestions from #902. The only reason one even imagines needing a separate client ID is to use as a pointer to a configuration in pocket ID.

I would disagree that this is a duplicate if Pocket were to follow the RFC, since for workload identity in most cases you would have a different sub defined by a cloud provider then the client_id, violating the RFC. This is a seperate flow that can be seen in Azure Entra, AWS Cognito, etc. and I haven't seen any other issues requesting it specifically.

@yyuemii commented on GitHub (Dec 19, 2025): > Yeah this is just a duplicate of the existing issues. There's no reason to not follow RFC7523 except that pocket ID doesn't allow you to authenticate an `(issuer, sub)`, one of the suggestions from [#902](https://github.com/pocket-id/pocket-id/issues/902). The only reason one even imagines needing a separate client ID is to use as a pointer to a configuration in pocket ID. I would disagree that this is a duplicate if Pocket were to follow the RFC, since for workload identity in most cases you would have a different `sub` defined by a cloud provider then the `client_id`, violating the RFC. This is a seperate flow that can be seen in Azure Entra, AWS Cognito, etc. and I haven't seen any other issues requesting it specifically.
Author
Owner

@michaelbeaumont commented on GitHub (Dec 19, 2025):

since for workload identity in most cases you would have a different sub defined by a cloud provider then the client_id, violating the RFC

But the client ID is defined by what you configure in Pocket ID. If you just let the (issuer, sub) combination authenticate, you don't need a client_id.

@michaelbeaumont commented on GitHub (Dec 19, 2025): > since for workload identity in most cases you would have a different sub defined by a cloud provider then the client_id, violating the RFC But the client ID is defined by what you configure in Pocket ID. If you just let the (issuer, sub) combination authenticate, you don't need a client_id.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/pocket-id#554