Access Saml assertion or Response

Hello All, I have a request where I need to send Saml assertion in an external request. I’m insitiating SSO and ACS url will be our internal method, here is there any way to access saml assertion/ response to be accessed and send it in a different request. We don’t need to send it to SP. We have to send saml assertion/response as Json. We are using .net core

You can construct the SAML assertion directly in your code rather than calling through the ISamlIdentityProvider interface.

For example:


using ComponentSpace.Saml2.Assertions;

var samlAssertion = new SamlAssertion()
{
// TODO - set the various properties as required.
};

// Typically you would serialize the SAML assertion to XML prior to sending.
var samlAssertionElement = samlAssertion.ToXml();



The GenerateSignature project under the Examples\Signature folder demonstrates how to sign a SAML assertion.

If this isn’t exactly what you wish to achieve, please provide some more details of your requirements.

For example, do you want to send a SAML response or SAML assertion?

Are you signing the SAML assertion using an XML signature?

How are you converting the SAML assertion object or the signed XML to JSON?

How is the JSON being transmitted?

[quote]
ComponentSpace - 10/9/2021
You can construct the SAML assertion directly in your code rather than calling through the ISamlIdentityProvider interface.

For example:


using ComponentSpace.Saml2.Assertions;

var samlAssertion = new SamlAssertion()
{
// TODO - set the various properties as required.
};

// Typically you would serialize the SAML assertion to XML prior to sending.
var samlAssertionElement = samlAssertion.ToXml();



The GenerateSignature project under the Examples\Signature folder demonstrates how to sign a SAML assertion.

If this isn't exactly what you wish to achieve, please provide some more details of your requirements.

For example, do you want to send a SAML response or SAML assertion?

Are you signing the SAML assertion using an XML signature?

How are you converting the SAML assertion object or the signed XML to JSON?

How is the JSON being transmitted?
[/quote]

Basically we need to send signed saml response to other portal in Json format, is there a easy way to this instead of creating assertion manually. We don;t need to initiate any SSO.

The OnSamlResponseCreated event provides you with access to the SAML response.

For example:


private Task CompleteSsoAsync()
{
_samlIdentityProvider.Events.OnSamlResponseCreated = (context, samlResponse) =>
{
// Send the SAML response or save it for sending later - not shown.

return samlResponse;
};

// Get the name of the logged in user.
var userName = User.Identity.Name;

// For demonstration purposes, include some claims.
var attributes = new List()
{
new SamlAttribute(ClaimTypes.Email, User.FindFirst(ClaimTypes.Email)?.Value),
new SamlAttribute(ClaimTypes.GivenName, User.FindFirst(ClaimTypes.GivenName)?.Value),
new SamlAttribute(ClaimTypes.Surname, User.FindFirst(ClaimTypes.Surname)?.Value),
};

// The user is logged in at the identity provider.
// Respond to the authn request by sending a SAML response containing a SAML assertion to the SP.
return _samlIdentityProvider.SendSsoAsync(userName, attributes);
}



I’m not sure how you intend to send the SAML response but you could either send it or save it for later sending from the OnSamlResponseCreated event.

If you also want to stop the SAML response being returned to the browser in the HTTP response as part of the SAML protocol, you can implement the IHttpResponse interface so that the HTTP response is written to a memory stream and therefore doesn’t go anywhere.

For example:


public class NopHttpResponse : IHttpResponse
{
public string ContentType { get; set; }

public Stream Body { get; set; } = new MemoryStream();

public void AddCookie(string cookieName, string cookieValue,
ComponentSpace.Saml2.Bindings.CookieOptions cookieOptions)
{
}

public void AddHeader(string headerName, StringValues headerValues)
{
}

public void Redirect(string url)
{
}
}



You register this implementation at start-up as follows:


// Add SAML SSO services.
services.AddSaml(Configuration.GetSection(“SAML”));

services.AddTransient<IHttpResponse, NoHttpResponse>();



It would be good to have a better understanding of your requirements to see if there’s a better solution. Sending an XML signed SAML response message as JSON is very unusual.

[quote]
ComponentSpace - 10/10/2021
The OnSamlResponseCreated event provides you with access to the SAML response.

For example:


private Task CompleteSsoAsync()
{
_samlIdentityProvider.Events.OnSamlResponseCreated = (context, samlResponse) =>
{
// Send the SAML response or save it for sending later - not shown.

return samlResponse;
};

// Get the name of the logged in user.
var userName = User.Identity.Name;

// For demonstration purposes, include some claims.
var attributes = new List()
{
new SamlAttribute(ClaimTypes.Email, User.FindFirst(ClaimTypes.Email)?.Value),
new SamlAttribute(ClaimTypes.GivenName, User.FindFirst(ClaimTypes.GivenName)?.Value),
new SamlAttribute(ClaimTypes.Surname, User.FindFirst(ClaimTypes.Surname)?.Value),
};

// The user is logged in at the identity provider.
// Respond to the authn request by sending a SAML response containing a SAML assertion to the SP.
return _samlIdentityProvider.SendSsoAsync(userName, attributes);
}



