I have a SAML Assertion template that I want to use to generate a SAML assertion after I have validated the username and password. I don’t want to use the default assertion generated by Apigee. How do I use my template to dynamically generate the SAML assertion after the username and password are validated (assuming I use Apigee BaaS)?
My SAML Template is shown below. I'll post the answer shortly.
<?xml version="1.0" encoding="UTF-8"?> <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:enc="http://www.w3.org/2001/04/xmlenc#" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Destination="https://liveperson.net" ID="ppVee6mrzFP" IssueInstant="2017-06-06T19:50:58Z" Version="2.0"> <saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://example.com</saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /> </samlp:Status> <saml:Assertion ID="id-gLNuoAc3" IssueInstant="2017-06-06T19:50:58Z" Version="2.0"> <saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://example.com</saml:Issuer> <dsig:Signature> <dsig:SignedInfo> <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> <dsig:Reference URI="#id-gLNuFhD9M3"> <dsig:Transforms> <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> <dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> </dsig:Transforms> <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <dsig:DigestValue>NEQc=</dsig:DigestValue> </dsig:Reference> </dsig:SignedInfo> <dsig:SignatureValue>XhjPzGkx</dsig:SignatureValue> </dsig:Signature> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">username</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData NotOnOrAfter="2017-06-06T19:55:58Z" Recipient="https://liveperson.net/" /> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2017-06-06T19:50:58Z" NotOnOrAfter="2017-06-06T19:55:58Z"> <saml:AudienceRestriction> <saml:Audience>LivePerson</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2017-06-06T19:08:11Z" SessionIndex="id-sKouq-ydUXs" SessionNotOnOrAfter="2017-06-06T20:50:58Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>Scheme</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="siteId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">22</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="loginName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">user@email.com</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion> </samlp:Response>
SAML uses a public/private key, so you should follow the steps here, which describe how to:
Apigee BaaS
The next step is to create a user within Apigee BaaS in your Sandbox application. Use the Apigee BaaS sandbox application as a POC only, as it does not have the appropriate security for production applications. Use the UI to create the user.
In the top left corner of Apigee BaaS make sure that the “Sandbox” application is selected.
Click Users on the right side of the screen.
Click the “add new user” button.
The “Create New User” form will open. Enter the new user’s info here.
Generate SAML Policy Template
GenerateSAMLAssertion policy is shown below.
Notice the following:
<?xml version="1.0" encoding="UTF-8"?> <GenerateSAMLAssertion ignoreContentType="false" name="GenerateSAML-Assertion2"> <DisplayName>GenerateSAML-Assertion2</DisplayName> <KeyStore> <Name ref="reference">SAML</Name> <Alias ref="reference">demo.com</Alias> </KeyStore> <Subject ref="username" /> <Issuer ref="issuer" /> <Template ignoreUnresolvedVariables="false"><![CDATA[ <saml:Assertion xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:enc="http://www.w3.org/2001/04/xmlenc#" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Destination="https://liveperson.net/" ID="55555" IssueInstant="2017-06-06T19:50:58Z" Version="2.0"> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">{apigee.username}</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData NotOnOrAfter="{saml.issueInstant}" Destination="https://liveperson.net"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="{mysaml.now}" NotOnOrAfter="{mysaml.expiry}"> <saml:AudienceRestriction> <saml:Audience>LivePerson</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="{mysaml.now}"> <saml:AuthnContext> <saml:AuthnContextClassRef>{saml.authnContextClassRef}</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="siteId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">7 </saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="loginName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string"> {apigee.mail} </saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion>]]></Template> <OutputVariable> <FlowVariable name="assertion.content" /> </OutputVariable> </GenerateSAMLAssertion>
Generate SAML Policy Result
The result of the policy is shown below.
A couple of items to point out.
<?xml version="1.0" encoding="UTF-8"?> <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:enc="http://www.w3.org/2001/04/xmlenc#" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ID="_810fec639be5361041181654789e7bc7" IssueInstant="2017-06-19T16:21:07.310Z" Version="2.0"> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://yourdomain.com/oam/fed</saml2:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> <ds:Reference URI="#_89e7bc7"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs" /> </ds:Transform> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <ds:DigestValue>9iBSrY=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>cbFUpfcSZg=</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>MIICRgHBEZX9+k</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">username</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData Destination="https://liveperson.net/" NotOnOrAfter="2017-06-19T16:21:07.310Z" /> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2017-06-19T16:21:07Z" NotOnOrAfter="2017-06-19T17:21:07Z"> <saml:AudienceRestriction> <saml:Audience>LivePerson</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2017-06-19T16:21:07Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="siteId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">97</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="loginName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">email@yourdomain.com</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion>
This code is implemented in the following repository.
The POST request to test is shown below.
curl -X POST \ https://org-env.apigee.net/saml/generate-saml -H 'content-type: application/json' \ -d '{ "username":"youruser", "password":"password" }'
Hi @swilliams,
I installed your repo, (made a small pull request as well ;-)), but I am unable to solve an error.
First I changed the CURL command to include the content-type XML, because it complains about the media type. (This could also be resolved by setting: ignoreContentType="true" for that matter.)
But I seem to be running into the same error over and over again. (On the easiest request).
curl -X GET \ https://ORG-ENV.apigee.net/saml/generate-saml \ -H 'cache-control: no-cache' -H "Content-Type:application/xml"
I generated my own certificates and keystores, tried your sample key files (which are expired for about 2 months by the way).
(I also have the same issue on my own created GenerateSAMLAssertion).
The error is: "Error transforming assertion into message.".
Errorcode: "steps.saml.generate.ErrorUpdatingPayload".
Attached the Trace output, which also indicates: "premature end of file" and an "UncheckedException".
Does anybody got a clue what I might be doing wrong?
Hello @Gijs Zonneveld
Can you send me your GenerateSAMLAssertion policy? It sounds like there is an issue within the Template element.
Thanks for your response.
I am using the one as unmodified as possible from your sample.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <GenerateSAMLAssertion ignoreContentType="false" name="GenerateSAML-Assertion"> <DisplayName>GenerateSAML-Assertion</DisplayName> <KeyStore> <Name>keystorename</Name> <Alias>keystorealias</Alias> <!--use reference to refer to a flow variable instead of hardcoding.--> <!--Name ref="flow.variable"></Name--> <!--Alias ref="flow.variable"></Alias--> </KeyStore> <Subject ref="reference">1234</Subject> <Issuer ref="reference">samltest</Issuer> <!--use reference to refer to a flow variable instead of hardcoding.--> <!--Subject ref="flow.variable"></Subject--> <!--Issuer ref="flow.variable"></Issuer--> <Template ignoreUnresolvedVariables="false"/> <OutputVariable> <Message name="message"> <Namespaces> <Namespace prefix="soapenv">http://schemas.xmlsoap.org/soap/envelope/</Namespace> </Namespaces> <XPath>/soapenv:Envelope/soapenv:Header</XPath> </Message> </OutputVariable> </GenerateSAMLAssertion>
Am I overlooking something?
Thanks!
I updated my repo. I had a couple of copy and paste errors.
1) The GenerateSAMLAssertion output variable should be
<OutputVariable> <FlowVariable name="assertion.content"/> </OutputVariable>
2) The proxies default.xml file should not include a route (see below).
<RouteRule name="route"> </RouteRule>
It should work after you make these changes as long as the keystore and alias that you created matches what is defined in the GenerateSAMLAssertion policy. Also, it should be deployed to the same environment where you created the keystore/alias.
<KeyStore> <Name>keystorename</Name> <Alias>keystorealias</Alias> </KeyStore>
Thanks for your great support! I now made my first SAML request, thanks for your help, really appreciated!
Hi @swilliams,
Sorry to bother again and maybe a little off-topic.
I am now trying to define a template te create a signed Meta-Data Consumer request, containing some md:SPSSODescriptor elements.
I don't seem to get it working, by Apigee edge. Would you be able to help me out with a start?
Thanks in advance.
Hello @Gijs Zonneveld
Please create a new question in the community and include as much information as possible.
Is Apigee supposed to generate the SAML or validate it?
Provide a sample of the SAML request.
Provide info about the consumer of the SAML token.
What attributes need to be variables in the template?
The more information you provide about the context of your question will make it easier for someone to answer quickly.
Thanks! @swilliams I created a new ticket, altered the question a little and added a sample request, defining more or less what I want to achive.
User | Count |
---|---|
7 | |
2 | |
2 | |
2 | |
1 |