Skip to content

[papi] OIDC service signs state with HS256, reusing signing PK - WEB-206 #17328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 24, 2023

Conversation

easyCZ
Copy link
Member

@easyCZ easyCZ commented Apr 22, 2023

Description

  • Uses the same sign/verify mechanism we use for Session JWTs in OIDC
  • This results in the following:
    • We still sign the JWT with HS256, but we use the RSA Private key as the key
    • We no longer require a an extra key for OIDC

Related Issue(s)

How to test

  1. Unit tests
  2. Preview, if needed

Documentation

Preview status

Gitpod was successfully deployed to your preview environment.

Build Options:

  • /werft with-werft
    Run the build with werft instead of GHA
  • leeway-no-cache
  • /werft no-test
    Run Leeway with --dont-test
Publish Options
  • /werft publish-to-npm
  • /werft publish-to-jb-marketplace
Installer Options
  • analytics=segment
  • with-dedicated-emulation
  • with-ws-manager-mk2
  • workspace-feature-flags
    Add desired feature flags to the end of the line above, space separated

Preview Environment Options:

  • /werft with-local-preview
    If enabled this will build install/preview
  • /werft with-preview
  • /werft with-large-vm
  • /werft with-gce-vm
    If enabled this will create the environment on GCE infra
  • with-integration-tests=all
    Valid options are all, workspace, webapp, ide, jetbrains, vscode, ssh

/hold

@easyCZ easyCZ force-pushed the mp/papi-oidc-jwt-rsa256 branch from dc793e6 to 3b75276 Compare April 22, 2023 21:20
@easyCZ easyCZ changed the title [papi] OIDC service signs state with RSA256 [papi] OIDC service signs state with RSA256 - WEB-206 Apr 22, 2023
Base automatically changed from mp/papi-jwt-generalize-sign-verify to main April 24, 2023 07:14
@roboquat roboquat added size/XXL and removed size/L labels Apr 24, 2023
@easyCZ easyCZ force-pushed the mp/papi-oidc-jwt-rsa256 branch from 793a04c to 74f4fbe Compare April 24, 2023 07:16
@easyCZ easyCZ marked this pull request as ready for review April 24, 2023 07:16
@easyCZ easyCZ requested a review from a team April 24, 2023 07:16
@github-actions github-actions bot added the team: webapp Issue belongs to the WebApp team label Apr 24, 2023
@AlexTugarev
Copy link
Member

@easyCZ, the reason to use HS256 for state param is that it's used as a URL param and RSA256 signed JWTs are significant longer.

Quick stats from JWT.io: HS256 -> ~150 bytes, RSA256 -> 500 bytes

The state param is a passthrough we're sending and expect to get back. The rest of the URL is already a lengthy beast, and it may contain various IdP-specific params. We need to be sure this is not breaking the authorize requests to IdPs, or redirects back to Gitpod.

@easyCZ
Copy link
Member Author

easyCZ commented Apr 24, 2023

We need to be sure this is not breaking the authorize requests to IdPs, or redirects back to Gitpod.

How do we ensure this? Is there anything about this in the spec? And if not, can we use the RSA symmetric key?

@easyCZ
Copy link
Member Author

easyCZ commented Apr 24, 2023

From a quick search, there appears to be nothing in the spec for this. It seems to be largely limited by browser URL max size, which tends to not have a limit, or be on the order of ~5k chars which we'd fit into.

Yes, there's also the question whether the auth provider imposes max URL limit but I'd expect most frameworks to keep this reasonable.

Given the OIDC tokens are short-lived, and basically only sign-in use, we could go with this change and should we encounter problems with a provider, we can change just the OIDC back to HS256. The benefit is that we reduce the need for another secret for now, making our config (and lives) simpler.

@AlexTugarev
Copy link
Member

How do we ensure this?

It's not spec'd.

After searching for that topic, it seems there are limitations per provider. You'll find only vague statements on the limitations like this. Numbers existing limits vary depending on search results, 1k, 512, 256, 100, all from different OAuth2 services. Only option to make sure we are not breaking things upfront would be to test some of the major providers (Google, Auth0, Azure AD, maybe more) and see if they all go above 512 bytes.

If there is another to reduce length, it would be preferable.

@AlexTugarev
Copy link
Member

and should we encounter problems with a provider

We should make sure it works with the known providers, before changing this. At least the tree IdPs mentioned above should work.

BTW, testing this would be not too hard. Configure the services, prepare the authorize URL containing a lengthy random state param, and navigate the browser to this location. If it doesn't reject, it should be fine.

@AlexTugarev
Copy link
Member

And if not, can we use the RSA symmetric key?

In order to get rid of a second secret? Fine with that.

The benefit is that we reduce the need for another secret for now, making our config (and lives) simpler.

See, that sound easier. But rolling back if it breaks with a customer's in-house IdP service, is something we really want to avoid, especially if we are already aware of it now.

@easyCZ
Copy link
Member Author

easyCZ commented Apr 24, 2023

If there is another to reduce length, it would be preferable.

If we want it signed (and decentralized), then a symmetric cipher is the only way.

We can use the RSA private key as the symmetric key, which produces the following:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6InRlc3QtaWQiLCJyZXR1cm5UbyI6InRlc3QtdXJsIiwiZXhwIjoxNjgyMzIyOTM4LCJpYXQiOjE2ODIzMjI2Mzh9.498rY758bRdCCnYEpIGhm3-RBZpv_csHvfSUCPr73-I

Which is HS256, equivalent to the previous size.

@easyCZ
Copy link
Member Author

easyCZ commented Apr 24, 2023

I've refactored the code above to sign with HS256, but use the RSA PK as the key.

I'll push some more tests for the HS256 shortly, but see if this now looks okay.

@roboquat roboquat added size/XL and removed size/L labels Apr 24, 2023
@easyCZ easyCZ changed the title [papi] OIDC service signs state with RSA256 - WEB-206 [papi] OIDC service signs state with HS256, reusing signing PK - WEB-206 Apr 24, 2023
@AlexTugarev
Copy link
Member

If we want it signed (and decentralized), then a [a]symmetric cipher is the only way.

Understood.

@easyCZ
Copy link
Member Author

easyCZ commented Apr 24, 2023

Also updated PR description to reflect the change.

Copy link
Member

@AlexTugarev AlexTugarev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!
Tested with Google ✔️

@easyCZ
Copy link
Member Author

easyCZ commented Apr 24, 2023

Thanks @AlexTugarev for the insights and review!

@easyCZ
Copy link
Member Author

easyCZ commented Apr 24, 2023

/unhold

@roboquat roboquat merged commit d9ccc1d into main Apr 24, 2023
@roboquat roboquat deleted the mp/papi-oidc-jwt-rsa256 branch April 24, 2023 09:14
@roboquat roboquat added deployed: webapp Meta team change is running in production deployed Change is completely running in production labels May 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deployed: webapp Meta team change is running in production deployed Change is completely running in production size/XL team: webapp Issue belongs to the WebApp team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants