Skip to content

Commit feedeac

Browse files
committed
Do not reject end session requests that don't include an explicit client_id when request caching is used
1 parent 7517252 commit feedeac

File tree

2 files changed

+58
-11
lines changed

2 files changed

+58
-11
lines changed

src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -404,17 +404,8 @@ public ValueTask HandleAsync(ValidateEndSessionRequestContext context)
404404
return default;
405405
}
406406

407-
// For consistency with authorization requests, the client_id parameter
408-
// is also required when using a request_uri parameter is present.
409-
if (string.IsNullOrEmpty(context.Request.ClientId))
410-
{
411-
context.Reject(
412-
error: Errors.InvalidRequest,
413-
description: SR.FormatID2037(Parameters.RequestUri, Parameters.ClientId),
414-
uri: SR.FormatID8000(SR.ID2037));
415-
416-
return default;
417-
}
407+
// Note: unlike authorization requests, the client_id parameter is not required for end
408+
// session requests and may not be present in the original request before it is cached.
418409

419410
return default;
420411
}

test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Session.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,62 @@ public async Task ValidateEndSession_ValidRequestUriDoesNotCauseAnError()
206206
Assert.Equal("af0ifjsldkj", response.State);
207207
}
208208

209+
[Fact]
210+
public async Task ValidateEndSession_MissingClientIdDoesNotCauseAnError()
211+
{
212+
// Arrange
213+
await using var server = await CreateServerAsync(options =>
214+
{
215+
options.EnableDegradedMode();
216+
217+
options.AddEventHandler<HandleEndSessionRequestContext>(builder =>
218+
builder.UseInlineHandler(context =>
219+
{
220+
context.SignOut();
221+
222+
return default;
223+
}));
224+
225+
options.AddEventHandler<ValidateTokenContext>(builder =>
226+
{
227+
builder.UseInlineHandler(context =>
228+
{
229+
Assert.Equal("6esc_11ACC5bwc014ltc14eY22c", context.Token);
230+
Assert.Equal([TokenTypeHints.Private.RequestToken], context.ValidTokenTypes);
231+
232+
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
233+
.SetTokenType(TokenTypeHints.Private.RequestToken)
234+
.SetClaim(Claims.Private.RequestTokenType, RequestTokenTypes.Private.CachedEndSessionRequest)
235+
.SetClaim(Claims.Private.RequestParameters, $$"""
236+
{
237+
"post_logout_redirect_uri": "http://www.fabrikam.com/path",
238+
"state": "af0ifjsldkj"
239+
}
240+
""");
241+
242+
return default;
243+
});
244+
245+
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
246+
});
247+
});
248+
249+
await using var client = await server.CreateClientAsync();
250+
251+
// Act
252+
var response = await client.GetAsync("/connect/endsession", new OpenIddictRequest
253+
{
254+
ClientId = null,
255+
RequestUri = RequestUris.Prefixes.Generic + "6esc_11ACC5bwc014ltc14eY22c"
256+
});
257+
258+
// Assert
259+
Assert.Null(response.Error);
260+
Assert.Null(response.ErrorDescription);
261+
Assert.Null(response.ErrorUri);
262+
Assert.Equal("af0ifjsldkj", response.State);
263+
}
264+
209265
[Theory]
210266
[InlineData("/path", SR.ID2030)]
211267
[InlineData("/tmp/file.xml", SR.ID2030)]

0 commit comments

Comments
 (0)