The documentation for ServiceNow’s SAML setup is the best that it has ever been. More and more customers are able to set up SAML correctly without having to engage outside help. That being said, what happens when you set up SAML and things just aren’t working out correctly?

When debugging SAML issues in ServiceNow, there are two things I recommend:
1. Use the Debug Log statements in ServiceNow
2. Use a network tracer such as those built into Chrome & Firefox, or Fiddler for Windows users.

This article covers the first recommended action, following the Debug Log statements inside ServiceNow.

Enabling and Viewing Debug Logging


First, you will need to make sure you have Debug Logging enabled for your SAML plugin. This can be done by browsing to the properties page and checked the Debug Logging checkbox.

SAML Debug Logging Property

This will ensure that the SAML debug statements will be logged to your instance’s System Log.

Now, to browse your System Log, simply go to “System Logs -> All”. I like to sort my logs on creation date where the create time on the filter for the log is after the last statement before I attempt to do a SAML login.

Filtering the System Log

Typical Log Statements

The following is typical log output for a successful SAML authentication:

This line just shows the SAML processing URL (the one that the IdP will send the Response to when it is done) and also the calculated base URL of the instance for use later on in the script.

1
Stripping down the serviceURL: https://myinstance.service-now.com/navpage.do to a base URL of: https://myinstance.service-now.com

Now, in the case of this example, we were using deep linking. This means that we clicked on a non-home page link an after authentication we want to be redirected to that specific page. In order for SAML to trigger on that, the url needs to use “nav_to.do”. This is what link we were using in this example:

https://myinstance.service-now.com/nav_to.do?uri=incident.do?sys_id=46e482d9a9fe198101d3e3f3e2a14459

In this next log statement, we analyze the destination URL to see if there is deep linking. The request URI is the page that is being accessed, and the “Query String” statement is the parameters on that URL.

Based on the URI an Query String, the script will attempt to use Deep Linking since it found query string parameters.

1
2
3
4
5
6
7
requestURI: /nav_to.do

Query String (qs): uri=incident.do?sys_id=46e482d9a9fe198101d3e3f3e2a14459

URI Parameter: incident.do?sys_id=46e482d9a9fe198101d3e3f3e2a14459

There may be Deep Linking involved with this SAML request

If we were not deep linking, then most of those statements above would be empty, or show a “null” value.

Next SAML will try to generate a Relay State parameter. This is sent to the IdP. Once authentication is complete on the Identity Provider’s side, it will redirect back to ServiceNow and it will post this Relay State with the SAML Response. This lets ServiceNow know where to redirect the browser once the login is completed.

The SAML plugin will URL encode the Relay State value since this is going on the URL that we send to the IdP. We don’t want any special URL characters to interfere with the base URL redirection that we are doing.

If there is no relay state, then a default relay state is generated. Out of the box, this relay state will be the main page of your instance.

1
Generating a Relay State of: https://myinstance.service-now.com/nav_to.do?uri=incident.do%3fsys_id%3d46e482d9a9fe198101d3e3f3e2a14459

Once the Relay State is generated, the system will generate an AuthnRequest XML document. This document will then be DEFLATED, base64 encoded, and URL Encoded and added to the URL as a “SAMLRequest” parameter. The log will show both the XML document for the request, and the full URL with SAMLRequest and RelayState that we will use for redirection to the IdP.

1
2
3
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://myinstance.service-now.com/navpage.do" ForceAuthn="false" ID="SNC04bc590a4d03b653d77fb07a88a345eb" IsPassive="false" IssueInstant="2012-05-09T15:21:52.974Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" ProviderName="https://myinstance.service-now.com/navpage.do" Version="2.0"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://myinstance.service-now.com</saml2:Issuer><saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" SPNameQualifier="https://myinstance.service-now.com/navpage.do"/><saml2p:RequestedAuthnContext Comparison="exact"><saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef></saml2p:RequestedAuthnContext></saml2p:AuthnRequest>

Redirecting to: https://idp.ssocircle.com:443/sso/SSORedirect/metaAlias/ssocircle?SAMLRequest=nVPBcpswEP0VRneDwKa2NcYzlEynnklTYtwechPSYmsGJKoVjvP3BeIkPjTuJNfdp9333j6tkDd11LK0cwe9hT8doPNOTa2RPXcS0lnNDEeFTPMGkDnBivTHLYt8ylprnBGmJl6KCNYpozOjsWvAFmCPSsCv7W1CDs61LAi4LY0uzZN%2FMA1Ijb6xexYuKI0CzY8t34MvDfG%2BGStgJJSQitcIxNvcJKS4y%2BisFPGS8pmk0%2FJLPJXzeVXSOV8s%2BHQWQ9kDMeeI6ghvTxE72Gh0XLuERDSMJjSe0OUujFkUsjjyl%2FPZA%2FHys5SvSkul99d1l88gZN93u3yS%2Fyx244CjkmDvevRHJf8Gi713PT%2BfkvVqtJ6NzO3lNa6T4i8nIOv%2Fbl8FlzvOG1s2cN%2Fc5KZW4slL69o8Zha46%2FU428F4moa792mEfjhWlJxUI5RBw1WdSmkBkXhFPmy473itKgX2gzYFrzzPSQU5xqSPnIOT8zLTtNwqHIyEExfu1cpLWFb3Rm2h%2BpSxV2GCiWF2Xx5C%2BGisHEIFoue5s1xja6x7Mf5fjNbn5jv63tqXv3X9Fw%3D%3D&RelayState=https://myinstance.service-now.com/nav_to.do?uri=incident.do%3fsys_id%3d46e482d9a9fe198101d3e3f3e2a14459

