Receiving SAML Logout response at /Saml2/Acs point - saml-2.0

In my application single logout works fine but after logout request processed on Idp i am getting response at /Saml2/Acs point. I am not sure where does this URL come from,so is there any particular way to configure this end point at SP side because i don't have control over Idp.
To provide additional details following are Login/Logout request responses
<!-- Loging Request -->
<saml2p:AuthnRequest
AssertionConsumerServiceURL="https://service.provider.com/server/Saml2/Acs"
Destination="https://identity.provider.com/nidp/saml2/sso" ID="id969024c5919e47148622d87bd40724ad"
IssueInstant="2019-04-08T10:51:03Z" Version="2.0"
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2:Issuer>https://service.provider.com</saml2:Issuer>
<saml2p:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>
</saml2p:AuthnRequest>
<!-- Loging Request -->
<!-- ##### -->
<!-- Login Response -->
<samlp:Response Destination="https://service.provider.com/server/Saml2/Acs"
ID="idNammIIHbKBac2pGfdbHqHFTwy9w" InResponseTo="id969024c5919e47148622d87bd40724ad"
IssueInstant="2019-04-08T10:51:49Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<saml:Issuer>https://identity.provider.com/nidp/saml2/metadata</saml:Issuer>
<samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status>
<saml:Assertion ID="idqn4Szd8L-wAJQojG9-4j-JAaXzo" IssueInstant="2019-04-08T10:51:49Z" Version="2.0">
<saml:Issuer>https://identity.provider.com/nidp/saml2/metadata</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"
xmlns="http://www.w3.org/2000/09/xmldsig#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#idqn4Szd8L-wAJQojG9-4j-JAaXzo">
<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#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue xmlns="http://www.w3.org/2000/09/xmldsig#">/KjwtCOlMQllJ8/rw22iowBNeEM=</DigestValue>
</ds:Reference>
</ds:SignedInfo>
<SignatureValue xmlns="http://www.w3.org/2000/09/xmldsig#">
SIGNARTURE-REMOVED
</SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
CERTIFICATE-REMOVED
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
NameQualifier="https://identity.provider.com/nidp/saml2/metadata"
SPNameQualifier="https://service.provider.com">00001234</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData InResponseTo="id969024c5919e47148622d87bd40724ad"
NotOnOrAfter="2019-04-08T10:56:49Z"
Recipient="https://service.provider.com/server/Saml2/Acs"/></saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2019-04-08T10:46:49Z" NotOnOrAfter="2019-04-08T10:56:49Z">
<saml:AudienceRestriction>
<saml:Audience>https://service.provider.com</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2019-04-08T10:45:27Z"
SessionIndex="idqn4Szd8L-wAJQojG9-4j-JAaXzo">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="achternaam"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<saml:AttributeValue xsi:type="xs:string">LastName</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="rollen" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<saml:AttributeValue xsi:type="xs:string">role</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<saml:AttributeValue xsi:type="xs:string">f.lastname#company.come</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="tussenvoegsel"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<saml:AttributeValue xsi:type="xs:string">middle</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="voornaam" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<saml:AttributeValue xsi:type="xs:string">FirstName</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="uniqueid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<saml:AttributeValue xsi:type="xs:string">00001234</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>
<!-- Login Response -->
<!-- ##### -->
<!-- Logout Request -->
<saml2p:LogoutRequest Destination="https://identity.provider.com/nidp/saml2/slo"
ID="idd2e66a13b3ed43b29a9fd06724723ea2" IssueInstant="2019-04-08T10:52:54Z" Version="2.0"
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2:Issuer>https://service.provider.com</saml2:Issuer>
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
NameQualifier="https://identity.provider.com/nidp/saml2/metadata"
SPNameQualifier="https://service.provider.com">00001234</saml2:NameID>
<saml2p:SessionIndex>idqn4Szd8L-wAJQojG9-4j-JAaXzo</saml2p:SessionIndex>
</saml2p:LogoutRequest>
<!-- Logout Request -->
<!-- ##### -->
<!-- Logout Response -->
<samlp:LogoutResponse Destination="https://service.provider.com/server/Saml2/Acs"
ID="idIANzyBI5tg2fB2dWOxcSrDA4bko" InResponseTo="idd2e66a13b3ed43b29a9fd06724723ea2"
IssueInstant="2019-04-08T10:52:55Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<saml:Issuer>https://identity.provider.com/nidp/saml2/metadata</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"
xmlns="http://www.w3.org/2000/09/xmldsig#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#idIANzyBI5tg2fB2dWOxcSrDA4bko">
<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#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue xmlns="http://www.w3.org/2000/09/xmldsig#">dcdadDJVjgx1hzfs/OK0eBHVbEc=</DigestValue>
</ds:Reference>
</ds:SignedInfo>
<SignatureValue xmlns="http://www.w3.org/2000/09/xmldsig#">
SIGNARTURE-REMOVED
</SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
CERTIFICATE-REMOVED
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status>
</samlp:LogoutResponse>
<!-- Logout Response -->

A 'single logout service' should be configured on the service provider with the location set to where you would like the SP to re-direct the user after logging out from the Identity Provider.
To check to see if this is configured properly, you could print out the metadata for your SP. As you can see in the metadata below, my SP has been configured with a SingleLogoutService (this is where the logout requests and responses are sent from the IdP).
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:3000/auth/saml-logout-callback"/>
The SingleLogoutService has a location of "http://localhost:3000/auth/saml-logout-callback" meaning that the SP will send the user to /auth/saml-logout-callback on receiving a Logout Response. Of course, your SP should be configured to send the user to a different endpoint in dev than in production.
Setting up this this was pretty straight forward for me because I am using the Passport SAML library to configure the SP options. So, if you are using a library to communicate with SAML, there might be some good options to configure the SP single logout location. In passport, you specify the logout url as a parameter when declaring the SAML strategy.
I've written some more about the general workflow for signing out here: https://spin.atomicobject.com/2019/04/06/saml-2-0-flow/

Related

How to supply unit_count_type and unit_count Amazon product data feed?

I supplied value of unit of Measure and Unit count in _POST_PRODUCT_DATA_ feed.
XmlElement unitOfMeasure = xmlDocument.CreateElement("unitOfMeasure");
unitOfMeasure.InnerText = "Count";
Product.AppendChild(unitOfMeasure);
XmlElement UnitCount = xmlDocument.CreateElement("UnitCount");
UnitCount.InnerText = "1";
Product.AppendChild(UnitCount);
My xml feed looks like this
<?xml version="1.0" encoding="iso-8859-1"?>
<AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
<Header>
<DocumentVersion>1.01</DocumentVersion>
<MerchantIdentifier>xxxxxxx</MerchantIdentifier>
</Header>
<MessageType>Product</MessageType>
<PurgeAndReplace>false</PurgeAndReplace>
<Message>
<MessageID>1</MessageID>
<OperationType>Update</OperationType>
<Product>
<SKU>book1568388578</SKU>
<StandardProductID>
<Type>ASIN</Type>
<Value>1568388578</Value>
</StandardProductID>
<ProductTaxCode>A_GEN_NOTAX</ProductTaxCode>
<unitOfMeasure>count</unitOfMeasure>
<UnitCount>1</UnitCount>
<DescriptionData>
<Title>Relapse Prevention Long-term Workbook</Title>
<Brand> </Brand>
<Description> </Description>
<BulletPoint> </BulletPoint>
<BulletPoint> </BulletPoint>
<MSRP currency="USD">70.74</MSRP>
<Manufacturer>Hazelden Foundation,U.S.</Manufacturer>
<ItemType>books</ItemType>
</DescriptionData>
<ProductData>
<Health>
<ProductType>
<HealthMisc>
<Ingredients>Example Ingredients</Ingredients>
<Directions>Example Directions</Directions>
</HealthMisc>
</ProductType>
</Health>
</ProductData>
</Product>
</Message>
</AmazonEnvelope>
I am getting following error in feed result.
XML Parsing Error at Line 19, Column 22: cvc-complex-type.2.4.a: Invalid content was found starting with element &apos;unitOfMeasure&apos;. One of &apos;{LaunchDate, DiscontinueDate, ReleaseDate, ExternalProductUrl, Condition, Rebate, ItemPackageQuantity, NumberOfItems, LiquidVolume, DescriptionData, DiscoveryData, ProductData, ShippedByFreight, EnhancedImageURL, Amazon-Vendor-Only, Amazon-Only, RegisteredParameter, NationalStockNumber, UnspscCode, UVPListPrice}&apos; is expected.
I got the solution. You need to provide this feed of unit count in HealthMisc
Correct xml..
<?xml version="1.0" encoding="iso-8859-1"?>
<AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
<Header>
<DocumentVersion>1.01</DocumentVersion>
<MerchantIdentifier>xxxxxxxxxx</MerchantIdentifier>
</Header>
<MessageType>Product</MessageType>
<PurgeAndReplace>false</PurgeAndReplace>
<Message>
<MessageID>1</MessageID>
<OperationType>Update</OperationType>
<Product>
<SKU>book1568388578</SKU>
<StandardProductID>
<Type>ASIN</Type>
<Value>1568388578</Value>
</StandardProductID>
<ProductTaxCode>A_GEN_NOTAX</ProductTaxCode>
<DescriptionData>
<Title>Relapse Prevention Long-term Workbook</Title>
<Brand> </Brand>
<Description> </Description>
<BulletPoint> </BulletPoint>
<BulletPoint> </BulletPoint>
<MSRP currency="USD">70.74</MSRP>
<Manufacturer>Hazelden Foundation,U.S.</Manufacturer>
<ItemType>books</ItemType>
</DescriptionData>
<ProductData>
<Health>
<ProductType>
<HealthMisc>
<UnitCount unitOfMeasure="Count">1</UnitCount>
<Ingredients>Example Ingredients</Ingredients>
<Directions>Example Directions</Directions>
</HealthMisc>
</ProductType>
</Health>
</ProductData>
</Product>
</Message>
</AmazonEnvelope>

VoiceXML gives 'internal error' but no obvious error is shown

I have created this VoiceXML code to ask the user to fill in some data, which is then supposed to be stored in the database.
When I run the code through Postman to simulate the request, I don't get any errors back. But when I actually run and call my Python/Django voice application I get an 'internal error' back once my application reaches that part.
The VoiceXML output:
<?xml version="1.0" encoding="UTF-8"?>
<!--- <vxml version = "2.1" > -->
<!DOCTYPE vxml SYSTEM "http://www.w3.org/TR/voicexml21/vxml.dtd">
<vxml xmlns="http://www.w3.org/2001/vxml"
version="2.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/vxml
http://www.w3.org/TR/2007/REC-voicexml21-20070619/vxml.xsd">
<!---<property name="inputmodes" value="dtmf" /> -->
<!-- Kasadaka VoiceXML File -->
<form id="input_form">
<property name="inputmodes" value="dtmf" />
<property name="interdigittimeout" value="2s"/>
<property name="timeout" value="4s"/>
<property name="termchar" value="#" />
<field name="DTMF_input" type="digits?maxlength=5">
<prompt>
<audio src="/uploads/petrichor_here_you_can_fill_in_your_farmer_id_en_QL7Xu6T.wav"/>
</prompt>
</field>
<block>
<prompt>
<audio src="/uploads/petrichor_thank_you_for_your_input_en_rFaZyF5.wav"/>
</prompt>
<filled namelist="DTMF_input">
<submit src=" /vxml/InputData/34/18" namelist="DTMF_input" method="post"/>
</filled>
</block>
</form>
</vxml>
And if needed, the code that is supposed to save the input:
def InputData(request, element_id, session_id):
input_element = get_object_or_404(InputData_model, pk=element_id)
voice_service = input_element.service
session = lookup_or_create_session(voice_service, session_id)
if request.method == "POST":
session = get_object_or_404(CallSession, pk=session_id)
value = 'DTMF_input'
result = UserInput()
result.session = session
result.category = input_element.input_category
result.save()
return redirect(request.POST['redirect'])
session.record_step(input_element)
context = input_generate_context(input_element, session)
context['url'] = request.get_full_path(False)
return render(request, 'input.xml', context, content_type='text/xml')
Is my VoiceXML code correct if I want the user to be able to fill in numbers through DTMF and then store that data into my model? Or am I missing something important for it to work?
EDIT: Error Logs:
============================================================
Error Summary
============================================================
An error occurred while executing the following dialog.
Initial URL1: http://petrichor-rain-system.herokuapp.com/vxml/start/3
Initial URL2: null
Initial URL3: null
Current URL: /vxml/choice/35/26
Calling Number (ANI): 447520631888
Called Number (DNIS): 9991494860
Redirecting Number (RDNIS): ""
State: hello-and-welcome
VoiceXML Browser Version: 16.0.25.88606
Date/Time: 2019/4/18 10:4:29.387
VoiceException:
error.badfetch
Could not compile document: http://petrichor-rain-system.herokuapp.com/vxml/InputData/33/26
Dialog stack trace:
State (Dialog) URL (Document)
-------------- ------------------------------
hello-and-welcome http://petrichor-rain-system.herokuapp.com/vxml/choice/35/26
============================================================
Current Document
============================================================
<?xml version="1.0" encoding="UTF-8"?>
<!--- <vxml version = "2.1" > -->
<!DOCTYPE vxml SYSTEM "http://www.w3.org/TR/voicexml21/vxml.dtd">
<vxml xmlns="http://www.w3.org/2001/vxml"
version="2.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/vxml
http://www.w3.org/TR/2007/REC-voicexml21-20070619/vxml.xsd">
<meta name="maintainer" content="email" />
<property name="inputmodes" value="dtmf" />
<!-- Kasadaka VoiceXML File -->
<form id="hello-and-welcome">
<field name="choice">
<prompt>
<audio src="/uploads/petrichor_hello_welcome_en_AwoXmq3.wav"/>
<audio src="/uploads/pre_choice_option_en.wav"/>
<audio src="/uploads/petrichor_press_one_to_listen_to_explanation_en_L6iqUHW.wav"/>
<audio src="/uploads/post_choice_option_en.wav"/>
<audio src="/uploads/1_en.wav"/>
<audio src="/uploads/pre_choice_option_en.wav"/>
<audio src="/uploads/petrichor_press_two_to_fill_in_collected_data_en_zXRGSby.wav"/>
<audio src="/uploads/post_choice_option_en.wav"/>
<audio src="/uploads/2_en.wav"/>
<audio src="/uploads/pre_choice_option_en.wav"/>
<audio src="/uploads/petrichor_press_three_to_stop_the_call_en_bOL0PDC.wav"/>
<audio src="/uploads/post_choice_option_en.wav"/>
<audio src="/uploads/3_en.wav"/>
</prompt>
<grammar xml:lang="en-US" root = "MYRULE" mode="dtmf">
<rule id="MYRULE" scope = "public">
<one-of>
<item>1</item>
<item>2</item>
<item>3</item>
</one-of>
</rule>
</grammar>
<filled>
<if cond="choice == '1'">
<goto next="/vxml/message/18/26"/>
<elseif cond="choice == '2'" />
<goto next="/vxml/InputData/33/26"/>
<elseif cond="choice == '3'" />
<goto next="/vxml/choice/22/26"/>
<else/>
</if>
</filled>
</field>
</form>
</vxml>
To post the results back to the server, you need to use the submit element and not the goto element.
<submit src="/vxml/InputData/34/8" namelist="DTMF_input" method="post"/>
See details in the VoiceXML specification.

