Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Commit 9acdb64

Browse files
authored
Merge pull request #424 from kbrekke/bugfix/par
Set correct ClientCredentialStyle for use with ClientAssertion
2 parents 5203769 + f611ad7 commit 9acdb64

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

src/OidcClient/AuthorizeClient.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,14 @@ private async Task<PushedAuthorizationResponse> PushAuthorizationRequestAsync(st
140140

141141
ClientSecret = _options.ClientSecret,
142142
ClientAssertion = await _options.GetClientAssertionAsync(),
143-
144143
Parameters = CreateAuthorizeParameters(state, codeChallenge, frontChannelParameters),
145144
};
146145

146+
if(par.ClientAssertion?.Value != null)
147+
{
148+
par.ClientCredentialStyle = ClientCredentialStyle.PostBody;
149+
}
150+
147151
return await http.PushAuthorizationAsync(par);
148152
}
149153

test/OidcClient.Tests/CodeFlowResponseTests.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using System.Threading.Tasks;
1717
using IdentityModel.Client;
1818
using Xunit;
19+
using System.Web;
1920

2021
namespace IdentityModel.OidcClient.Tests
2122
{
@@ -486,5 +487,82 @@ public async Task Malformed_identity_token_on_token_response_should_fail()
486487
result.IsError.Should().BeTrue();
487488
result.Error.Should().Contain("invalid_jwt");
488489
}
490+
491+
[Fact]
492+
public async Task Authorize_should_push_parameters_when_PAR_is_enabled()
493+
{
494+
// Configure the client for PAR, authenticating with a client secret
495+
_options.ClientSecret = "secret";
496+
_options.ProviderInformation.PushedAuthorizationRequestEndpoint = "https://this-is-set-so-par-will-be-used";
497+
var client = new OidcClient(_options);
498+
499+
// Mock the response from the par endpoint
500+
var requestUri = "mocked_request_uri";
501+
var parResponse = new Dictionary<string, string>
502+
{
503+
{ "request_uri", requestUri }
504+
};
505+
var backChannelHandler = new NetworkHandler(JsonSerializer.Serialize(parResponse), HttpStatusCode.OK);
506+
_options.BackchannelHandler = backChannelHandler;
507+
508+
// Prepare the login to cause the backchannel PAR request
509+
var state = await client.PrepareLoginAsync();
510+
511+
// Validate that the resulting PAR state is correct
512+
var startUrl = new Uri(state.StartUrl);
513+
var startUrlQueryParams = HttpUtility.ParseQueryString(startUrl.Query);
514+
startUrlQueryParams.Should().HaveCount(2);
515+
startUrlQueryParams.GetValues("client_id").Single().Should().Be("client");
516+
startUrlQueryParams.GetValues("request_uri").Single().Should().Be(requestUri);
517+
518+
// Validate that the client authentication during the PAR request was correct
519+
var request = backChannelHandler.Request;
520+
request.Headers.Authorization.Should().NotBeNull();
521+
request.Headers.Authorization.Scheme.Should().Be("Basic");
522+
request.Headers.Authorization.Parameter.Should()
523+
.Be(BasicAuthenticationOAuthHeaderValue.EncodeCredential("client", "secret"));
524+
}
525+
526+
[Fact]
527+
public async Task Par_request_should_include_client_assertion_in_body()
528+
{
529+
// Configure the client for PAR, authenticating with a client assertion
530+
var clientAssertion = "mocked_client_assertion";
531+
var clientAssertionType = "mocked_assertion_type";
532+
_options.ClientAssertion = new ClientAssertion
533+
{
534+
Type = clientAssertionType,
535+
Value = clientAssertion
536+
};
537+
_options.ProviderInformation.PushedAuthorizationRequestEndpoint = "https://this-is-set-so-par-will-be-used";
538+
var client = new OidcClient(_options);
539+
540+
// Mock the response from the par endpoint
541+
var requestUri = "mocked_request_uri";
542+
var parResponse = new Dictionary<string, string>
543+
{
544+
{ "request_uri", requestUri }
545+
};
546+
var backChannelHandler = new NetworkHandler(JsonSerializer.Serialize(parResponse), HttpStatusCode.OK);
547+
_options.BackchannelHandler = backChannelHandler;
548+
549+
// Prepare the login to cause the backchannel PAR request
550+
var state = await client.PrepareLoginAsync();
551+
552+
// Validate that the resulting PAR state is correct
553+
var startUrl = new Uri(state.StartUrl);
554+
var startUrlQueryParams = HttpUtility.ParseQueryString(startUrl.Query);
555+
startUrlQueryParams.Should().HaveCount(2);
556+
startUrlQueryParams.GetValues("client_id").Single().Should().Be("client");
557+
startUrlQueryParams.GetValues("request_uri").Single().Should().Be(requestUri);
558+
559+
// Validate that the client authentication during the PAR request was correct
560+
var parRequest = backChannelHandler.Request;
561+
var parContent = await parRequest.Content.ReadAsStringAsync();
562+
var parParams = HttpUtility.ParseQueryString(parContent);
563+
parParams.GetValues("client_assertion").Single().Should().Be(clientAssertion);
564+
parParams.GetValues("client_assertion_type").Single().Should().Be(clientAssertionType);
565+
parRequest.Headers.Authorization.Should().BeNull();
566+
}
489567
}
490568
}

0 commit comments

Comments
 (0)