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

Support OIDC for the SSO #5008

Merged
merged 17 commits into from
Aug 28, 2024
Merged

Conversation

kumo-rn5s
Copy link
Contributor

@kumo-rn5s kumo-rn5s commented Jun 29, 2024

What this PR does / why we need it:

This PR introduces a new OIDC login method to enhance user authentication options by supporting the basic OIDC Authorization Code Flow. It also includes support for common OIDC providers like Keycloak, Okta, and Cognito.

Which issue(s) this PR fixes:

Fixes #4906

Does this PR introduce a user-facing change?:

  • How are users affected by this change: Users will have the option to log in using OIDC, providing a more secure and versatile authentication method.
  • Is this breaking change: No
  • How to migrate (if breaking change): No need

TODO:

  • Adding key commits for basic OIDC Authorization Code Flow.
  • Testing with major OIDC providers
    • Keycloak
    • Auth0
    • Cognito
  • Adding OIDC documentation.

@kumo-rn5s kumo-rn5s marked this pull request as draft June 29, 2024 11:11
@kumo-rn5s kumo-rn5s force-pushed the feature-oidc-support branch 2 times, most recently from 3655160 to 1862336 Compare June 29, 2024 11:19
@kumo-rn5s kumo-rn5s force-pushed the feature-oidc-support branch 2 times, most recently from 126d268 to 0c85d07 Compare July 6, 2024 07:39
@kumo-rn5s kumo-rn5s marked this pull request as ready for review July 6, 2024 07:40
@kumo-rn5s kumo-rn5s force-pushed the feature-oidc-support branch 2 times, most recently from bc6e64a to 44f2ee7 Compare July 6, 2024 10:54
@kumo-rn5s kumo-rn5s force-pushed the feature-oidc-support branch 4 times, most recently from 1fe9366 to 50640ad Compare July 11, 2024 09:38
@t-kikuc
Copy link
Member

t-kikuc commented Jul 18, 2024

Thank you for your great contribution!
I'll run your code locally, and then we'll review the code!

Copy link
Member

@t-kikuc t-kikuc left a comment

Choose a reason for hiding this comment

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

Thank you for your great contributions.

Your code worked well! Pleaes let me share some comments.

var avatarUrlClaimKeys = []string{"picture", "avatar_url"}
var roleClaimKeys = []string{"groups", "roles", "cognito:groups", "custom:roles", "custom:groups"}

// OAuthClient is a oauth client for OIDC.
Copy link
Member

Choose a reason for hiding this comment

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

[nits]

Suggested change
// OAuthClient is a oauth client for OIDC.
// OAuthClient is an oauth client for OIDC.

@@ -348,6 +355,34 @@ func (p *ProjectSSOConfig_GitHub) GenerateAuthCodeURL(project, callbackURL, stat
return authURL, nil
}

// GenerateAuthCodeURL generates an auth URL for the specified configuration.
func (p *ProjectSSOConfig_Oidc) GenerateAuthCodeURL(project, state string) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

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

How about adding tests in project_test.go like this?
(although (p *ProjectSSOConfig_GitHub) GenerateAuthCodeURL does not have tests...)

func TestGenerateAuthCodeURL(t *testing.T) {
	testcases := []struct {
		title       string
		project     string
		state       string
		issuer      string
		scopes      []string
		expectedURL string
	}{
		{
			title:       "scopes are configured",
			project:     "test-project",
			state:       "test-state",
			issuer:      "https://accounts.google.com", // TODO: Is this proper? or use mock??
			scopes:      []string{"openid", "profile", "email"},
			expectedURL: "https://accounts.google.com/o/oauth2/v2/auth?access_type=online&client_id=&prompt=consent&response_type=code&scope=openid+profile+email&state=test-state%3Atest-project",
		},
		{
			title:       "empty scopes",
			project:     "test-project",
			state:       "test-state",
			issuer:      "https://accounts.google.com",
			scopes:      []string{},
			expectedURL: "https://accounts.google.com/o/oauth2/v2/auth?access_type=online&client_id=&prompt=consent&response_type=code&scope=openid&state=test-state%3Atest-project",
		},
	}

	for _, tc := range testcases {
		t.Run(tc.title, func(t *testing.T) {
			p := &ProjectSSOConfig_Oidc{
				Issuer: tc.issuer,
				Scopes: tc.scopes,
			}
			url, err := p.GenerateAuthCodeURL(tc.project, tc.state)
			assert.NoError(t, err)
			assert.Equal(t, tc.expectedURL, url)
		})
	}
}

