OAuth2 PKCE authentication with git-gateway-backend
Summary
With Netlify deprecating the Identity product, solutions need to be added to support additional authentication providers. This code adds support to the git-gateway backend for the OAuth2 PKCE authentication flow, without impacting any existing defaults.
Test plan
Test using the standard options with git-gateway and ensure that functionality is not affected.
Test with OAuth2 provider (I used Amazon Cognito). Example configuration that uses PKCE authentication (this is also documented in the decap-cms-backend-git-gateway README, for future use):
backend:
name: git-gateway
# Enables PKCE authentication with the git-gateway backend. After auth,
# sends the access_token for all requests to the git-gateway host.
auth_type: pkce
# The base OAuth2 URL. Here is an obfuscated AWS Cognito example.
base_url: https://your-cognito-instance.auth.us-east-1.amazoncognito.com
# If you need to customize the authorize or token endpoints for PKCE, do that here
#auth_endpoint: oauth2/authorize
#auth_token_endpoint: oauth2/token
# The OAuth2 client ID
app_id: your-oauth2-client-id
# The base URL of your custom git-gateway. Note that the last part of the path
# should be "bitbucket", "gitlab", or "github", so the implementation can automatically
# determine which backend API to use when making requests.
gateway_url: https://your.gitgateway.host/git-gateway/bitbucket/
# Optional: defaults to "master"
branch: main
Checklist
- [x] I have read the contribution guidelines.
I have a couple of discussion points about this PR. These are not necessarily directly related to your PR, but to general decap architecture and it's limitations. Also to the way the oauth vendors mangle up the standard.
So first this is that there's an almost exact copy of your PKCEAuthenticationPage.js already in the repo. It's also claimining to be generic but in it's not in practice.
Basicly we need to decide if we'll have one module to handle all the providers, or a module for each. A combination of the two aproaches will be a mess. I tried Azure B2C with your code and after some tweaking I came to the login page. However the completeAuth part seems to be totally different to what Cognito does.
Perhaps we should start with a list of providers that we want to support?
https://github.com/decaporg/decap-cms/issues/7420
So first this is that there's an almost exact copy of your
PKCEAuthenticationPage.jsalready in the repo. It's also claimining to be generic but in it's not in practice.
True, I saw the existing file and re-used it. There are some changes added to mangle the claims into a format acceptable by git-gateway, but some deduplication could be done with the code between those two classes, if you prefer. I just didn't want to add a dependency on an undocumented backend file.
Basicly we need to decide if we'll have one module to handle all the providers, or a module for each. A combination of the two aproaches will be a mess. I tried Azure B2C with your code and after some tweaking I came to the login page. However the
completeAuthpart seems to be totally different to what Cognito does.
In theory, the actual authentication mechanism (PKCE flow) should be the same, right? If so, perhaps we just need a way to normalize the claims from each provider, hopefully with overrideable autodetection. Personally, as a user of the Decap app, I'd expect PKCE to work regardless of provider, and wouldn't want to be limited to a smaller set of providers when any OAuth2 should work, as long as the necessary data is somewhere in the claims.
If you like, I can move the PKCE auth UI and associated claim-normalization into a separate module, and use that in both backends.
In theory, the actual authentication mechanism (PKCE flow) should be the same, right?
In theory, yes. It's just that the vendors didn't get the message. Here are my notes for Azure B2C (the idea is to take these notes and add options to PkceAuthenticator):
- the URL's are not build the same way as Cognito. Authenticate url looks like this:
/<policy>/oauth2/v2.0/authorize, completeAuth url looks like this:/<policy>/oauth2/v2.0/token - authenticate:
nonceis not in state, but as a separete parameter (perhaps we can assume that vendors will ignore extra params?) - authenticate: state includes:
meta: { interactionType: 'redirect' } - completeAuth: I think that nonce should be completely ignored
If you like, I can move the PKCE auth UI and associated claim-normalization into a separate module, and use that in both backends.
That would be great. The idea is not so much that you need to support all of them, just that there's enough flexibility in the implementation so that others can be added without too much work and too much duplication. So split what's really generic to common module. Don't be afraid to rip out the old stuff.
I updated the PR with some refactoring and some improvements:
- I moved the PKCE and Netlify auth pages to a new UI library, so identical auth pages do not need to be created across backends. These were moved from the git-gateway and aws-cognito-github-proxy backends.
- I added a new config section, named
auth, which can be used to configure more fine-tuned options to the authentication providers. The original values frombackend(ex: "base_url") are still recognized, for backwards-compatibility, but any explicit options provided inauthwill be preferred - I added options for converting claim data to the fields expected by git-gateway. The most important one is
email-- if your provider isn't returning an explicitemailclaim in the access or ID token, but it is available in a different claim, addauth.email_claimin your config to the name of the claim. - I added basic OpenID Connect endpoint autodiscovery to the pkce-oauth library, turned off by default. Add
auth.use_oidc: truein your config, and assuming yourauth.base_url(orbackend.base_url) is a valid OIDC issuer with a .well-known/openid-configuration URL, the code will figure out the auth and token endpoints for you
I didn't touch any of the nonce/state logic, since I don't have an Azure B2C provider. If I have time this week, I can try firing up a basic test Azure App Registration and see if it works, but I don't know if that is significantly different from B2C.
One comment about Azure and OAuth that I ran into a few weeks ago for something completely unrelated: by default, Azure App Registrations use OAuth v1, which has very different claims from OAuth v2. I wouldn't be surprised if B2C had the same default. To switch over to v2 for App Registrations, you need to edit the manifest manually, find the requestedAccessTokenVersion setting in the manifest, and set it to the number 2 (by default, it's null, and MS uses v1 as the default). Save it and wait like 15 minutes for it to take effect.
Do you know if your B2C testing was on v1 or v2? If you aren't sure, trying decoding the JWT, it should have a version or similar claim with 1 or 2.
Sorry, I'm busy, will take a look during the weekend or sooner.
Hello guys, can you please give more priority to this PR. Without it we have to rely on the deprecated Netlify Identity if we want to use Decap CMS with Netlify. @samo4 you mentioned you'd review it soon, but that was two months ago, so I'm guessing it might've slipped through the cracks. Could you please take a look when you get a chance? Would be great to get this moving forward again. Thanks!
I am sorry if I read over something. But I am not really sure about the process here: Who is all able to review Pull request? Only PM Techhub Staff or are there others?
Thanks for the approval. I think I need a maintainer to also approve the workflows, so they can run before the code is merged.
we're testing it, will merge soon
There were merge conflicts with a recent commit to main, so I resolved the conflicts and repushed my branch. Please re-review.
Hi, I wonder if there is a way that I could help to bring this forward to be merged?
This has been sitting open for too long again, so new merge conflicts crept in. I merged the latest from main into my fork/branch, but I haven't had time to manually test it again. But unit tests all succeed locally.
Now that the changes are approved and all checks have passed, what is the next step to get it merged?
@samo4 I had to merge from main again, can you re-approve this request?
Thanks @samo4 for approving the changes. Do you mind approving the workflows, so the automated builds can run?
@pspizzo this is now released in v3.8.3. Please test. Would you be willing to contribute to the docs too?
Thanks for your first contribution!
Just wanted to say great work with this one, thanks to this, SSO flows have now become possible with DecapBridge 🎉
Just wanted to say great work with this one, thanks to this, SSO flows have now become possible with DecapBridge 🎉
I'm glad you found it useful!