By: Will Beacon user 23 Jan 2018 at 8:13 a.m. CST

4 Responses
Will Beacon gravatar
We're testing out deploying Gluu as a CAS server, and intergating one of our existing applications with it. We've run through the documentation, referenced [here](https://gluu.org/docs/ce/3.1.1/admin-guide/cas/). The only difference in our setup is that we want to release the attributes transientId, LastName, and employeeNumber. As per the documentation, calling https://your.gluu.host/idp/profile/cas/serviceValidate does not seem to be returning with a ticket validation response, we're just seeing 'E_TICKET_NOT_SPECIFIED'. Checking the idp-process.log file at this point gives the following warning and info... ``` 2018-01-23 13:59:21,326 - WARN [org.opensaml.profile.action.impl.LogEvent:105] - A non-proceed event occurred while processing the request: TicketNotSpecified 2018-01-23 13:59:21,365 - INFO [Shibboleth-Audit.SSO:241] - 20180123T135921Z|||E_SERVICE_NOT_SPECIFIED|https://www.apereo.org/cas/protocol/serviceValidate||||||||E_TICKET_NOT_SPECIFIED| ``` We have our app redirecting to https://ourGluuServer/idp/profile/cas/login When the app redirects we're getting the 'Web Login Service - Unsupported Request' screen with the application you have access is not registered for use with the service message. The idp-process.log then logs... ``` 2018-01-23 14:04:55,018 - WARN [net.shibboleth.idp.profile.impl.SelectProfileConfiguration:111] - Profile Action SelectProfileConfiguration: Profile https://www.apereo.org/cas/protocol/login is not available for RP configuration shibboleth.UnverifiedRelyingParty (RPID https://10.234.3.48/Restricted/AdministratorsRoleOnly/) 2018-01-23 14:04:55,028 - WARN [org.opensaml.profile.action.impl.LogEvent:105] - A non-proceed event occurred while processing the request: InvalidProfileConfiguration 2018-01-23 14:04:55,029 - INFO [Shibboleth-Audit.SSO:241] - 20180123T140455Z||||https://www.apereo.org/cas/protocol/login||||||||| ``` Clearly something wrong with the CAS configuration on our Gluu server or TR setup. I've tried making changes to the 'fake' SAML TR we've setup (changes to the SP metadata file) with no success, so I'm unsure as to how to identify the underlying issue. Based on the log snippets, are you able to suggest a few areas to target first? Any assistance would be greatly appreciated!

By Aliaksandr Samuseu staff 23 Jan 2018 at 8:53 a.m. CST

Aliaksandr Samuseu gravatar
Hi, Will. The only purpose "Fake TR" serves is to manage list of attributes you want to be available in CAS flows. It doesn't affect which attribute is released to what CAS client, only defines a full list that will be available to CAS server. Protocol details are provided [here](https://apereo.github.io/cas/5.0.x/protocol/CAS-Protocol-V2-Specification.html). Specifically, flow starts with request to `/login` endpoint like this `https://server/cas/login?service=http%3A%2F%2Fwww.service.com`. If you get "service is not known" type of error, something is most likely wrong with the way you defined your service in `cas-protocol.xml.vm` template file. >As per the documentation, calling https://your.gluu.host/idp/profile/cas/serviceValidate does not seem to be returning with a ticket validation response, we're just seeing 'E_TICKET_NOT_SPECIFIED'. You need to supply ticket, of course. And judging by what you said, you can't get the ticket as your service is not known to CAS server. What CAS client do you use? Please also provide your edited `cas-protocol.xml.vm` and `attribute-filter.xml.vm` files, plus `/opt/shibboleth-idp/conf/attribute-resolver.xml` file. Then also create a HAR file with capture of the full failing flow; [here are the steps](https://www.inflectra.com/support/knowledgebase/kb254.aspx) - please use Firefox for that, Chrome's HARs are flawed; also don't forget to set "Persist log" checkbox in the console to save everything, not just the recently loaded page. I'm also not sure why you need to issue `transientId` in CAS flow, that hasn't been yet tested so I can't say whether it's possible.

By Will Beacon user 25 Jan 2018 at 10:47 a.m. CST

Will Beacon gravatar
Thanks for getting back to me Aliaksandr. We've run through the documentation again, and setup the attributes on the fake TR, and in attribute-filter.xml.vm as per the documentation, so transientId _shouldn't_ be returned now. We're just using Email, FirstName, LastName and Username as described. Here are the files.... cas-protocol.xml.vm ``` <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="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 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd" default-init-method="initialize" default-destroy-method="destroy"> <!-- | The CAS service registry defines verified relying parties by endpoint URI. | The default implementation treats the ID of each entry as a regular expression defining a logical group of | services whose URIs match the expression. | | This bean is reloaded periodically according to %{idp.home}/conf/services.properties. --> <bean id="reloadableServiceRegistry" class="%{idp.cas.serviceRegistryClass:net.shibboleth.idp.cas.service.PatternServiceRegistry}"> <property name="definitions"> <list> <!-- <bean class="net.shibboleth.idp.cas.service.ServiceDefinition" c:regex="https://([A-Za-z0-9_-]+\.)*example\.org(:\d+)?/.*" p:group="proxying-services" p:authorizedToProxy="true" p:singleLogoutParticipant="true" /> <bean class="net.shibboleth.idp.cas.service.ServiceDefinition" c:regex="http://([A-Za-z0-9_-]+\.)*example\.org(:\d+)?/.*" p:group="non-proxying-services" p:authorizedToProxy="false" / --> <bean class="net.shibboleth.idp.cas.service.ServiceDefinition" c:regex="https:\/\/([A-Za-z0-9_-]+\.)*example\.org(:\d+)?\/.*" p:group="institutional-services" p:authorizedToProxy="false" /> </list> </property> </bean> <!-- | Advanced CAS configuration. | | Override default CAS components by creating aliases to custom components where the alias | is the same as the default component bean ID. --> <!-- <bean id="cas.CustomTicketService" class="org.example.idp.cas.CustomTicketService" /> <alias name="cas.CustomTicketService" alias="cas.TicketService" /> <bean id="cas.CustomProxyAuthenticator" class="org.example.idp.cas.CustomProxyAuthenticator" /> <alias name="cas.CustomProxyAuthenticator" alias="cas.ProxyAuthenticator" /> --> </beans> ``` attribute-filter.xml.vm... ``` <?xml version="1.0" encoding="UTF-8"?> <AttributeFilterPolicyGroup id="ShibbolethFilterPolicy" xmlns="urn:mace:shibboleth:2.0:afp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mace:shibboleth:2.0:afp http://shibboleth.net/schema/idp/shibboleth-afp.xsd"> #foreach( $trustRelationship in $trustParams.trusts ) #set ($isFederation = ($trustParams.trustEntityIds.get($trustRelationship.inum).size() > 1)) #if ($trustParams.trustIds.get($trustRelationship.inum)) <!-- Release some attributes to an SP. --> <AttributeFilterPolicy id="SiteApp$trustParams.trustIds.get($trustRelationship.inum)"> #if ($trustRelationship.isResearchBundle()) <PolicyRequirementRule xsi:type="AND"> <Rule xsi:type="EntityAttributeExactMatch" attributeName="http://macedir.org/entity-category" attributeValue="http://refeds.org/category/research-and-scholarship"/> <Rule xsi:type="EntityAttributeExactMatch" attributeName="http://macedir.org/entity-category" attributeValue="http://id.incommon.org/category/registered-by-incommon"/> #if ($isFederation) <Rule xsi:type="OR"> #foreach( $entityId in $trustParams.trustEntityIds.get($trustRelationship.inum) ) <Rule xsi:type="Requester" value="$entityId" /> #end </Rule> #else <Rule xsi:type="Requester" value="$trustParams.trustEntityIds.get($trustRelationship.inum).get(0)" /> #end </PolicyRequirementRule> #else #if ($isFederation) <PolicyRequirementRule xsi:type="OR"> #foreach( $entityId in $trustParams.trustEntityIds.get($trustRelationship.inum) ) <Rule xsi:type="Requester" value="$entityId" /> #end </PolicyRequirementRule> #else <PolicyRequirementRule xsi:type="Requester" value="$trustParams.trustEntityIds.get($trustRelationship.inum).get(0)" /> #end #end #foreach( $attribute in $trustRelationship.releasedCustomAttributes ) <AttributeRule attributeID="$attribute.name"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> #end </AttributeFilterPolicy> #end #end #foreach( $trustRelationship in $trustParams.deconstructed ) <AttributeFilterPolicy id="FederatedSiteApp$trustParams.deconstructedIds.get($trustRelationship.entityId)"> <PolicyRequirementRule xsi:type="Requester" value="$trustRelationship.entityId" /> #foreach( $attribute in $trustRelationship.releasedCustomAttributes ) <AttributeRule attributeID="$attribute.name"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> #end </AttributeFilterPolicy> #end <AttributeFilterPolicy id="ManualCASFilterRule1"> <PolicyRequirementRule xsi:type="RequesterRegex" regex="^https:\/\/([A-Za-z0-9_-]+\.)*example\.org(:\d+)?\/.*$" /> <AttributeRule attributeID="mail"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="givenName"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="sn"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="uid"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> </AttributeFilterPolicy> </AttributeFilterPolicyGroup> ``` attribute-resolver.xml.... ``` <?xml version="1.0" encoding="UTF-8"?> <resolver:AttributeResolver xmlns:resolver="urn:mace:shibboleth:2.0:resolver" xmlns:ad="urn:mace:shibboleth:2.0:resolver:ad" xmlns:dc="urn:mace:shibboleth:2.0:resolver:dc" xmlns:enc="urn:mace:shibboleth:2.0:attribute:encoder" xmlns:sec="urn:mace:shibboleth:2.0:security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd urn:mace:shibboleth:2.0:resolver:ad http://shibboleth.net/schema/idp/shibboleth-attribute-resolver-ad.xsd urn:mace:shibboleth:2.0:resolver:dc http://shibboleth.net/schema/idp/shibboleth-attribute-resolver-dc.xsd urn:mace:shibboleth:2.0:attribute:encoder http://shibboleth.net/schema/idp/shibboleth-attribute-encoder.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd"> <!-- ========================================== --> <!-- Attribute Definitions --> <!-- ========================================== --> #foreach( $attribute in $attrParams.attributes ) #if( ! ($attribute.name.equals('transientId') or $attribute.name.equals('persistentId') ) ) #if($attribute.name.equals('eppnForNIH')) <resolver:AttributeDefinition id="eduPersonPrincipalName" xsi:type="ad:Scoped" scope="%{idp.scope}" sourceAttributeID="uid"> <resolver:Dependency ref="siteLDAP" /> <resolver:AttributeEncoder xsi:type="enc:SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" friendlyName="eduPersonPrincipalName" encodeType="false" /> </resolver:AttributeDefinition> #else <resolver:AttributeDefinition xsi:type="ad:Simple" id="$attribute.name" sourceAttributeID="$attribute.name"> <resolver:Dependency ref="siteLDAP" /> <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="$attrParams.attributeSAML2Strings.get($attribute.name)" friendlyName="$attribute.name" encodeType="false" /> </resolver:AttributeDefinition> #end #end #end <!-- ========================================== --> <!-- Data Connectors --> <!-- ========================================== --> <resolver:DataConnector id="siteLDAP" xsi:type="dc:LDAPDirectory" ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}" baseDN="%{idp.attribute.resolver.LDAP.baseDN}" principal="%{idp.attribute.resolver.LDAP.bindDN}" principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}" useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"> <dc:FilterTemplate> <![CDATA[ (uid=$requestContext.principalName) ]]> </dc:FilterTemplate> <!-- <dc:ReturnAttributes>%{idp.attribute.resolver.LDAP.returnAttributes}</dc:ReturnAttributes> --> <dc:StartTLSTrustCredential id="LDAPtoIdPCredential" xsi:type="sec:X509ResourceBacked"> <sec:Certificate>%{idp.attribute.resolver.LDAP.trustCertificates}</sec:Certificate> </dc:StartTLSTrustCredential> </resolver:DataConnector> </resolver:AttributeResolver> ``` Here is the har file.... [Archive 18-01-25 16-29-31.har](https://www.dropbox.com/s/8ew4x29c1er9uoe/Archive%2018-01-25%2016-29-31.har?dl=0) We're using an open source CAS client called [DotNetCasClient](https://github.com/apereo/dotnet-cas-client). I've plugged the project/dll into the Example Web Application. Clicking a secure link is redirecting to the idp/profile/cas/login on our Gluu server, but we're still getting the Web Login Service - Unsupported Request screen, with the same WARN and INFO log entries being written out to the idp-process.log file. I'm sure it's something obvious we've missed during the configuration process! Many thanks.

By Aliaksandr Samuseu staff 25 Jan 2018 at 5:17 p.m. CST

Aliaksandr Samuseu gravatar
Hi, Will. You can use [this tool](https://toolbox.googleapps.com/apps/har_analyzer/) to view the HAR file yourself, to see what's going on. Here is request url your client used: ``` https://uktwk-vt-glu01/idp/profile/cas/login?service=https%3a%2f%2f10.234.3.48%2fCASClient%2fRestricted%2fAdministratorsRoleOnly%2f ``` Whatever this service string - `https://10.234.3.48/CASClient/Restricted/AdministratorsRoleOnly/` - in it represents, it doesn't seem to be present in your `cas-protocol.xml.vm`. The regexp your service's definition uses there - `c:regex="https:\/\/([A-Za-z0-9_-]+\.)*example\.org(:\d+)?\/.*"` - doesn't seem to match what you send to server. You need to correct this discrepancy first.

By Will Beacon user 29 Jan 2018 at 6:34 a.m. CST

Will Beacon gravatar
Aliaksandr - thanks very much! A complete oversight on my part. We've altered the cas-protocol.xml.vm file with a correct regex for the request url and the redirect to Gluu login is working. Thanks for pointing out the issue.