Konubinix' opinionated web of thoughts

Making Sense of Github OIDC Flow

Fleeting

making sense of github OIDC flow, used by pypi to harden security

https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect

Reminder of OIDC : a relying party (which is an oauth 2.0 client) needs a resource owner to authenticate against an OpenID Connect Provider (which is an authorization server) and consent the relying party to access to some data from a resource server. The relying party is provided with an access token, proof of this consented authorization, that will be passed along requests to the resource server. The resource owner knows how to check how genuine the access token is and what resources are bound to it. The OIDC provider is also a resource server where the resource is the user identity1. It provides part of this information with an Identity Token along with the access token.

Let’s remember that the identity token IS a JWT, and the access token is only a bearer token, while in practice, most implementation issue access tokens as JWT. Because self-encoded access token is quite useful in plenty of use cases. When doing so, the audience claim SHOULD refer to the resource server2.

Also, let’s remember that the identity token is a proof of two things

  1. that some end user, mentioned in the token authenticated against the OIDC provider,
  2. the proof was meant for the relying party.

Possessing this token only proves that. It DOES NOT prove that the entity possessing this token is granted anything on any resource server anywhere. It is public knowledge and should not be used as proof of authorization3.

Now, let’s see the flow in github:

  1. github generates a JWT,
  2. the workflow provides this token to the cloud provider,
  3. the cloud provider returns an access token,
  4. the workflow connects to the cloud provider with the access token to do its job.

Using OIDC concepts, this is how I interpret this.

  • there are two overlapping flows
  • first flow:
    • github is the authorization server,
    • the workflow is the client,
    • the cloud provider is the resource server,
    • the resource is an access token,
    • github, on behalf of the workflow “asks” itself for an access token to get access to the cloud provider access token. It “grants” itself the permission.
    • the workflow uses that token to get access to the cloud provider access token,
  • second flow:
    • the cloud provider is the authorization server AND the resource server
    • the workflow is the client
    • the resource is the cloud service
    • the previous flow issues the access token
    • in this case the audience claim should be the cloud provider as well,

The cloud provider is the resource server in both cases. Therefore, it SHOULD be the audience in both.

It feels a bit like the flows similar to google sign-in4.

To me, it looks like name dropping. This flow makes total sense to me, but it seems to me intellectually dishonest to call them OIDC flow, only because it rely on some aspect of OIDC. It made it harder for me to understand what they were doing.

Note: It may exist a definition of this flow at OIDC, but I don’t think so. The burden of proof lies on github for referring to it. The github documentation only refers to https://openid.net/specs/openid-connect-core-1_0.html , that I used as base for my analysis.