string user_info_endpoint = 7;
// The address of the proxy used while communicating with the OpenID Connect service.
string proxy_url = 8;
// scopes to request from the OpenID Connect service.
Copy link
Member

Choose a reason for hiding this comment

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

[nits]

Suggested change
// scopes to request from the OpenID Connect service.
// Scopes to request from the OpenID Connect service.

@@ -41,6 +41,9 @@ const useStyles = makeStyles((theme) => ({
githubLoginButton: {
background: "#24292E",
},
oidcLoginButton: {
background: "#4A90E2",
},
Copy link
Member

Choose a reason for hiding this comment

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

[nits] To make a space between GitHub and OIDC.

Suggested change
},
marginTop: theme.spacing(1),
},
image

sharedSSOConfigs:
- name: oidc
provider: OIDC
oidc:
Copy link
Member

Choose a reason for hiding this comment

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

We need to add the configuration reference of oidc in this file like this:

Note: Before that, please make your branch up-to-date.

## SharedSSOConfig
...
| oidc | [SSOConfigOIDC](#ssoconfigoidc) | OIDC sso configuration. | No |
## SSOConfigOIDC

| Field | Type | Description | Required |
|-|-|-|-|
| ClientId | string | The client id string of OpenID Connect oauth app. | Yes |
| ClientSecret | string | The client secret string of OpenID Connect oauth app. | Yes |
| Issuer | string | The address of OpenID Connect service. | Yes |
| RedirectUri | string | The address of the redirect URI. | Yes |
| AuthorizationEndpoint | string | The address of the authorization endpoint. | Yes |
| TokenEndpoint | string | The address of the token endpoint. | Yes |
| UserInfoEndpoint | string | The address of the user info endpoint. | Yes |
| ProxyUrl | string | The address of the proxy used while communicating with the OpenID Connect service. | Yes |
| Scopes | []string | Scopes to request from the OpenID Connect service. | No |

If the Required fields above are wrong, please correct them🙏


idTokenRAW, ok := c.Token.Extra("id_token").(string)
if !ok {
return nil, fmt.Errorf("no access_token in oauth2 token")
Copy link
Member

Choose a reason for hiding this comment

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

[nits]

Suggested change
return nil, fmt.Errorf("no access_token in oauth2 token")
return nil, fmt.Errorf("no id_token in oauth2 token")

default:
return nil, fmt.Errorf("not implemented")
}
}

func parseProjectAndState(r *http.Request) (string, string, error) {
Copy link
Member

Choose a reason for hiding this comment

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

Would you add unit tests of parseProjectAndState() in callback_test.go? (Sorry, the file is empty now...)

@t-kikuc
Copy link
Member

t-kikuc commented Aug 9, 2024

[TODO] I have 2 nits of UI we'll improve in other PRs.

1. Show username+role on the header.

Currently, users can't see which account they logged in.
So, for instance, I want to show the username+role when hovering over the user icon.
image

2. Hide the SSO button(s) in the login form when they are not configured in the project.

Currently, both login with GitHub and login with OIDC are shown.
However, it's confusing because the GitHub button will appear even if OIDC is configured.(and then the GitHub button goes to OIDC's auth page)
image

@kumo-rn5s kumo-rn5s force-pushed the feature-oidc-support branch 2 times, most recently from 9e30f02 to 4ce7f7b Compare August 16, 2024 04:57
@kumo-rn5s
Copy link
Contributor Author

kumo-rn5s commented Aug 16, 2024

@t-kikuc I have addressed all the comments mentioned above.
Please review the changes from 9087fce to ef53065

Signed-off-by: kumo-rn5s <firosstuart@gmail.com>
Signed-off-by: kumo-rn5s <firosstuart@gmail.com>
t-kikuc
t-kikuc previously approved these changes Aug 19, 2024
Copy link
Member

@t-kikuc t-kikuc left a comment

Choose a reason for hiding this comment

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

Thank you for your great amazing contribution.

I commented some nits, but we'll fix in other PRs.


| Field | Type | Description | Required |
|-|-|-|-|
| ClientId | string | The client id string of OpenID Connect oauth app. | Yes |
Copy link
Member

Choose a reason for hiding this comment

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

We'll fix in later PRs.

Field names are actually lowerCamelCase.

Copy link
Member

Choose a reason for hiding this comment

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

solved by #5173

)

