mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-11-03 20:17:59 +00:00 
			
		
		
		
	identity/oidc: change the state parameter to optional (#16599)
* identity/oidc: change the state parameter to optional * adds changelog * update docs
This commit is contained in:
		
							
								
								
									
										3
									
								
								changelog/16599.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								changelog/16599.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					```release-note:bug
 | 
				
			||||||
 | 
					identity/oidc: Change the `state` parameter of the Authorization Endpoint to optional.
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
@@ -448,7 +448,6 @@ func oidcProviderPaths(i *IdentityStore) []*framework.Path {
 | 
				
			|||||||
				"state": {
 | 
									"state": {
 | 
				
			||||||
					Type:        framework.TypeString,
 | 
										Type:        framework.TypeString,
 | 
				
			||||||
					Description: "The value used to maintain state between the authentication request and client.",
 | 
										Description: "The value used to maintain state between the authentication request and client.",
 | 
				
			||||||
					Required:    true,
 | 
					 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				"nonce": {
 | 
									"nonce": {
 | 
				
			||||||
					Type:        framework.TypeString,
 | 
										Type:        framework.TypeString,
 | 
				
			||||||
@@ -1609,11 +1608,7 @@ func (i *IdentityStore) keyIDsReferencedByTargetClientIDs(ctx context.Context, s
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (i *IdentityStore) pathOIDCAuthorize(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
 | 
					func (i *IdentityStore) pathOIDCAuthorize(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
 | 
				
			||||||
	// Validate the state
 | 
					 | 
				
			||||||
	state := d.Get("state").(string)
 | 
						state := d.Get("state").(string)
 | 
				
			||||||
	if state == "" {
 | 
					 | 
				
			||||||
		return authResponse("", "", ErrAuthInvalidRequest, "state parameter is required")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get the namespace
 | 
						// Get the namespace
 | 
				
			||||||
	ns, err := namespace.FromContext(ctx)
 | 
						ns, err := namespace.FromContext(ctx)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,7 +55,7 @@ func TestOIDC_Path_OIDC_Cross_Provider_Exchange(t *testing.T) {
 | 
				
			|||||||
	require.NoError(t, err)
 | 
						require.NoError(t, err)
 | 
				
			||||||
	require.NoError(t, json.Unmarshal(resp.Data["http_raw_body"].([]byte), &authRes))
 | 
						require.NoError(t, json.Unmarshal(resp.Data["http_raw_body"].([]byte), &authRes))
 | 
				
			||||||
	require.Regexp(t, authCodeRegex, authRes.Code)
 | 
						require.Regexp(t, authCodeRegex, authRes.Code)
 | 
				
			||||||
	require.NotEmpty(t, authRes.State)
 | 
						require.Equal(t, req.Data["state"], authRes.State)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Assert that the authorization code cannot be exchanged using the second provider
 | 
						// Assert that the authorization code cannot be exchanged using the second provider
 | 
				
			||||||
	var tokenRes struct {
 | 
						var tokenRes struct {
 | 
				
			||||||
@@ -477,7 +477,7 @@ func TestOIDC_Path_OIDC_Token(t *testing.T) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			require.NoError(t, json.Unmarshal(resp.Data["http_raw_body"].([]byte), &authRes))
 | 
								require.NoError(t, json.Unmarshal(resp.Data["http_raw_body"].([]byte), &authRes))
 | 
				
			||||||
			require.Regexp(t, authCodeRegex, authRes.Code)
 | 
								require.Regexp(t, authCodeRegex, authRes.Code)
 | 
				
			||||||
			require.NotEmpty(t, authRes.State)
 | 
								require.Equal(t, tt.args.authorizeReq.Data["state"], authRes.State)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Update the assignment
 | 
								// Update the assignment
 | 
				
			||||||
			tt.args.assignmentReq.Operation = logical.UpdateOperation
 | 
								tt.args.assignmentReq.Operation = logical.UpdateOperation
 | 
				
			||||||
@@ -740,21 +740,6 @@ func TestOIDC_Path_OIDC_Authorize(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			wantErr: ErrAuthInvalidRedirectURI,
 | 
								wantErr: ErrAuthInvalidRedirectURI,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "invalid authorize request with missing state",
 | 
					 | 
				
			||||||
			args: args{
 | 
					 | 
				
			||||||
				entityID:      entityID,
 | 
					 | 
				
			||||||
				clientReq:     testClientReq(s),
 | 
					 | 
				
			||||||
				providerReq:   testProviderReq(s, clientID),
 | 
					 | 
				
			||||||
				assignmentReq: testAssignmentReq(s, entityID, groupID),
 | 
					 | 
				
			||||||
				authorizeReq: func() *logical.Request {
 | 
					 | 
				
			||||||
					req := testAuthorizeReq(s, clientID)
 | 
					 | 
				
			||||||
					req.Data["state"] = ""
 | 
					 | 
				
			||||||
					return req
 | 
					 | 
				
			||||||
				}(),
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			wantErr: ErrAuthInvalidRequest,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "invalid authorize request with request parameter provided",
 | 
								name: "invalid authorize request with request parameter provided",
 | 
				
			||||||
			args: args{
 | 
								args: args{
 | 
				
			||||||
@@ -910,6 +895,20 @@ func TestOIDC_Path_OIDC_Authorize(t *testing.T) {
 | 
				
			|||||||
				}(),
 | 
									}(),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "valid authorize request with empty state",
 | 
				
			||||||
 | 
								args: args{
 | 
				
			||||||
 | 
									entityID:      entityID,
 | 
				
			||||||
 | 
									clientReq:     testClientReq(s),
 | 
				
			||||||
 | 
									providerReq:   testProviderReq(s, clientID),
 | 
				
			||||||
 | 
									assignmentReq: testAssignmentReq(s, entityID, groupID),
 | 
				
			||||||
 | 
									authorizeReq: func() *logical.Request {
 | 
				
			||||||
 | 
										req := testAuthorizeReq(s, clientID)
 | 
				
			||||||
 | 
										req.Data["state"] = ""
 | 
				
			||||||
 | 
										return req
 | 
				
			||||||
 | 
									}(),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "active re-authentication required with token creation time exceeding max_age requirement",
 | 
								name: "active re-authentication required with token creation time exceeding max_age requirement",
 | 
				
			||||||
			args: args{
 | 
								args: args{
 | 
				
			||||||
@@ -1143,7 +1142,7 @@ func TestOIDC_Path_OIDC_Authorize(t *testing.T) {
 | 
				
			|||||||
			expectSuccess(t, resp, err)
 | 
								expectSuccess(t, resp, err)
 | 
				
			||||||
			require.Equal(t, http.StatusOK, resp.Data[logical.HTTPStatusCode].(int))
 | 
								require.Equal(t, http.StatusOK, resp.Data[logical.HTTPStatusCode].(int))
 | 
				
			||||||
			require.Regexp(t, authCodeRegex, authRes.Code)
 | 
								require.Regexp(t, authCodeRegex, authRes.Code)
 | 
				
			||||||
			require.NotEmpty(t, authRes.State)
 | 
								require.Equal(t, tt.args.authorizeReq.Data["state"], authRes.State)
 | 
				
			||||||
			require.Empty(t, authRes.Error)
 | 
								require.Empty(t, authRes.Error)
 | 
				
			||||||
			require.Empty(t, authRes.ErrorDescription)
 | 
								require.Empty(t, authRes.ErrorDescription)
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -672,7 +672,7 @@ to be used for the [Authorization Code Flow](https://openid.net/specs/openid-con
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
- `redirect_uri` `(string: <required>)` - The redirection URI to which the response will be sent.
 | 
					- `redirect_uri` `(string: <required>)` - The redirection URI to which the response will be sent.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- `state` `(string: <required>)` - A value used to maintain state between the authentication request and client.
 | 
					- `state` `(string: <optional>)` - A value used to maintain state between the authentication request and client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- `nonce` `(string: <optional>)` - A value that is returned in the ID token nonce claim. It is used to mitigate replay attacks, so we *strongly encourage* providing this optional parameter.
 | 
					- `nonce` `(string: <optional>)` - A value that is returned in the ID token nonce claim. It is used to mitigate replay attacks, so we *strongly encourage* providing this optional parameter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -199,7 +199,7 @@ Each provider offers an unauthenticated endpoint that provides the public portio
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Authorization Endpoint
 | 
					### Authorization Endpoint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Each provider offers an authenticated [authorization endpoint](https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint). The authorization endpoint for each provider is added to Vault's [default policy](/docs/concepts/policies#default-policy) using the `identity/oidc/provider/+/authorize` path. The endpoint incorporates all required [authentication request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) parameters as input. Additionally, the `state` parameter is required.
 | 
					Each provider offers an authenticated [authorization endpoint](https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint). The authorization endpoint for each provider is added to Vault's [default policy](/docs/concepts/policies#default-policy) using the `identity/oidc/provider/+/authorize` path. The endpoint incorporates all required [authentication request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) parameters as input.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The endpoint [validates](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequestValidation) client requests and ensures that all required parameters are present and valid. The `redirect_uri` of the request is validated against the client's `redirect_uris`. The requesting Vault entity will be validated against the client's `assignments`. An appropriate [error code](https://openid.net/specs/openid-connect-core-1_0.html#AuthError) is returned for invalid requests.
 | 
					The endpoint [validates](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequestValidation) client requests and ensures that all required parameters are present and valid. The `redirect_uri` of the request is validated against the client's `redirect_uris`. The requesting Vault entity will be validated against the client's `assignments`. An appropriate [error code](https://openid.net/specs/openid-connect-core-1_0.html#AuthError) is returned for invalid requests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user