Skip to content

Add Support for Custom Saml Bearer in HttpRequest Headers #3273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 3, 2025

Conversation

sthanu98
Copy link
Contributor

@sthanu98 sthanu98 commented Feb 28, 2025

Add Support for Saml Authorization Scheme in HttpRequest Headers

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Summary of the changes (Less than 80 chars)

Description

This PR introduces a change to the way authorization headers are added to HTTP requests, specifically to support SAML tokens. The change ensures that custom SAML authorization schemes are correctly added using TryAddWithoutValidation. This approach allows for more flexible handling of SAML tokens, even when they might not pass standard validation.

Changes:

Replaced the below line to improve compatibility with custom SAML authorization schemes.

httpRequestMessage.Headers.Add(Authorization, authorizationHeader);

with

httpRequestMessage.Headers.TryAddWithoutValidation(Authorization, authorizationHeader);

Added unit tests to validate the new behavior and ensure headers are correctly added in various scenarios.

Fixes #3269

@sthanu98 sthanu98 requested a review from a team as a code owner February 28, 2025 16:12
@sthanu98
Copy link
Contributor Author

@sthanu98 please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.

@microsoft-github-policy-service agree [company="{your company}"]

Options:

  • (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@microsoft-github-policy-service agree
  • (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@microsoft-github-policy-service agree company="Microsoft"

Contributor License Agreement

@microsoft-github-policy-service agree company="Microsoft"

@pmaytak
Copy link
Contributor

pmaytak commented Feb 28, 2025

Couple of questions:

  • What exactly is the error now when using the SAML auth header?
  • What validation is skipped when using the new method?
  • Looks like there's property NonValidated for such headers, does HTTP client treat those headers differently, will it cause issues E2E?
  • Is there a way to add the SAML header value as valid to the HTTP client?
    • I am a bit skeptical on turning off validation for all header values. This means we should make sure we have proper test coverage that makes sure the header creator doesn't create invalid headers somehow (also, for ex. if we add a new header provider implementation).

@sthanu98
Copy link
Contributor Author

sthanu98 commented Mar 2, 2025

@pmaytak

  1. System.FormatException: The format of value 'http://schemas.microsoft.com/dsts/saml2-bearer token-redacted' is invalid.
    at System.Net.Http.Headers.HttpHeaderParser.ParseValue(String value, Object storeValue, Int32& index)
    at System.Net.Http.Headers.HttpHeaders.ParseAndAddValue(HeaderDescriptor descriptor, HeaderStoreItemInfo info, String value)
    at System.Net.Http.Headers.HttpHeaders.Add(HeaderDescriptor descriptor, String value)
    at ActorServer_WebAPI_MISE.Controllers.HelloWorldController.GetAsync() in C:\repos\Microsoft.Identity.Client.Internal\samples\SamlOBO\ActorServer_WebAPI_MISE\Controllers\HelloWorldController.cs:line 61

This is the error when using Add() instead of TryAddWithoutValidation()

  1. HttpHeaders.ParseAndAddValue method is skipped in TryAddWithoutValidation()
  2. the NonValidated headers are treated the same as validated headers when sending requests in HttpClient.
  3. The SAML header value we are passing fails the ParseAndAddValue validation, so we cannot make it valid for httpclient. If you are skeptical of this change affecting existing JWT scenarios, we can change to either of the below implementations
if(authorizationHeader.StartsWith("https://schemas.microsoft.com/saml-bearer"))
{
httpRequestMessage.Headers.TryAddWithoutValidation(Authorization, authorizationHeader);
}
else
{
httpRequestMessage.Headers.Add(Authorization, authorizationHeader)
}

or

try
{
httpRequestMessage.Headers.Add(Authorization, authorizationHeader)
}
catch(FormatException)
{
httpRequestMessage.Headers.TryAddWithoutValidation(Authorization, authorizationHeader);
}

Copy link
Collaborator

@jmprieur jmprieur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM
Thanks @sthanu98

@jmprieur jmprieur merged commit 2e7b8ca into AzureAD:master Mar 3, 2025
4 of 5 checks passed
@pmaytak pmaytak added this to the 3.8.0 milestone Mar 21, 2025
This was referenced Aug 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature Request] Support for using SAML bearer tokens to call Downstream API using Headers.TryAddWithoutValidation()
4 participants