Skip to content

feat: add OAuth2 applications #11197

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 30 commits into from
Dec 21, 2023
Merged

feat: add OAuth2 applications #11197

merged 30 commits into from
Dec 21, 2023

Conversation

code-asher
Copy link
Member

@code-asher code-asher commented Dec 13, 2023

This is part 1 of #11084.

It adds the oauth application configuration part. The actual token exchange is not implemented yet, probably will use golang/oauth2. As a consequence I have not linked the new page in the sidebar, but it can be accessed by going to /deployment/oauth2-apps. The endpoints are restricted to dev.

This is big enough that I felt like it made sense to get a review on it now even though the token exchange is missing. It is just a bunch of CRUD, so mostly tedious work like queries and a frontend for those queries.

Two areas in particular I am not sure about:

  1. Did I do the RBAC part right?
  2. I am not sure I am using features/entitlements correctly. I am not actually preventing adding/editing applications but maybe I should? I was going to prevent the token exchange though. I am doing this now.

Relying on backend validation right now but maybe should do it on the frontend since the backend errors are a bit hard to read. Also could add that emoji picker to the icon field.

@code-asher code-asher force-pushed the asher/oauth-provider branch 9 times, most recently from 0706a37 to 2bdd363 Compare December 14, 2023 02:17
These are applications that will be able to use OAuth2 to get an API key
from Coder.
These let you add, update, and remove OAuth2 applications.
@code-asher code-asher force-pushed the asher/oauth-provider branch 2 times, most recently from d865c7f to 1ff12c8 Compare December 14, 2023 02:55
@code-asher code-asher marked this pull request as ready for review December 14, 2023 03:22
@code-asher code-asher requested review from Emyrk, a team and Parkreiner and removed request for a team December 14, 2023 03:22
@code-asher
Copy link
Member Author

Not sure about the race tests...will look into it later.

@Emyrk
Copy link
Member

Emyrk commented Dec 14, 2023

Github allows any user to make an Oauth2 app. Do we expect this to be the case for Coder?

Do we want Coder to not allow personal Oauth2 apps, and only allow global oauth apps?

Should apps be scoped to an org?

Comment on lines 2192 to 2197
func (q *querier) InsertOAuth2AppSecret(ctx context.Context, arg database.InsertOAuth2AppSecretParams) (database.OAuth2AppSecret, error) {
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceOAuth2AppSecret); err != nil {
return database.OAuth2AppSecret{}, err
}
return q.db.InsertOAuth2AppSecret(ctx, arg)
}
Copy link
Member

Choose a reason for hiding this comment

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

We should incorporate this in the encrypted db layer.

Copy link
Member

@Parkreiner Parkreiner left a comment

Choose a reason for hiding this comment

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

TypeScript looks good! There's a lot of files, though, so I'll do a second review pass later today to check the stories and pull the repo down to kick the tires a bit

</TableHead>
<TableBody>
{isLoadingSecrets && <TableLoader />}
{!isLoadingSecrets && (!secrets || secrets?.length === 0) && (
Copy link
Member

Choose a reason for hiding this comment

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

Could the second case be simplified down to !secrets?.length? I think that would catch both the undefined and 0 cases

Copy link
Member Author

Choose a reason for hiding this comment

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

It definitely could, for some reason I like to always compare length to a number rather than make use of falsey checks.

Copy link
Member

Choose a reason for hiding this comment

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

Honestly, that's generally what I default to, too – I guess my main concern here was making sure the condition isn't too long, since there's not an easy way to name it without moving the value all the way above the return statement

event.preventDefault();
const formData = new FormData(event.target as HTMLFormElement);
onSubmit({
name: formData.get("name") as string,
Copy link
Member

Choose a reason for hiding this comment

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

I get that the type assertions are necessary to exclude the File type, but do you think we should still have null checks?

Copy link
Member Author

Choose a reason for hiding this comment

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

Honestly I should probably use Formik or whatever, and add the validations too. I just...dislike Formik haha

I figure null will be caught by validation, either on the frontend (if I add it) or the backend. But from a code complete perspective it does seem like adding null here is the right move.

Copy link
Member Author

Choose a reason for hiding this comment

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

Since the page is blocked from being used outside of development for now I am going to punt frontend validation for another PR, if that seems chill.

@code-asher
Copy link
Member Author

code-asher commented Dec 14, 2023

Github allows any user to make an Oauth2 app. Do we expect this to be the case for Coder?
Do we want Coder to not allow personal Oauth2 apps, and only allow global oauth apps?
Should apps be scoped to an org?

I asked and looks like we should be scoping them to an org for the future, and right now owner-only is fine (so I think we should leave the possibility this will change).

Also remove a ? since that condition would short-circuit if `secrets`
was not set.  We could just do a falsey check, but I like to compare
length to a number.
@code-asher code-asher requested a review from Emyrk December 15, 2023 22:14
@@ -315,6 +333,15 @@ export const AppRouter: FC = () => {
path="external-auth"
element={<ExternalAuthSettingsPage />}
/>

<Route path="oauth2-provider">
<Route path="apps">
Copy link
Member

Choose a reason for hiding this comment

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

One thing I noticed during testing: I think there should be a redirect or something when the user tries to go go the deployment/oauth2-provider/ URL path

Right now, it doesn't take you to a completely empty screen, but you only see the navbar and the Deployment options

Copy link
Member Author

Choose a reason for hiding this comment

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

I am hesitant to do that because one day we might have something else on that page (like for example a toggle for whether to enable the oauth2 provider) and I would not want folks getting confused learning they can go to just /oauth2-provider to get to the apps, if that makes sense.

Copy link
Member Author

Choose a reason for hiding this comment

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

That said, seems like it should at least show a proper 404. Mine gives this error:

"user" must be an existing uuid or username.
queried user="deployment"

So I guess it is falling through to some other page.

Copy link
Member Author

Choose a reason for hiding this comment

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

Whoops I was on dev.coder.com, yeah you are right it shows a blank page with the deployment sidebar. That is pretty weird. Is there even a way for me to show a 404 here? Maybe a redirect is the only fix...

Copy link
Member Author

Choose a reason for hiding this comment

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

I added a route with NotFoundPage.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah but that is weird too because the sidebar is still there. At least the page says "not found" I guess.

@Emyrk
Copy link
Member

Emyrk commented Dec 18, 2023

I'll get a green checkmark on this today.

We should get this in soon to prevent merge conflicts on the moving base.

Copy link
Member

@Parkreiner Parkreiner left a comment

Choose a reason for hiding this comment

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

The UI worked really well when I was testing things out. Just had a few more comments

This will work better on smaller screens.

Also I had an extra useless Stack around the button.
- Make it a header
- Add a copy icon
One day we might have other settings on this page but for now there is
nothing to show.
This should not normally be possible because the modal would prevent
hitting the delete button but you never know.
Copy link
Member

@Emyrk Emyrk left a comment

Choose a reason for hiding this comment

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

Lets get this in.

@code-asher code-asher enabled auto-merge (squash) December 21, 2023 21:20
@code-asher code-asher merged commit 5cfa34b into main Dec 21, 2023
@code-asher code-asher deleted the asher/oauth-provider branch December 21, 2023 21:38
@github-actions github-actions bot locked and limited conversation to collaborators Dec 21, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants