Parse a SAML SSO request from a given URL with the High-Level-API

Our login process has multiple steps. So we pass through the SAML request to each page as SAML-encoded URL parameter.
After the login is completed we want to read the ReplyUrl from the original SSO request.

Unfortunately the High-Level-API has no method to parse a given SAML-Request. So we’re faking the HttpContext and use the ReceiveSsoAsync()-method to read the SAML request.
Please, could you advice me. Is there a better method?

My current code is attached below:

private IdpSsoResult GetSignInRequestMessage(string returnUrl)
{
if (returnUrl == “/”)
return null;

var request = _contextAccessor.HttpContext.Request;
var spUrl = new Uri(request.Scheme + “://” + request.Host + returnUrl);
if (request.Path.HasValue &&
!request.Path.Value.Equals(spUrl.LocalPath, StringComparison.OrdinalIgnoreCase))
{
// workaround to trick high level api
var tempPath = request.Path;
var tempQuery = request.QueryString;
var tempMethod = request.Method;
request.Path = spUrl.LocalPath;
request.QueryString = new QueryString(spUrl.Query);
request.Method = “GET”;
var signInMessage = TryGetSignInRequestMessageAsync().Result;
request.Path = tempPath;
request.QueryString = tempQuery;
request.Method = tempMethod;
return signInMessage;
}
else
{
return TryGetSignInRequestMessageAsync().Result;
}
}

///


/// Get SSO request message or null if the message couldn’t be read.
///

private async Task TryGetSignInRequestMessageAsync()
{
try
{
return await _samlIdentityProvider.ReceiveSsoAsync();
}
catch (Exception ex)
{
_logger.LogWarning(“The SAML request can’t be parsed. {ex}”, ex);
}
return null;
}

At the first step where you receive the SAML authn request, couldn’t you call _samlIdentityProvider.ReceiveSsoAsync to process the message and for subsequent steps in the login process simply pass the information that’s required rather than the actual SAML authn request?
Having each step call _samlIdentityProvider.ReceiveSsoAsync to process the SAML authn request seems inefficient and more complicated.

We’re passing the full SAML request in the URL during the login steps because we wan’t to validate the signature of the SAML authn request before issuing the SAML token to the client. If we’d just pass the required information, we can’t make sure that it isn’t manipulated over the steps in the login process.

What exactly do you mean by the ReplyUrl?
Is there a particular field in the SAML authn request you need to save across the login steps?
Would the following work?
Call _samlIdentityProvider.ReceiveSsoAsync just once to have the authn request processed including verifying any signature.
Store any information required across the login steps as session data or via some other mechanism.
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-2.1&tabs=aspnetcore2x

I meant the URL where to send the issued security token after the login was successful.
We’ll take into consideration to use a server-side session. We’ve preferred to pass all required information across the login steps as URL parameters, because it’s easier for load-balanced scenarios.

Thanks. That’s referred to as the assertion consumer service URL. It’s the service provider URL where the SAML response is sent.
Please note that we handle the assertion consumer service URL internally. The application shouldn’t have to handle this aspect of SSO.
We will check the assertion consumer service URL against the list of valid URLs for the service provider and return the SAML response to this URL.