This is an automated email from the ASF dual-hosted git repository.

zike pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-client-go.git


The following commit(s) were added to refs/heads/master by this push:
     new c3b0633a [Fix] Oauth2 Client credentials flow use scopes from the 
keyfile as well (#1244)
c3b0633a is described below

commit c3b0633a2f5fcc5b560b504d04fdef0e82f6b72a
Author: Nikolaj Lund Sørensen <nikolajlundsoren...@gmail.com>
AuthorDate: Wed Jul 24 12:51:19 2024 +0200

    [Fix] Oauth2 Client credentials flow use scopes from the keyfile as well 
(#1244)
    
    ### Motivation
    
    As the issue shows when using Pulsarctl which works with a context as 
configuration style, Oauth2 is used under the hood.
    
    However the library does not expose any way to inject the context 
configuration `scope` value, and then relies on reading that from the `keyFile` 
for `client_credentials flow`.
    
    However that is not being utilized in the current code as the scope value 
is not read from from the file.
    
    *Explain here the context, and why you're making that change. What is the 
problem you're trying to solve.*
    To allow the usage of oauth2 with a keyfile in Pulsarctl 3+ which it 
doesn't right now
    
    ### Modifications
    Alters so reading the keyFile for client credentials also returns the 
`scope` value.
    
    The value is then split on spaces, and added to a temporary slice.
    After that the value of any additionalScopes that was already in the 
options is then added to the temp slice as well.
    In the end the additionalScopes property on the options is set to the temp 
slice containing values from previous additionalScopes and the ones from the 
keyFile.
---
 oauth2/client_credentials_flow.go          | 18 +++++++++++++++---
 oauth2/client_credentials_flow_test.go     |  6 +++++-
 oauth2/client_credentials_provider.go      |  1 +
 oauth2/client_credentials_provider_test.go |  2 ++
 4 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/oauth2/client_credentials_flow.go 
b/oauth2/client_credentials_flow.go
index 2252144a..9a2643a9 100644
--- a/oauth2/client_credentials_flow.go
+++ b/oauth2/client_credentials_flow.go
@@ -20,6 +20,8 @@ package oauth2
 import (
        "net/http"
 
+       "strings"
+
        "github.com/apache/pulsar-client-go/oauth2/clock"
 
        "github.com/pkg/errors"
@@ -68,7 +70,6 @@ func newClientCredentialsFlow(
 // NewDefaultClientCredentialsFlow provides an easy way to build up a default
 // client credentials flow with all the correct configuration.
 func NewDefaultClientCredentialsFlow(options ClientCredentialsFlowOptions) 
(*ClientCredentialsFlow, error) {
-
        credsProvider := 
NewClientCredentialsProviderFromKeyFile(options.KeyFile)
        keyFile, err := credsProvider.GetClientCredentials()
        if err != nil {
@@ -81,7 +82,6 @@ func NewDefaultClientCredentialsFlow(options 
ClientCredentialsFlowOptions) (*Cli
        }
 
        tokenRetriever := NewTokenRetriever(&http.Client{})
-
        return newClientCredentialsFlow(
                options,
                keyFile,
@@ -94,13 +94,25 @@ var _ Flow = &ClientCredentialsFlow{}
 
 func (c *ClientCredentialsFlow) Authorize(audience string) 
(*AuthorizationGrant, error) {
        var err error
+
+       // Merge the scopes of the options AdditionalScopes with the scopes 
read from the keyFile config
+       var scopesToAdd []string
+       if len(c.options.AdditionalScopes) > 0 {
+               scopesToAdd = append(scopesToAdd, c.options.AdditionalScopes...)
+       }
+
+       if c.keyfile.Scope != "" {
+               scopesSplit := strings.Split(c.keyfile.Scope, " ")
+               scopesToAdd = append(scopesToAdd, scopesSplit...)
+       }
+
        grant := &AuthorizationGrant{
                Type:              GrantTypeClientCredentials,
                Audience:          audience,
                ClientID:          c.keyfile.ClientID,
                ClientCredentials: c.keyfile,
                TokenEndpoint:     c.oidcWellKnownEndpoints.TokenEndpoint,
-               Scopes:            c.options.AdditionalScopes,
+               Scopes:            scopesToAdd,
        }
 
        // test the credentials and obtain an initial access token
diff --git a/oauth2/client_credentials_flow_test.go 
b/oauth2/client_credentials_flow_test.go
index 987ae73d..6d9db354 100644
--- a/oauth2/client_credentials_flow_test.go
+++ b/oauth2/client_credentials_flow_test.go
@@ -47,6 +47,7 @@ var clientCredentials = KeyFile{
        ClientSecret: "test_clientSecret",
        ClientEmail:  "test_clientEmail",
        IssuerURL:    "http://issuer";,
+       Scope:        "test_scope",
 }
 
 var _ = Describe("ClientCredentialsFlow", func() {
@@ -64,9 +65,11 @@ var _ = Describe("ClientCredentialsFlow", func() {
                })
 
                It("invokes TokenExchanger with credentials", func() {
+                       additionalScope := "additional_scope"
                        provider := newClientCredentialsFlow(
                                ClientCredentialsFlowOptions{
-                                       KeyFile: "test_keyfile",
+                                       KeyFile:          "test_keyfile",
+                                       AdditionalScopes: 
[]string{additionalScope},
                                },
                                &clientCredentials,
                                oidcEndpoints,
@@ -81,6 +84,7 @@ var _ = Describe("ClientCredentialsFlow", func() {
                                ClientID:      clientCredentials.ClientID,
                                ClientSecret:  clientCredentials.ClientSecret,
                                Audience:      "test_audience",
+                               Scopes:        []string{additionalScope, 
clientCredentials.Scope},
                        }))
                })
 
diff --git a/oauth2/client_credentials_provider.go 
b/oauth2/client_credentials_provider.go
index 3eb8ba44..4083bc35 100644
--- a/oauth2/client_credentials_provider.go
+++ b/oauth2/client_credentials_provider.go
@@ -38,6 +38,7 @@ type KeyFile struct {
        ClientSecret string `json:"client_secret"`
        ClientEmail  string `json:"client_email"`
        IssuerURL    string `json:"issuer_url"`
+       Scope        string `json:"scope"`
 }
 
 func NewClientCredentialsProviderFromKeyFile(keyFile string) *KeyFileProvider {
diff --git a/oauth2/client_credentials_provider_test.go 
b/oauth2/client_credentials_provider_test.go
index 869616d7..8e69f1c5 100644
--- a/oauth2/client_credentials_provider_test.go
+++ b/oauth2/client_credentials_provider_test.go
@@ -34,12 +34,14 @@ func TestNewClientCredentialsProviderFromKeyFile(t 
*testing.T) {
        ClientSecret := "CLIENT_SECRET"
        ClientEmail := "CLIENT_EMAIL"
        IssuerURL := "ISSUER_URL"
+       Scope := "SCOPE"
        keyFile := &KeyFile{
                Type:         oauthType,
                ClientID:     clientID,
                ClientSecret: ClientSecret,
                ClientEmail:  ClientEmail,
                IssuerURL:    IssuerURL,
+               Scope:        Scope,
        }
 
        b, err := json.Marshal(keyFile)

Reply via email to