Skip to content
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

server: refactor: introduce AuthUser interface #838

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

paul-marechal
Copy link
Member

@paul-marechal paul-marechal commented Nov 25, 2023

Replace the references to OAuth2User by AuthUser. This allows downstream extenders to more easily contribute alternative OAuth2 providers: If the expected data is stored in different attributes it will be possible to bridge it by implementing the proper AuthUser.

New configuration example:

ovsx:
  oauth2:
    provider: gitlab
    attribute-names:
      gitlab:
        avatar-url: avatar_url
        email: email
        full-name: name
        login-name: username
        provider-url: '' # idk what this is for

spring:
  security:
    oauth2:
      client:
        registration:
          gitlab:
            client-id: [client-id]
            client-secret: [client-secret]
            authorization-grant-type: authorization_code
            redirect-uri: http://[openvsx-host-name]/login/oauth2/code/gitlab
            scope: read_user
            clientName: OpenVSX
        provider:
          gitlab:
            authorization-uri: http://[gitlab-host-name]/oauth/authorize
            token-uri: http://[gitlab-host-name]/oauth/token
            user-info-uri: http://[gitlab-host-name]/api/v4/user
            jwk-set-uri: http://[gitlab-host-name]/oauth/discovery/keys
            user-name-attribute: id

@paul-marechal
Copy link
Member Author

Note that there seems to be an issue with formatting in this project...

I'm using VS Code along its Java extension to develop and it often feels like reorganizing or cleaning up imports.

I'd be in favor of keeping the cleanup as part of these changes.

It would be good to look into making auto-formatting part of the build step, maybe as a gradle plugin of some kind?

@paul-marechal
Copy link
Member Author

Rebased my branch.

@amvanbaren
Copy link
Contributor

@HeikoBoettger Can you share which additional identity provider you were able to implement using this PR?

@HeikoBoettger-KarlStorz
Copy link

@HeikoBoettger Can you share which additional identity provider you were able to implement using this PR?

@amvanbaren Somehow I lost my comment. The PR didn't help completely, what is missing is basically a mapping of the login-attribute. One could add a GitLab specific mapping to the code, what I did based on this merge request adding a completely new generic provider type which uses additional setting from the application.yaml file defining for the web-interface what provider to use for the login-link and how to map the login (supporting mapping any of the attributes in the AuthUserFactory).

If the code could be changed to use spring.security.oauth2.client.provider.[providerId].user-name-attribute / providerDetails.userInfoEndpoint.userNameAttributeName as described in https://docs.spring.io/spring-security/reference/servlet/oauth2/login/core.html#oauth2login-sample-application-config. Instead of login I could abuse the GitHub provider entry.

To fully support other providers the UI would require a change to select the login method and the AuthToken inside the UserData class need to be contain a map from provider to token:

Or the code gets simplified to just store an AuthToken for one provider at a time. I don't know why there are two fields in the UserData when there is only one provider-String.

@HeikoBoettger-KarlStorz
Copy link

@paul-marechal Is it possible to rebase this branch on to the latest master?

@amvanbaren
Copy link
Contributor

Or the code gets simplified to just store an AuthToken for one provider at a time. I don't know why there are two fields in the UserData when there is only one provider-String.

The githubToken is to login. The eclipseToken is to check the publisher agreement.
We could rename githubToken to loginToken.

Replace the references to `OAuth2User` by `AuthUser`. This allows
downstream extenders to more easily contribute alternative OAuth2
providers: If the expected data is stored in different attributes it
will be possible to bridge it by implementing the proper `AuthUser`.
Introduce a configuration to define attribute names to use when mapping
attributes from an auth provider.
Allow configuring the auth for arbitrary providers (other than github).
@paul-marechal
Copy link
Member Author

paul-marechal commented Dec 9, 2024

Ok so I initially didn't want to bother implementing the configuration of attributes because it adds a decent amount of complexity... I changed my mind figuring it might make someone else's life easier.

The configuration may look like this:

ovsx:
  auth:
    attribute-names:
      gitlab:
        avatar-url: awdawd
        email: awdawd
        full-name: awdawd
        login-name: awdawd
        provider-url: awdawd

We don't need to define mappings for github as it's handled by default.

@amvanbaren
Copy link
Contributor

@paul-marechal Thanks for providing the configuration. I'll try to configure Google OAuth using this PR.

@paul-marechal
Copy link
Member Author