Here, the user’s browser is redirected to the IdP for authentication. Logging is now the responsibility of the IdP. We will not receive any more log messages in the SAML process until the IdP processed the authentication and redirects the user back to ServiceNow with the SAML response document and relay state.

Logging resumes as we get the response back from the IdP. Before we act on the response, we first do a number of validation and security checks to ensure we can trust this SAML response.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Response object created

Issue Instant: 2012-05-09T15:22:01.000Z

Signature Reference ID: s2e460726688ab83e1875101549b1ad03d4af8837a

certificate Issuer DN: CN=CA, O=SSOCircle, C=DE

Public key created

Signature not in response, attempting to get signature from assertion

Got signature

<?xml version="1.0" encoding="UTF-8"?><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="#s255bdf815a7493479752d610386841f58ac677211">
<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"/>
<ds:DigestValue>gtpu2XT1bLHTMkpQeTpiunMO1Yo=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
mCvayhe1KJaLy/o1D9kIpL1t99rTRdedpLw7KQIy9T/siDytBOgo42yr91sfcG2dc7AX/JuQpQh8
HGL63H0ZgadVEp0DlErc8jetkje3o6DgKd/Cw0HAMuJujhh83cFthkQDgX8xg9L7LUqgptqHds/5
ssLyVvCok3dJYyImPX8=
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIICjDCCAXSgAwIBAgIFAJRvxcMwDQYJKoZIhvcNAQEEBQAwLjELMAkGA1UEBhMCREUxEjAQBgNV
BAoTCVNTT0NpcmNsZTELMAkGA1UEAxMCQ0EwHhcNMTEwNTE3MTk1NzIxWhcNMTYwODE3MTk1NzIx
WjBLMQswCQYDVQQGEwJERTESMBAGA1UEChMJU1NPQ2lyY2xlMQwwCgYDVQQLEwNpZHAxGjAYBgNV
BAMTEWlkcC5zc29jaXJjbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbzDRkudC/
aC2gMqRVVaLdPJJEwpFB4o71fR5bnNd2ocnnNzJ/W9CoCargzKx+EJ4Nm3vWmX/IZRCFvrvy9C78
fP1cmt6Sa091K9luaMAyWn7oC8h/YBXH7rB42tdvWLY4Kl9VJy6UCclvasyrfKx+SR4KU6zCsM62
2Kvp5wW67QIDAQABoxgwFjAUBglghkgBhvhCAQEBAf8EBAMCBHAwDQYJKoZIhvcNAQEEBQADggEB
AJ0heua7mFO3QszdGu1NblGaTDXtf6Txte0zpYIt+8YUcza2SaZXXvCLb9DvGxW1TJWaZpPGpHz5
tLXJbdYQn7xTAnL4yQOKN6uNqUA/aTVgyyUJkWZt2giwEsWUvG0UBMSPS1tp2pV2c6/olIcbdYU6
ZecUz6N24sSS7itEBC6nwCVBoHOL8u6MsfxMLDzJIPBI68UZjz3IMKTDUDv6U9DtYmXLc8iMVZBn
cYJn9NgNi3ghl9fYPpHcc6QbXeDUjhdzXXUqG+hB6FabGqdTdkIZwoi4gNpyr3kacKRVWJssDgak
eL2MoDNqJyQ0fXC6Ze3f79CKy/WjeU5FLwDZR0Q=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>

Signature is valid.

After the SAML response is validated and trusted by the system, we will process it and attempt to login using the nameId token passed back to use from the IdP.

The log will display the NameID token received from the IdP. We will match this up with a real user in our system and establish a valid ServiceNow session.

1
2
3
4
5
NameID:john.user@service-now.com

SAML2 NameID: john.user@service-now.com

SAML2 SessionIndex: s2edd20d41d9a7f3fcdb02360877e9d8cfa313ac11

At this point, we redirect the user’s browser to the page indicated by the RelayState that was passed back to us from the IdP. This should be the same relay state that we sent to the IdP to hold on for us.

1
We will be redirecting user to the RelayState: https://myinstance.service-now.com/nav_to.do?uri=incident.do?sys_id=46e482d9a9fe198101d3e3f3e2a14459

The user is then authenticated and redirected to the relay state’s URL.