Skip to content

Commit d8614fb

Browse files
author
CI Bot
committed
Merge remote-tracking branch 'origin/pr/client-credentials-grant-sync'
2 parents c3165b1 + f72d7eb commit d8614fb

File tree

5 files changed

+39
-4
lines changed

5 files changed

+39
-4
lines changed

server/handlers.go

+31
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,8 @@ func (s *Server) handleToken(w http.ResponseWriter, r *http.Request) {
859859
s.withClientFromStorage(w, r, s.handlePasswordGrant)
860860
case grantTypeTokenExchange:
861861
s.withClientFromStorage(w, r, s.handleTokenExchange)
862+
case grantTypeClientCredentials:
863+
s.withClientFromStorage(w, r, s.handleClientCredentialsGrant)
862864
default:
863865
s.tokenErrHelper(w, errUnsupportedGrantType, "", http.StatusBadRequest)
864866
}
@@ -1111,6 +1113,35 @@ func (s *Server) handleUserInfo(w http.ResponseWriter, r *http.Request) {
11111113
w.Write(claims)
11121114
}
11131115

1116+
func (s *Server) handleClientCredentialsGrant(w http.ResponseWriter, r *http.Request, client storage.Client) {
1117+
if err := r.ParseForm(); err != nil {
1118+
s.tokenErrHelper(w, errInvalidRequest, "Couldn't parse data", http.StatusBadRequest)
1119+
return
1120+
}
1121+
q := r.Form
1122+
1123+
nonce := q.Get("nonce")
1124+
scopes := strings.Fields(q.Get("scope"))
1125+
1126+
claims := storage.Claims{UserID: client.ID}
1127+
1128+
accessToken, _, err := s.newAccessToken(r.Context(), client.ID, claims, scopes, nonce, "client")
1129+
if err != nil {
1130+
s.logger.ErrorContext(r.Context(), "failed to create new access token", "err", err)
1131+
s.tokenErrHelper(w, errServerError, err.Error(), http.StatusInternalServerError)
1132+
return
1133+
}
1134+
1135+
idToken, expiry, err := s.newIDToken(r.Context(), client.ID, claims, scopes, nonce, accessToken, "", "client")
1136+
if err != nil {
1137+
s.tokenErrHelper(w, errServerError, fmt.Sprintf("failed to create ID token: %v", err), http.StatusInternalServerError)
1138+
return
1139+
}
1140+
1141+
resp := s.toAccessTokenResponse(idToken, accessToken, "", expiry)
1142+
s.writeAccessToken(w, resp)
1143+
}
1144+
11141145
func (s *Server) handlePasswordGrant(w http.ResponseWriter, r *http.Request, client storage.Client) {
11151146
ctx := r.Context()
11161147
// Parse the fields

server/handlers_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func TestHandleDiscovery(t *testing.T) {
6363
Introspect: fmt.Sprintf("%s/token/introspect", httpServer.URL),
6464
GrantTypes: []string{
6565
"authorization_code",
66+
"client_credentials",
6667
"refresh_token",
6768
"urn:ietf:params:oauth:grant-type:device_code",
6869
"urn:ietf:params:oauth:grant-type:token-exchange",

server/oauth2.go

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ const (
133133
grantTypePassword = "password"
134134
grantTypeDeviceCode = "urn:ietf:params:oauth:grant-type:device_code"
135135
grantTypeTokenExchange = "urn:ietf:params:oauth:grant-type:token-exchange"
136+
grantTypeClientCredentials = "client_credentials"
136137
)
137138

138139
const (

server/server.go

+1
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ func newServer(ctx context.Context, c Config, rotationStrategy rotationStrategy)
237237
grantTypeRefreshToken: true,
238238
grantTypeDeviceCode: true,
239239
grantTypeTokenExchange: true,
240+
grantTypeClientCredentials: true,
240241
}
241242
supportedRes := make(map[string]bool)
242243

server/server_test.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ func newTestServer(ctx context.Context, t *testing.T, updateConfig func(c *Confi
101101
grantTypeTokenExchange,
102102
grantTypeImplicit,
103103
grantTypePassword,
104+
grantTypeClientCredentials,
104105
},
105106
}
106107
if updateConfig != nil {
@@ -1760,7 +1761,7 @@ func TestServerSupportedGrants(t *testing.T) {
17601761
{
17611762
name: "Simple",
17621763
config: func(c *Config) {},
1763-
resGrants: []string{grantTypeAuthorizationCode, grantTypeRefreshToken, grantTypeDeviceCode, grantTypeTokenExchange},
1764+
resGrants: []string{grantTypeAuthorizationCode, grantTypeClientCredentials, grantTypeRefreshToken, grantTypeDeviceCode, grantTypeTokenExchange},
17641765
},
17651766
{
17661767
name: "Minimal",
@@ -1770,20 +1771,20 @@ func TestServerSupportedGrants(t *testing.T) {
17701771
{
17711772
name: "With password connector",
17721773
config: func(c *Config) { c.PasswordConnector = "local" },
1773-
resGrants: []string{grantTypeAuthorizationCode, grantTypePassword, grantTypeRefreshToken, grantTypeDeviceCode, grantTypeTokenExchange},
1774+
resGrants: []string{grantTypeAuthorizationCode, grantTypeClientCredentials, grantTypePassword, grantTypeRefreshToken, grantTypeDeviceCode, grantTypeTokenExchange},
17741775
},
17751776
{
17761777
name: "With token response",
17771778
config: func(c *Config) { c.SupportedResponseTypes = append(c.SupportedResponseTypes, responseTypeToken) },
1778-
resGrants: []string{grantTypeAuthorizationCode, grantTypeImplicit, grantTypeRefreshToken, grantTypeDeviceCode, grantTypeTokenExchange},
1779+
resGrants: []string{grantTypeAuthorizationCode, grantTypeClientCredentials, grantTypeImplicit, grantTypeRefreshToken, grantTypeDeviceCode, grantTypeTokenExchange},
17791780
},
17801781
{
17811782
name: "All",
17821783
config: func(c *Config) {
17831784
c.PasswordConnector = "local"
17841785
c.SupportedResponseTypes = append(c.SupportedResponseTypes, responseTypeToken)
17851786
},
1786-
resGrants: []string{grantTypeAuthorizationCode, grantTypeImplicit, grantTypePassword, grantTypeRefreshToken, grantTypeDeviceCode, grantTypeTokenExchange},
1787+
resGrants: []string{grantTypeAuthorizationCode, grantTypeClientCredentials, grantTypeImplicit, grantTypePassword, grantTypeRefreshToken, grantTypeDeviceCode, grantTypeTokenExchange},
17871788
},
17881789
}
17891790

0 commit comments

Comments
 (0)