paul-marechal commented Dec 10, 2024

I want to apologize for forgetting to transpose code to handle OidcUserRequest we had to use for our fork... Without it we couldn't access certain attributes.

Second, there's still a need to manually edit the webui code to change the OAuth2 authorization endpoint used from github to whatever you want to reach. I'm not sure if we can somehow get rid of it or make it configurable yet. I will try so it's also less of a hassle...

This PR is slowly growing bigger than what we required on our fork so I hope this will help.

@amvanbaren
Copy link
Contributor

there's still a need to manually edit the webui code

Yes, the login url is hardcoded in the webui:

getLoginUrl(): string {
return createAbsoluteURL([this.serverUrl, 'oauth2', 'authorization', 'github']);
}

The UserAPI has a login endpoint, but it causes CORS errors:

@GetMapping(
path = "/login"
)
public ModelAndView login(ModelMap model) {
return new ModelAndView("redirect:/oauth2/authorization/github", model);
}

@paul-marechal
Copy link
Member Author

paul-marechal commented Dec 10, 2024

I implemented the dynamic redirection based on a server configuration, I didn't encounter a CORS error?

ovsx:
  auth:
    provider: azure

@GetMapping(
path = "/login"
)
public ModelAndView login(ModelMap model) {
return new ModelAndView("redirect:/oauth2/authorization/" + config.getAuth().getProvider(), model);
}

@paul-marechal
Copy link
Member Author

paul-marechal commented Dec 10, 2024

Using the latest commit I can now assert that no more code changes are required to configure a custom provider (following our use cases) as I was able to completely configure authentication to Azure using only the server spring config. I initially forgot to include a few modifications...

@HeikoBoettger-KarlStorz

@paul-marechal Just to give an early feedback. I compared your changes with the modifications I did on my local branch I was thinking of contributing and it's more or less the same.

One thing I wonder is, do you use the githubToken to store the token in the database (UserData)? The TokenService also contains a switch block with the providers.

@paul-marechal
Copy link
Member Author

I didn't find it required to store anything in githubToken.

@HeikoBoettger-KarlStorz

Note sure whether I did something wrong but I get an error message: "Missing configuration: ovsx.auth.attribute-names.gitlab".
Shouldn't there be an default value.

@HeikoBoettger-KarlStorz
Copy link

HeikoBoettger-KarlStorz commented Dec 12, 2024

@paul-marechal First of all thank you for this awesome work.

ovsx:
  auth:
    attribute-names:
      gitlab:
        avatar-url: awdawd
        email: awdawd
        full-name: awdawd
        login-name: awdawd
        provider-url: awdawd

I used the following values for gitlab:

ovsx:
  auth:
    attribute-names:
      gitlab:
        avatar-url: avatar_url
        email: email
        full-name: name
        login-name: username

I don't know what to set for the provider-url on gitlab but with this mapping I can confirm that I am able to login.

For spring.security.oauth2 I used the following settings:

spring.security.oauth2.client.registration.gitlab.client-id=[client-id]" 
spring.security.oauth2.client.registration.gitlab.client-secret=[client-secret]
spring.security.oauth2.client.registration.gitlab.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.gitlab.redirect-uri=http://[openvsx-host-name]/login/oauth2/code/gitlab
spring.security.oauth2.client.registration.gitlab.scope=read_user
spring.security.oauth2.client.registration.gitlab.clientName=OpenVSX
spring.security.oauth2.client.provider.gitlab.authorization-uri=http://[gitlab-host-name]/oauth/authorize
spring.security.oauth2.client.provider.gitlab.token-uri=http://[gitlab-host-name]/oauth/token
spring.security.oauth2.client.provider.gitlab.user-info-uri=http://[gitlab-host-name]/api/v4/user
spring.security.oauth2.client.provider.gitlab.jwk-set-uri=http://[gitlab-host-name]/oauth/discovery/keys
spring.security.oauth2.client.provider.gitlab.user-name-attribute=id

@HeikoBoettger-KarlStorz

For completeness this is the configuration inside gitlab:
image

@paul-marechal
Copy link
Member Author

I noticed that there's another PR opened which allows to auth users without oauth2, so I renamed the configuration I introduced from ovsx.auth to ovsx.oauth2 so it better match its intended purpose.

I also updated the main PR description with a configuration example I took from @HeikoBoettger-KarlStorz :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

4 participants