DNN SiteAnalytics.config (Google Tag Manager?) Blocking Save for the DNN HTML Module

We have a site where Google Tag Manager seems to be blocking the saving of changes in the HTML Module. GTM is implemented to spec and otherwise functions the way we expect.
When Google Tag Manager is on the page HTML Module changes do not save. When it's removed changes save properly.
No javascript errors are being thrown. No DNN Admin Log errors are being recorded.
I am searching for answers and hoping someone else has seen this before.
To insert GTM I am using the following as my SiteAnalytics.config and GoogleAnalytics.config:
<!-- SiteAnalytics.config -->
<?xml version="1.0" encoding="utf-8" ?>
<AnalyticsEngineConfig>
<Engines>
<AnalyticsEngine>
<EngineType>DotNetNuke.Services.Analytics.GoogleAnalyticsEngine, DotNetNuke</EngineType>
<ElementId>Head</ElementId>
<InjectTop>True</InjectTop>
<ScriptTemplate>
<![CDATA[
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','[TRACKING_ID]');</script>
<!-- End Google Tag Manager -->
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '[TRACKING_ID]');
</script>
]]>
</ScriptTemplate>
</AnalyticsEngine>
<AnalyticsEngine>
<EngineType>DotNetNuke.Services.Analytics.GoogleAnalyticsEngine, DotNetNuke</EngineType>
<ElementId>Body</ElementId>
<InjectTop>True</InjectTop>
<ScriptTemplate>
<![CDATA[
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=[TRACKING_ID]"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
]]>
</ScriptTemplate>
</AnalyticsEngine>
</Engines>
</AnalyticsEngineConfig>
<!-- GoogleAnalytics.config -->
<?xml version="1.0" encoding="utf-8"?>
<AnalyticsConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Settings>
<AnalyticsSetting>
<SettingName>TrackingId</SettingName>
<SettingValue>GTM-CODEHERE</SettingValue>
</AnalyticsSetting>
<AnalyticsSetting>
<SettingName>UrlParameter</SettingName>
<SettingValue />
</AnalyticsSetting>
<AnalyticsSetting>
<SettingName>TrackForAdmin</SettingName>
<SettingValue>true</SettingValue>
</AnalyticsSetting>
</Settings>
</AnalyticsConfig>
So far I have tried:
removing all tags from GTM except Universal Analytics
setting the GTM code to .defer=true instead of .async=true (see Google Tag Manager delaying window.load?)
minimizing my theme (skin.ascx) by removing my custom javascript
loading GTM on DOMContentLoaded (see JavaScript that executes after page load)
Validating the skin template the W3C's HTML checker
Continuing on today.
This was a strange issue with a stranger solution, so strange that I should probably change the title of the question. Maybe the site with this issue was a one-off but just in case here is the answer.
I discovered that it wasn't Google Analytics code causing the issue but something in DNN that was conflicting between SiteAnalytics.config and the DNN HTML module. In the code snippet below (from SiteAnalytics.config) I was inserting the noscript tag for GTM using this XML:
<AnalyticsEngine>
<EngineType>DotNetNuke.Services.Analytics.GoogleAnalyticsEngine, DotNetNuke</EngineType>
<ElementId>Body</ElementId>
<InjectTop>True</InjectTop>
<ScriptTemplate>
<![CDATA[
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=[TRACKING_ID]"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
]]>
</ScriptTemplate>
</AnalyticsEngine>
I discovered by accident that my issue was resolved when I removed everything between the CDATA tags or the whole CDATA itself. Next I tried reinserting the noscript while changing InjectTop from True to False. That also solved my issue.
So what I know is that injecting anything at the top of the Body using SiteAnalytics.config caused a conflict with the DNN HTML module on this particular site. One would assume that this would be due to some bad HTML on the page or a custom script causing a conflict. However I validated the template through W3C's checker and there were no issues. I also removed all our custom scripts to no avail. So the exact mechanism of the original conflict is unknown but the issue is solved. Below is the updated code:
<!-- SiteAnalytics.config -->
<?xml version="1.0" encoding="utf-8" ?>
<AnalyticsEngineConfig>
<Engines>
<AnalyticsEngine>
<EngineType>DotNetNuke.Services.Analytics.GoogleAnalyticsEngine, DotNetNuke</EngineType>
<ElementId>Head</ElementId>
<InjectTop>True</InjectTop>
<ScriptTemplate>
<![CDATA[
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','[TRACKING_ID]');</script>
<!-- End Google Tag Manager -->
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '[TRACKING_ID]');
</script>
]]>
</ScriptTemplate>
</AnalyticsEngine>
<AnalyticsEngine>
<EngineType>DotNetNuke.Services.Analytics.GoogleAnalyticsEngine, DotNetNuke</EngineType>
<ElementId>Body</ElementId>
<InjectTop>False</InjectTop>
<ScriptTemplate>
<![CDATA[
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=[TRACKING_ID]"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
]]>
</ScriptTemplate>
</AnalyticsEngine>
</Engines>
</AnalyticsEngineConfig>
<!-- GoogleAnalytics.config -->
<?xml version="1.0" encoding="utf-8"?>
<AnalyticsConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Settings>
<AnalyticsSetting>
<SettingName>TrackingId</SettingName>
<SettingValue>GTM-CODEHERE</SettingValue>
</AnalyticsSetting>
<AnalyticsSetting>
<SettingName>UrlParameter</SettingName>
<SettingValue />
</AnalyticsSetting>
<AnalyticsSetting>
<SettingName>TrackForAdmin</SettingName>
<SettingValue>true</SettingValue>
</AnalyticsSetting>
</Settings>
</AnalyticsConfig>

