identity/oidc: adds client_secret_post token endpoint authentication method (#16598)
* identity/oidc: adds client_secret_post token endpoint authentication method * fix test * adds changelog
This commit is contained in:
parent
b7365df464
commit
59831a8d5c
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
identity/oidc: Adds the `client_secret_post` token endpoint authentication method.
|
||||
```
|
|
@ -510,8 +510,8 @@ func oidcProviderPaths(i *IdentityStore) []*framework.Path {
|
|||
Description: "The code verifier associated with the authorization code.",
|
||||
},
|
||||
// For confidential clients, the client_id and client_secret are provided to
|
||||
// the token endpoint via the 'client_secret_basic' authentication method, which
|
||||
// uses the HTTP Basic authentication scheme. See the OIDC spec for details at:
|
||||
// the token endpoint via the 'client_secret_basic' or 'client_secret_post'
|
||||
// authentication methods. See the OIDC spec for details at:
|
||||
// https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication
|
||||
|
||||
// For public clients, the client_id is required and a client_secret does
|
||||
|
@ -522,6 +522,10 @@ func oidcProviderPaths(i *IdentityStore) []*framework.Path {
|
|||
Type: framework.TypeString,
|
||||
Description: "The ID of the requesting client.",
|
||||
},
|
||||
"client_secret": {
|
||||
Type: framework.TypeString,
|
||||
Description: "The secret of the requesting client.",
|
||||
},
|
||||
},
|
||||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
|
@ -1483,6 +1487,7 @@ func (i *IdentityStore) pathOIDCProviderDiscovery(ctx context.Context, req *logi
|
|||
// PKCE is required for auth method "none"
|
||||
"none",
|
||||
"client_secret_basic",
|
||||
"client_secret_post",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -1856,13 +1861,15 @@ func (i *IdentityStore) pathOIDCToken(ctx context.Context, req *logical.Request,
|
|||
return tokenResponse(nil, ErrTokenInvalidRequest, "provider not found")
|
||||
}
|
||||
|
||||
// Get the client ID
|
||||
// client_secret_basic - Check for client credentials in the Authorization header
|
||||
clientID, clientSecret, okBasicAuth := basicAuth(req)
|
||||
if !okBasicAuth {
|
||||
// client_secret_post - Check for client credentials in the request body
|
||||
clientID = d.Get("client_id").(string)
|
||||
if clientID == "" {
|
||||
return tokenResponse(nil, ErrTokenInvalidRequest, "client_id parameter is required")
|
||||
}
|
||||
clientSecret = d.Get("client_secret").(string)
|
||||
}
|
||||
client, err := i.clientByID(ctx, req.Storage, clientID)
|
||||
if err != nil {
|
||||
|
@ -1873,8 +1880,7 @@ func (i *IdentityStore) pathOIDCToken(ctx context.Context, req *logical.Request,
|
|||
return tokenResponse(nil, ErrTokenInvalidClient, "client failed to authenticate")
|
||||
}
|
||||
|
||||
// Authenticate the client using the client_secret_basic authentication method if it's a
|
||||
// confidential client. The authentication method uses the HTTP Basic authentication scheme.
|
||||
// Authenticate the client if it's a confidential client type.
|
||||
// Details at https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication
|
||||
if client.Type == confidential &&
|
||||
subtle.ConstantTimeCompare([]byte(client.ClientSecret), []byte(clientSecret)) == 0 {
|
||||
|
|
|
@ -433,6 +433,22 @@ func TestOIDC_Path_OIDC_Token(t *testing.T) {
|
|||
tokenReq: testTokenReq(s, "", clientID, clientSecret),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid token request with client_secret_post client authentication method",
|
||||
args: args{
|
||||
clientReq: testClientReq(s),
|
||||
providerReq: testProviderReq(s, clientID),
|
||||
assignmentReq: testAssignmentReq(s, entityID, groupID),
|
||||
authorizeReq: testAuthorizeReq(s, clientID),
|
||||
tokenReq: func() *logical.Request {
|
||||
req := testTokenReq(s, "", clientID, clientSecret)
|
||||
req.Headers = nil
|
||||
req.Data["client_id"] = clientID
|
||||
req.Data["client_secret"] = clientSecret
|
||||
return req
|
||||
}(),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid token request",
|
||||
args: args{
|
||||
|
@ -3613,7 +3629,7 @@ func TestOIDC_Path_OpenIDProviderConfig(t *testing.T) {
|
|||
TokenEndpoint: basePath + "/token",
|
||||
UserinfoEndpoint: basePath + "/userinfo",
|
||||
GrantTypes: []string{"authorization_code"},
|
||||
AuthMethods: []string{"none", "client_secret_basic"},
|
||||
AuthMethods: []string{"none", "client_secret_basic", "client_secret_post"},
|
||||
RequestParameter: false,
|
||||
RequestURIParameter: false,
|
||||
}
|
||||
|
@ -3668,7 +3684,7 @@ func TestOIDC_Path_OpenIDProviderConfig(t *testing.T) {
|
|||
TokenEndpoint: basePath + "/token",
|
||||
UserinfoEndpoint: basePath + "/userinfo",
|
||||
GrantTypes: []string{"authorization_code"},
|
||||
AuthMethods: []string{"none", "client_secret_basic"},
|
||||
AuthMethods: []string{"none", "client_secret_basic", "client_secret_post"},
|
||||
RequestParameter: false,
|
||||
RequestURIParameter: false,
|
||||
}
|
||||
|
|
|
@ -288,7 +288,7 @@ This endpoint creates or updates a client.
|
|||
- `confidential`
|
||||
- Capable of maintaining the confidentiality of its credentials
|
||||
- Has a client secret
|
||||
- Uses the `client_secret_basic` [client authentication method](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication)
|
||||
- Uses the `client_secret_basic` or `client_secret_post` [client authentication method](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication)
|
||||
- May use Proof Key for Code Exchange ([PKCE](https://datatracker.ietf.org/doc/html/rfc7636))
|
||||
for the authorization code flow
|
||||
- `public`
|
||||
|
@ -602,6 +602,7 @@ $ curl \
|
|||
],
|
||||
"token_endpoint_auth_methods_supported": [
|
||||
"client_secret_basic",
|
||||
"client_secret_post",
|
||||
"none"
|
||||
]}
|
||||
```
|
||||
|
@ -737,9 +738,13 @@ for an OIDC provider.
|
|||
authorization request was sent. This must match the `redirect_uri` used when the
|
||||
original authorization code was generated.
|
||||
|
||||
- `client_id` `(string: <required>)` - The ID of the requesting client. This parameter
|
||||
is only required for `public` clients which do not have a client secret. `confidential`
|
||||
clients should not use this parameter.
|
||||
- `client_id` `(string: <optional>)` - The ID of the requesting client. This parameter
|
||||
is required for `public` clients which do not have a client secret or `confidential`
|
||||
clients using the `client_secret_post` client authentication method.
|
||||
|
||||
- `client_secret` `(string: <optional>)` - The secret of the requesting client. This
|
||||
parameter is required for `confidential` clients using the `client_secret_post` client
|
||||
authentication method.
|
||||
|
||||
- `code_verifier` `(string: <optional>)` - The code verifier associated with the given
|
||||
`code`. Required for authorization codes that were granted using [PKCE](https://datatracker.ietf.org/doc/html/rfc7636).
|
||||
|
@ -747,9 +752,10 @@ for an OIDC provider.
|
|||
|
||||
### Headers
|
||||
|
||||
- `Authorization: Basic` `(string: <required>)` - An HTTP Basic authentication scheme header
|
||||
- `Authorization: Basic` `(string: <optional>)` - An HTTP Basic authentication scheme header
|
||||
including the `client_id` and `client_secret` as described in the [client_secret_basic](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication)
|
||||
authentication method. This header is only required for `confidential` clients.
|
||||
authentication method. This header is only required for `confidential` clients using
|
||||
the `client_secret_basic` client authentication method.
|
||||
|
||||
### Sample Request
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ Confidential clients may use Proof Key for Code Exchange ([PKCE](https://datatra
|
|||
during the authorization code flow.
|
||||
|
||||
Confidential clients must authenticate to the token endpoint using the
|
||||
`client_secret_basic` [client authentication method](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication).
|
||||
`client_secret_basic` or `client_secret_post` [client authentication method](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication).
|
||||
|
||||
##### Public
|
||||
|
||||
|
|
|
@ -125,7 +125,8 @@ Any Vault auth method may be used within the OIDC flow. For simplicity, enable t
|
|||
],
|
||||
"token_endpoint_auth_methods_supported": [
|
||||
"none",
|
||||
"client_secret_basic"
|
||||
"client_secret_basic",
|
||||
"client_secret_post"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
|
Loading…
Reference in New Issue