I'm not sure how you intend to send the SAML response but you could either send it or save it for later sending from the OnSamlResponseCreated event.

If you also want to stop the SAML response being returned to the browser in the HTTP response as part of the SAML protocol, you can implement the IHttpResponse interface so that the HTTP response is written to a memory stream and therefore doesn't go anywhere.

For example:


public class NopHttpResponse : IHttpResponse
{
public string ContentType { get; set; }

public Stream Body { get; set; } = new MemoryStream();

public void AddCookie(string cookieName, string cookieValue,
ComponentSpace.Saml2.Bindings.CookieOptions cookieOptions)
{
}

public void AddHeader(string headerName, StringValues headerValues)
{
}

public void Redirect(string url)
{
}
}



You register this implementation at start-up as follows:


// Add SAML SSO services.
services.AddSaml(Configuration.GetSection("SAML"));

services.AddTransient();



It would be good to have a better understanding of your requirements to see if there's a better solution. Sending an XML signed SAML response message as JSON is very unusual.
[/quote]

Thanks for your reply, below is the saml code.

public async Task GenerateAssertion(string AppId, string Email)
{

var resp = new ApiResponse
{
responseCode = 0
};
try
{
if (!string.IsNullOrWhiteSpace(Email) && !string.IsNullOrWhiteSpace(AppId))
{
var userName = string.Empty;
var partnerName = string.Empty;
foreach (var item in _samlConfigurations.Configurations)
{
partnerName = item.PartnerServiceProviderConfigurations.Select(x => x.Name).FirstOrDefault();
}
userName = Email;
var attributes = new List()
{
new SamlAttribute(ClaimTypes.Email, Email),
new SamlAttribute("NameID", Email),
};
var response = _samlIdentityProvider.Events.OnSamlResponseCreated = (context, samlResponse) =>
{
// Send the SAML response or save it for sending later - not shown.
var test = samlResponse.ToXml();
var xmlAssertion = samlResponse.ToXml().OuterXml;
return samlResponse;

};

//Here is there a way not to inititate SSO and not to redirect to ACS url.
//I will be using samlResponse as string/xml and we need to send it to our internal method, where
// we will will sending it as object in response. Primary authentication is different, we need this assertion
// as addition.
_ = _samlIdentityProvider.InitiateSsoAsync(partnerName, userName, attributes, null, null);
}
else
{
_ = Task.Run(() => _logService.Info("Processing SamlController - Invalid Email"));
}
}
catch (Exception ex)
{
resp.responseMessage = "Unexpected error occured.";
_ = Task.Run(() => _logService.Error("Error in SamlController - Inititate SSO :" + ex));
}
}

Basically we need only assertion as one of the requirement. Here is there a way not to inititate SSO and not to redirect to ACS url.
I will be using samlResponse as string/xml and we need to send it to our internal method, where
we will will sending it as object in response. Primary authentication is different, we need this assertion
as addition parameter.


You have a couple of options.

The first option is to construct the SamlAssertion object and then sign it.

The second option is to call into the ISamlIdentityProvider interface (_samlIdentityProvider.InitiateSsoAsync or _samlIdentityProvider.SendSsoAsync). To stop the SAML response being sent to the service provider’s assertion consumer service, you need to use the NopHttpResponse as outlined in my previous post.

[quote]
ComponentSpace - 10/11/2021
You have a couple of options.

The first option is to construct the SamlAssertion object and then sign it.

The second option is to call into the ISamlIdentityProvider interface (_samlIdentityProvider.InitiateSsoAsync or _samlIdentityProvider.SendSsoAsync). To stop the SAML response being sent to the service provider's assertion consumer service, you need to use the NopHttpResponse as outlined in my previous post.
[/quote]

Hello ,

I am using InitiateSsoAsync With NoHttpReponse. I got the saml response. But it is missing tag. How do I get complete response with Signature?

I’ve replied to your separate post. You can use the OnSendMessage event to access the SAML response message including the XML signature.

I have a requirement to send signed SAML response to SP in .net core class library. we were able to do it in .net framework applications but couldn’t make it in .net core applications.

signedXml = signature.Generate(responseXml, certificate?.GetRSAPrivateKey(), SamlConstants.DigestAlgorithms.SHA256, SamlConstants.SignatureAlgorithms.RSA_SHA256, null, certificate);

looking for the equivalent method in .net core for the below code
// IdentityProvider.SendSAMLResponseByHTTPPost(response, _response.Destination, responseXml, targetUrl);

Appreciate any help