Spring MVC Angular Js integration without template engine

I would like to integrate Spring MVC with Angular JS without any Template Engine
I checked a few answers, but I could not resolve it . Below I have listed Xml,Controller and Html files. What I am missing here exactly?
app-Servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<annotation-driven />
<context:component-scan base-package="com.angular.app" />
<resources mapping="/views/**" location="/WEB-INF/views/" />
<resources mapping="/resources/**" location="/resources/" />
<beans:bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<beans:property name="order" value="1" />
<beans:property name="mediaTypes">
<beans:map>
<beans:entry key="html" value="text/html" />
</beans:map>
</beans:property>
</beans:bean>
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="order" value="2" />
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value="" />
</beans:bean>
</beans:beans>
Controller
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate);
return "home.html";
}
#RequestMapping(value="/app/welcome",method = RequestMethod.GET)
public #ResponseBody String welcome() {
logger.info("entering into original controller");
System.out.println("entering into original controller");
String text="Hello World!!!! Welcome";
return text;
}
home.html
<html>
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body>
<div ng-app="">
<div>
Name: <input type="text" ng-model="name">
</div>
<p ng-bind="name"></p>
<div ng-controller="helloworldcontroller">
<h1>{{title}}</h1>
</div>
</div>
<script>
function helloworldcontroller($scope, $http) {
$http.get("http://localhost:8080/app/welcome").success(
function(response) {
$scope.title = response;
alert("sucess");
});
}
</script>
</body>
</html>
I'm working on some projects using the architecture Spring MVC + AngularJs and can give you feedback about:
You are trying to control the routes of html pages through the Spring MVC Contollers and I think this is not the best approach, since the AngularJs has its own engine to control routes and pages through the ng-route or ui-router.
In architectures of my projects work with a Spring MVC project providing a whole REST API to be consumed by a web AngularJs application.
The project structure is as follows:
parent-maven-project:
|_project-core: Have all bussiness logic, data source config, persistence config, Services, Repositories, Entities, etc.
|_project-web: Have a angularJs App (that controls the html pages routing using ui-router), API REST (Spring MVC Controllers) to be consumed and give the business layer access (project-core).
|_project-ear: Pack core and web projects to deploy on JBoss EAP 6.2
In Spring MVC REST layer (project-web) | set up a Spring OAuth2 server that is used to authenticate users and make the session & access control through Spring Security. When the user logs into the application, the angularjs application receives an access token Bearer that is used to make the user requests during all the time that he remain logged in. All REST services are in request scope, are stateless, then the token is used to retrieve the Spring Security session and make all user access validation.

HTTP method POST is not supported by this URL app engine

I keep getting the following error:
HTTP method POST is not supported by this URL
when trying to build on my local machine using google app engine.
The code in ShowJSPServlet.java file:
package helloJSP;
import java.io.IOException;
import javax.servlet.http.*;
public class HelloJSPServlet extends HttpServlet
{
#Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
resp.setContentType("text/html");
resp.getWriter().println("Hello, world");
}
}
My web.xml file is:
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<servlet>
<servlet-name>ShowJSP</servlet-name>
<servlet-class>helloJSP.ShowJSPServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShowJSP</servlet-name>
<url-pattern>/ShowName</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>hello.jsp</welcome-file>
</welcome-file-list>
</web-app>
The hello.jsp file contents are:
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<form id="mainform" method="post" action="/ShowName">
<div>
Name: <input id="url" type="text" size="100"/>
<input type="submit" id="gobtn" value="Go" style="width: 70px"/>
</div>
</form>
</body>
</html>
This is the first time I am developing in JSP technology. What am I missing?
One problem is in your web.xml:
<servlet-class>helloJSP.ShowJSPServlet</servlet-class>
should be
<servlet-class>helloJSP.HelloJSPServlet</servlet-class>
Does that help?

Resources