Open omidraha opened 3 weeks ago
The default behavior is due to the default login request template set in the library (libsaml
in libsaml.ts
). Specifically, the defaultLoginRequestTemplate
in this file has ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
as the default protocol.
In this case, similar to other fields that are dynamically created, the ProtocolBinding
field is not assigned a specific value and always remains set to the default value, which is POST
.
About sp.createLoginRequest
with custom template question:
This filed should be define in ServiceProviderSettings
:
loginRequestTemplate: {
context: `<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" \
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" \
ID="{ID}" \
Version="2.0" \
IssueInstant="{IssueInstant}" \
Destination="{Destination}" \
AssertionConsumerServiceURL="{AssertionConsumerServiceURL}"> \
<saml:Issuer>{Issuer}</saml:Issuer> \
<samlp:NameIDPolicy Format="{NameIDFormat}" AllowCreate="{AllowCreate}" /> \
</samlp:AuthnRequest>`,
},
About ProtocolBinding
questing:
ProtocolBinding:
The ProtocolBinding attribute on AuthnRequest is used to specify the expected binding to be used by the IdP when sending their SAML Response XML. HTTP-Redirect isn't a valid option to use here, because of the possible length restriction on the URL querystring; a SAML Response,especially if it's signed, can be pretty lengthy.
https://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf
- Identity Provider issues
to Service Provider In step 5, the identity provider issues a message to be delivered by the user agent to the service provider. Either the HTTP POST, or HTTP Artifact binding can be used to transfer the message to the service provider through the user agent. The message may indicate an error, or will include (at least) an authentication assertion. The HTTP Redirect binding MUST NOT be used, as the response will typically exceed the URL length permitted by most user agents.
Considering that the loginRequestTemplate
type is SAMLDocumentTemplate
and should be assigned as follows:
// Custom loginRequestTemplate
loginRequestTemplate: {
context: `<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" \
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" \
ID="{ID}" \
Version="2.0" \
IssueInstant="{IssueInstant}" \
Destination="{Destination}" \
AssertionConsumerServiceURL="{AssertionConsumerServiceURL}"> \
<saml:Issuer>{Issuer}</saml:Issuer> \
<samlp:NameIDPolicy Format="{NameIDFormat}" AllowCreate="{AllowCreate}" /> \
</samlp:AuthnRequest>`,
},
};
But why the type of template
is defined as a string
?
createLoginRequest(idp: IdentityProvider, binding?: string, customTagReplacement?: (template: string) => BindingContext): BindingContext | PostBindingContext | SimpleSignBindingContext;
When printing its type and value in the customTagReplacement
method:
async generateSAMLRequest(
idp: IdentityProviderInstance,
sp: ServiceProviderInstance,
binding: string
): Promise<{ id: string; context: string }> {
const customTagReplacement = (template: string): BindingContext => {
console.log(
typeof template,
template
);
return {
id: sp.entitySetting.generateID(),
// should be template.context
context: template,
};
};
const { id, context } = sp.createLoginRequest(
idp,
binding,
customTagReplacement
);
return { id, context };
}
);
It appears as an object
and is displayed as follows:
{
context: '<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{ID}" Version="2.0" IssueInstant="{IssueInstant}" Destination="{Destination}" AssertionConsumerServiceURL="{AssertionConsumerServiceURL}"> <saml:Issuer>{Issuer}</saml:Issuer> <samlp:NameIDPolicy Format="{NameIDFormat}" AllowCreate="{AllowCreate}" /> </samlp:AuthnRequest>'
}
I've encountered an issue with the
createLoginRequest
method insamlify
. When using a custom callback for modifying the SAML request template, thecontext
returned by the callback appears to be ignored. Instead, thecontext
used bysamlify
is automatically generated, and any custom values specified in the callback seem to be overridden. Here’s a simplified version of my code:In the above example, even though the callback specifies
context: 'NEVER USED'
, the actualcontext
value logged in the console comes from thesamlify
library's internal handling, not the callback’s return value.Expected Behavior: The
context
provided by the callback should be used as the final output when returned, instead of being replaced by an internally generatedcontext
.Actual Behavior: The
context
set within the callback is overridden bysamlify
’s internally generated SAML request.Is there any suggested approach to ensure the custom
context
value from the callback is respected?My goal is to replace
ProtocolBinding
in the SAML request with the appropriate value, eitherurn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect
orurn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
. However, it always defaults tourn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
.Here’s a simplified version of the code I’m using:
Observed Output
Despite modifying the
ProtocolBinding
in the callback, the generated SAML request always includesProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
, even when binding is set toredirect
. Here’s an example of the