func TestParseProjectAndState(t *testing.T) {
tests := []struct {
Copy link
Member

Choose a reason for hiding this comment

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

We'll add t.Parallel() in later PRs.

Copy link
Member

Choose a reason for hiding this comment

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

solved by #5173

@@ -853,3 +853,66 @@ func TestProject_DeleteRBACRole(t *testing.T) {
})
}
}

func TestGenerateAuthCodeURL(t *testing.T) {
tests := []struct {
Copy link
Member

Choose a reason for hiding this comment

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

We'll add 't.Parallel()' later.

Copy link
Member

@ffjlabo ffjlabo left a comment

Choose a reason for hiding this comment

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

Thank you for the great contribution! I left a comment 🙏

pkg/app/server/httpapi/callback.go Outdated Show resolved Hide resolved
Co-authored-by: Yoshiki Fujikane <40124947+ffjlabo@users.noreply.github.com>
Signed-off-by: Kumo <35224826+kumo-rn5s@users.noreply.github.com>
@kumo-rn5s
Copy link
Contributor Author

@ffjlabo Sorry for the late response. I have signed off that suggestion to commit.

@kumo-rn5s kumo-rn5s requested a review from ffjlabo August 26, 2024 15:35
@t-kikuc
Copy link
Member

t-kikuc commented Aug 27, 2024

@kumo-rn5s Sorry, would you resolve the conflict of go.mod? 🙏

(The faiied test / go (pull_request) does not matter because it's due to a flaky test)

kumo-rn5s and others added 2 commits August 28, 2024 12:38
Signed-off-by: Kumo <35224826+kumo-rn5s@users.noreply.github.com>
Signed-off-by: kumo-rn5s <firosstuart@gmail.com>
@t-kikuc
Copy link
Member

t-kikuc commented Aug 28, 2024

Reopen due to the flaky test...

@t-kikuc t-kikuc closed this Aug 28, 2024
@t-kikuc t-kikuc reopened this Aug 28, 2024
Copy link

codecov bot commented Aug 28, 2024

Codecov Report

Attention: Patch coverage is 51.04167% with 94 lines in your changes missing coverage. Please review.

Project coverage is 22.96%. Comparing base (3d4bd4f) to head (35ad7e9).
Report is 1 commits behind head on master.

Files Patch % Lines
pkg/oauth/oidc/oidc.go 46.03% 68 Missing ⚠️
pkg/app/server/httpapi/callback.go 44.73% 21 Missing ⚠️
pkg/model/project.go 82.14% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5008      +/-   ##
==========================================
+ Coverage   22.82%   22.96%   +0.14%     
==========================================
  Files         412      413       +1     
  Lines       43838    44020     +182     
==========================================
+ Hits        10005    10111     +106     
- Misses      33042    33120      +78     
+ Partials      791      789       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@t-kikuc t-kikuc left a comment

Choose a reason for hiding this comment

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

Greatest Amazing Big Impact Contribution, Thank you!!! 🚀

Copy link
Member

@ffjlabo ffjlabo left a comment

Choose a reason for hiding this comment

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

Thank you for the great commit🚀

@t-kikuc t-kikuc merged commit f7c0b13 into pipe-cd:master Aug 28, 2024
24 of 27 checks passed
This was referenced Sep 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[feat] Support OIDC for the SSO
3 participants