duosecurity / duo_confluence

Duo two-factor authentication for Confluence.
14 stars 15 forks source link

Every request goes to Duo Auth / Auths in console #1

Closed tuctboh closed 11 years ago

tuctboh commented 11 years ago

Hi,

I'm wondering if this is a "feature" or an issue. Every request appears to go back to Duo for authentication. EG:

[11:45:14.887] GET http://MYCONFLUENCESERVER.example.com:8090/display/RES/Employee+Contact+Information [HTTP/1.1 302 Moved Temporarily 47ms] [11:45:14.981] GET http://MYCONFLUENCESERVER.example.com:8090/plugins/servlet/duologin?duo.request.key=TX|dHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTM4MTQ=|cc90e7d5b2612bb97c582b7392afb986b5e20597:APP|dHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTcxMTQ=|2190aef4d7acc486c197544ea3a0c91222256ef3&duo.host.key=myduosite.example.com&duo.originalurl.key=%2Fpages%2Fviewpage.action%3FspaceKey%3DRES%26title%3DEmployee%2BContact%2BInformation [HTTP/1.1 200 OK 30ms] [11:45:15.403] GET https://myduosite.example.com/frame/web/v1/auth?tx=TX%7CdHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTM4MTQ%3D%7Ccc90e7d5b2612bb97c582b7392afb986b5e20597&parent=http%3A%2F%2FMYCONFLUENCESERVER.example.com%3A8090%2Fplugins%2Fservlet%2Fduologin%3Fduo.request.key%3DTX%7CdHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTM4MTQ%3D%7Ccc90e7d5b2612bb97c582b7392afb986b5e20597%3AAPP%7CdHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTcxMTQ%3D%7C2190aef4d7acc486c197544ea3a0c91222256ef3%26duo.host.key%3Dmyduosite.example.com%26duo.originalurl.key%3D%252Fpages%252Fviewpage.action%253FspaceKey%253DRES%2526title%253DEmployee%252BContact%252BInformation [HTTP/1.1 200 OK 468ms] [11:45:16.002] POST http://MYCONFLUENCESERVER.example.com:8090/plugins/servlet/duologin?duo.originalurl.key=%2Fpages%2Fviewpage.action%3FspaceKey%3DRES%26title%3DEmployee%2BContact%2BInformation [HTTP/1.1 302 Moved Temporarily 35ms] [11:45:16.085] GET http://MYCONFLUENCESERVER.example.com:8090/pages/viewpage.action?spaceKey=RES&title=Employee+Contact+Information&sig_response=AUTH%7CdHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTM1NzU%3D%7C414565e3a6c6669ec27234c70f818b12febde2e7:APP%7CdHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTcxMTQ%3D%7C2190aef4d7acc486c197544ea3a0c91222256ef3 [HTTP/1.1 200 OK 8509ms]

[11:45:25.407] GET http://MYCONFLUENCESERVER.example.com:8090/s/en_GB/3390/fe254e109a6fb9b541d2f5e2946c3766ed81e099.67/2.1.0/_/download/batch/com.appfusions.confluence.google.confluence-google-docs:googleDocMacroCss/com.appfusions.confluence.google.confluence-google-docs:googleDocMacroCss.css [HTTP/1.1 200 OK 39ms] [11:45:25.408] GET http://MYCONFLUENCESERVER.example.com:8090/download/attachments/589916/ctowbin-9102-pp-photo.jpg?version=1&modificationDate=1351187310610 [HTTP/1.1 200 OK 152ms] [11:45:26.534] GET http://MYCONFLUENCESERVER.example.com:8090/rest/prototype/1/i18n?locale=en_GB&pluginKeys=com.atlassian.confluence.keyboardshortcuts&pluginKeys=com.atlassian.plugins.editor [HTTP/1.1 200 OK 114ms] [11:45:26.536] GET http://MYCONFLUENCESERVER.example.com:8090/rest/prototype/1/i18n/com.atlassian.confluence.plugins.confluence-like?locale=en_GB [HTTP/1.1 304 Not Modified 34ms] [11:45:26.537] GET http://MYCONFLUENCESERVER.example.com:8090/rest/prototype/1/i18n/com.atlassian.confluence.plugins.share-page?locale=en_GB [HTTP/1.1 304 Not Modified 67ms] [11:45:26.539] GET http://MYCONFLUENCESERVER.example.com:8090/rest/mywork/latest/status/notification/count [HTTP/1.1 200 OK 88ms] [11:45:26.588] GET http://MYCONFLUENCESERVER.example.com:8090/rest/likes/1.0/content/1540231/likes [HTTP/1.1 200 OK 33ms] [11:45:26.590] GET http://MYCONFLUENCESERVER.example.com:8090/rest/likes/1.0/content/1540231/comment-likes [HTTP/1.1 200 OK 38ms] [11:45:27.257] POST http://MYCONFLUENCESERVER.example.com:8090/plugins/editor-loader/editor.action [HTTP/1.1 200 OK 488ms] [11:45:27.425] OPTIONS http://confluence.ame.admarketplace.net:8090/rest/calendar-services/1.0/tips [233ms] [11:45:27.450] GET http://MYCONFLUENCESERVER.example.com:8090/plugins/macrobrowser/browse-macros.action [0ms] [11:45:28.751] GET http://MYCONFLUENCESERVER.example.com:8090/display/RES/Floorplan [HTTP/1.1 302 Moved Temporarily 36ms] [11:45:28.755] GET http://MYCONFLUENCESERVER.example.com:8090/plugins/servlet/duologin?duo.request.key=TX|dHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTM4Mjg=|9551dca66ff2da02a613b86bca87f0aaf575e02b:APP|dHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTcxMjg=|ceb8af07ad4a12da3c3cc12aae6e9f1c9b9aa630&duo.host.key=myduosite.example.com&duo.originalurl.key=%2Fpages%2Fviewpage.action%3FspaceKey%3DRES%26title%3DFloorplan [HTTP/1.1 200 OK 37ms] [11:45:28.924] GET https://myduosite.example.com/frame/web/v1/auth?tx=TX%7CdHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTM4Mjg%3D%7C9551dca66ff2da02a613b86bca87f0aaf575e02b&parent=http%3A%2F%2FMYCONFLUENCESERVER.example.com%3A8090%2Fplugins%2Fservlet%2Fduologin%3Fduo.request.key%3DTX%7CdHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTM4Mjg%3D%7C9551dca66ff2da02a613b86bca87f0aaf575e02b%3AAPP%7CdHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTcxMjg%3D%7Cceb8af07ad4a12da3c3cc12aae6e9f1c9b9aa630%26duo.host.key%3Dmyduosite.example.com%26duo.originalurl.key%3D%252Fpages%252Fviewpage.action%253FspaceKey%253DRES%2526title%253DFloorplan [HTTP/1.1 200 OK 120ms] [11:45:29.424] POST http://MYCONFLUENCESERVER.example.com:8090/plugins/servlet/duologin?duo.originalurl.key=%2Fpages%2Fviewpage.action%3FspaceKey%3DRES%26title%3DFloorplan [HTTP/1.1 302 Moved Temporarily 32ms] [11:45:29.546] GET http://MYCONFLUENCESERVER.example.com:8090/pages/viewpage.action?spaceKey=RES&title=Floorplan&sig_response=AUTH%7CdHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTM1ODg%3D%7Cb60d630d7450211e62fd65a09f3602965a18feb4:APP%7CdHVjQGFkbWFya2V0cGxhY2UuY29tfERJNk1YUjdLUU9DSjFWV1hSTVc3fDEzNzQ4NTcxMjg%3D%7Cceb8af07ad4a12da3c3cc12aae6e9f1c9b9aa630 [HTTP/1.1 200 OK 8431ms]

Our console also shows:

Today 11:27 AM EDT MYUSER Confluence Trusted Device SUCCESS IP Today 11:27 AM EDT MYUSER Confluence Trusted Device SUCCESS IP Today 11:27 AM EDT MYUSER Confluence Trusted Device SUCCESS IP Today 11:26 AM EDT MYUSER Confluence Trusted Device SUCCESS IP Today 11:26 AM EDT MYUSER Confluence Trusted Device SUCCESS IP Today 11:26 AM EDT MYUSER Confluence Trusted Device SUCCESS IP Today 11:26 AM EDT MYUSER Confluence Trusted Device SUCCESS IP Is this normal, or is there something maybe not set up correctly.

Thanks, Tuc

kra commented 11 years ago

Hi Tuc, you should only be sent to Duo for authentication once per user/session, after you first authenticate locally with Confluence.

I'm seeing 19 or so requests, two of which are going to Duo for authentication, is this what you're seeing? It looks like

/display/RES/Employee+Contact+Information /display/RES/Floorplan

are requiring Duo authentications here, while the rest aren't.

If all of these requests are for the same user and session, then yes, this is one more Duo request than expected. But if these are separate users, then this would be expected. Those Duo interactions are redirects to the page with the Duo frame, so they're obvious to the user - what are you seeing in your browser?

tuctboh commented 11 years ago

The only pages I navigated to in that instance were Employee Contact Information and Floorplan. I saw the "Duo Authentication" page inbetween getting from the main page saying "Logging you in...", and the Employee Contact Information, then again between that and the FloorPlan with "Logging you in...", and then again between that and the next page I went to saying "Logging you in...". Every page I go to constantly puts up the Duo Authentication page, says "Logging you in..." and continues.

(This is a demo server no one knows about, so its only me on it)

kra commented 11 years ago

OK, thanks. That is not the expected behavior. Is there any reason why you wouldn't be storing a valid Confluence session cookie in your browser (JSESSIONID), like changing the session timeout, or other edits to web.xml, or your clock being off? What version of Confluence and browser are you using? Are you using Crowd or any plugins?

It's looking like only pages in the RES space are requiring a Duo authentication in this log excerpt (not REST calls or images), does this happen if you visit the root URL or /dashboard.action directly?

tuctboh commented 11 years ago

Hi,

Checking the JSESSIONID, its the same each time.. No changes to session timeout. No other edits to web.xml. Clock matches server. Browser is both "Google Chrome 28.0.1500.72 (Official Build 211400) m" and "IE 10.0.7" on Windows and something FireFox on Linux. Confluence is 4.3.1 . Using LDAP, not sure the plugins. Root = Yes. /dashboard.action = No.

Tuc

kra commented 11 years ago

OK, thanks for the info, I'll try to reproduce this. This Confluence version should be supported, but I don't know if I have tested 4.3.1 in particular, and Confluence has made behavior changes in point releases - are you able to upgrade to a more recent stable 5.1.x Confluence? It's also interesting that this doesn't happen on the landing page, maybe the RES space has something to do with it? Would you be able to create a temp space with a page in it and see if it happens when you visit that URL?

tuctboh commented 11 years ago

Hi, Can't go to 5.1.X, sorry. I went to /display/home, /display/ADOPS, /display/SOCUL and all paused at the DUO authentication. I haven't added a new space though, those were existing too.

kra commented 11 years ago

Hi Tuc, I haven't been able to reproduce this using Confluence 4.3.1 running on Centos 6.3, either with an LDAP user or a local user. I also tried various combinations of space/page permissions and user groups, with no difference.

Do you want to send me your web.xml? If the configuration isn't put in the right order it can have weird behavior. You didn't happen to upgrade Confluence, or the Duo plugin, from a previous version, did you?

For some reason, you're successfully authing with Duo (since you're viewing the page content), but that isn't being recorded in your Confluence session, so Confluence is sending you back to auth again. It's interesting that /dashboard.action only the pages in the spaces are causing this to happen, that's why I suggested making a new space and trying that. But I wasn't able to reproduce this by tweaking perms.

tuctboh commented 11 years ago

Hi, Haven't upgraded either....

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com /xml/ns/j2ee/web-app_2_4.xsd" version="2.4">

<display-name>Confluence</display-name>
<description>Confluence Web App</description>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        classpath:/databaseSubsystemContext.xml,
        classpath:/services/cacheServiceContext.xml,
        classpath:/services/bandanaServiceContext.xml,
        classpath:/services/eventServiceContext.xml,
        classpath:/services/pluginServiceContext.xml,
        classpath:/services/taskQueueServiceContext.xml,
        classpath:/services/permissionsServiceContext.xml,
        classpath:/applicationContext.xml,
        classpath:/i18NContext.xml,
        classpath:/securityContext.xml,
        classpath:/productionDatabaseContext.xml,
        classpath:/indexingSubsystemContext.xml,
        classpath:/searchSubsystemContext.xml,
        classpath:/rpcSubsystemContext.xml,
        classpath:/upgradeSubsystemContext.xml,
        classpath:/wikiSubsystemContext.xml,
        classpath:/renderingContext.xml,
        classpath:/wikiFiltersSubsystemContext.xml,
        classpath:/velocityContext.xml,
        classpath:/importExportSubsystemContext.xml,
        classpath:/schedulingSubsystemContext.xml,
        classpath:/schedulingSubsystemManagedContext.xml,
        classpath:/atlassianUserContext.xml,
        classpath:/importedEmbeddedCrowdContext.xml,
        classpath:/embeddedCrowdContext.xml,
        classpath:/attachmentSubsystemContext.xml,
        classpath:/services/baseServiceContext.xml,
        classpath:/services/contentServiceContext.xml,
        classpath:/services/userServiceContext.xml,
        classpath:/services/statusServiceContext.xml,
        classpath:/services/labelServiceContext.xml,
        classpath:/com/atlassian/confluence/compatibility/compatibility-cont

ext.xml, classpath:/jmxContext.xml, classpath:/cacheProviderContext.xml, classpath:/wikiToXhtmlMigrationContext.xml

<context-param>
    <param-name>contextClass</param-name>
    <param-value>com.atlassian.confluence.setup.ConfluenceXmlWebApplicationC

ontext

<!-- Uncomment the following to disable the space export long running task. 

-->

/duos ...skipping

duoauth com.duosecurity.seraph.filter.DuoAuthFilter ikey IKEYHERE skey SKEYHERE akey AKEYHERE host api-XXXXXXX.duosecurity.com
<filter-mapping>
    <filter-name>duoauth</filter-name>

[tuc@valhalla Desktop]$ cat web.xml.duo <?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">

<display-name>Confluence</display-name>
<description>Confluence Web App</description>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        classpath:/databaseSubsystemContext.xml,
        classpath:/services/cacheServiceContext.xml,
        classpath:/services/bandanaServiceContext.xml,
        classpath:/services/eventServiceContext.xml,
        classpath:/services/pluginServiceContext.xml,
        classpath:/services/taskQueueServiceContext.xml,
        classpath:/services/permissionsServiceContext.xml,
        classpath:/applicationContext.xml,
        classpath:/i18NContext.xml,
        classpath:/securityContext.xml,
        classpath:/productionDatabaseContext.xml,
        classpath:/indexingSubsystemContext.xml,
        classpath:/searchSubsystemContext.xml,
        classpath:/rpcSubsystemContext.xml,
        classpath:/upgradeSubsystemContext.xml,
        classpath:/wikiSubsystemContext.xml,
        classpath:/renderingContext.xml,
        classpath:/wikiFiltersSubsystemContext.xml,
        classpath:/velocityContext.xml,
        classpath:/importExportSubsystemContext.xml,
        classpath:/schedulingSubsystemContext.xml,
        classpath:/schedulingSubsystemManagedContext.xml,
        classpath:/atlassianUserContext.xml,
        classpath:/importedEmbeddedCrowdContext.xml,
        classpath:/embeddedCrowdContext.xml,
        classpath:/attachmentSubsystemContext.xml,
        classpath:/services/baseServiceContext.xml,
        classpath:/services/contentServiceContext.xml,
        classpath:/services/userServiceContext.xml,
        classpath:/services/statusServiceContext.xml,
        classpath:/services/labelServiceContext.xml,
        classpath:/com/atlassian/confluence/compatibility/compatibility-context.xml,
        classpath:/jmxContext.xml,
        classpath:/cacheProviderContext.xml,
        classpath:/wikiToXhtmlMigrationContext.xml
    </param-value>
</context-param>

<context-param>
    <param-name>contextClass</param-name>
    <param-value>com.atlassian.confluence.setup.ConfluenceXmlWebApplicationContext</param-value>
</context-param>

<!-- Uncomment the following to disable the space export long running task. -->
<!--
    <context-param>
        <param-name>unsupportedContainersForExportLongRunningTask</param-name>
        <param-value>websphere,jboss</param-value>
    </context-param>
-->

<filter>
    <filter-name>debug-before-request</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.DebugFilter</filter-class>
    <init-param>
        <param-name>phase</param-name>
        <param-value>before</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>REQUEST</param-value>
    </init-param>
</filter>
<filter>
    <filter-name>debug-before-include</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.DebugFilter</filter-class>
    <init-param>
        <param-name>phase</param-name>
        <param-value>before</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>INCLUDE</param-value>
    </init-param>
</filter>
<filter>
    <filter-name>debug-before-forward</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.DebugFilter</filter-class>
    <init-param>
        <param-name>phase</param-name>
        <param-value>before</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>FORWARD</param-value>
    </init-param>
</filter>
<filter>
    <filter-name>debug-before-error</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.DebugFilter</filter-class>
    <init-param>
        <param-name>phase</param-name>
        <param-value>before</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>ERROR</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>debug-after-request</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.DebugFilter</filter-class>
    <init-param>
        <param-name>phase</param-name>
        <param-value>after</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>REQUEST</param-value>
    </init-param>
</filter>
<filter>
    <filter-name>debug-after-include</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.DebugFilter</filter-class>
    <init-param>
        <param-name>phase</param-name>
        <param-value>after</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>INCLUDE</param-value>
    </init-param>
</filter>
<filter>
    <filter-name>debug-after-forward</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.DebugFilter</filter-class>
    <init-param>
        <param-name>phase</param-name>
        <param-value>after</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>FORWARD</param-value>
    </init-param>
</filter>
<filter>
    <filter-name>debug-after-error</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.DebugFilter</filter-class>
    <init-param>
        <param-name>phase</param-name>
        <param-value>after</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>ERROR</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>webwork-cleanup</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ActionContextCleanUp</filter-class>
</filter>

<filter>
    <filter-name>header-sanitiser</filter-name>
    <filter-class>com.atlassian.core.filters.HeaderSanitisingFilter</filter-class>
</filter>

<filter>
    <filter-name>log404s</filter-name>
    <filter-class>com.atlassian.confluence.servlet.FourOhFourErrorLoggingFilter</filter-class>
</filter>

<filter>
    <filter-name>jmx</filter-name>
    <filter-class>com.atlassian.confluence.jmx.JmxFilter</filter-class>
</filter>

 <filter>
    <filter-name>request-param-cleaner</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.validateparam.RequestParamValidationFilter</filter-class>
    <init-param>
        <param-name>whitelistStrategy</param-name>
        <param-value>defaultRequestParamCleanerWhitelistStrategy</param-value>
    </init-param>
</filter>
  <!--USE WITH CAUTION!
  This filter will drop any request that comes in when Confluence is not finished setting up.
  To prevent this from dropping valid requests ensure that the filter url mapping maps to exactly the request you want
  to drop.-->
<filter>
    <filter-name>dropIfNotSetupFilter</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.DropIfNotSetupFilter</filter-class>
</filter>
<filter>
    <filter-name>language</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.LanguageExtractionFilter</filter-class>
</filter>

<filter>
    <filter-name>translation-mode</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.TranslationModeFilter</filter-class>
</filter>

<filter>
    <filter-name>johnson</filter-name>
    <filter-class>com.atlassian.confluence.web.ConfluenceJohnsonFilter</filter-class>
</filter>

<filter>
    <filter-name>sessioninview</filter-name>
    <filter-class>com.atlassian.config.FlushingSpringSessionInViewFilterForHibernate</filter-class>
</filter>

<filter>
    <filter-name>login</filter-name>
    <filter-class>com.atlassian.seraph.filter.LoginFilter</filter-class>
</filter>

<filter>
    <filter-name>trustedapp</filter-name>
    <filter-class>com.atlassian.confluence.security.trust.seraph.ConfluenceTrustedApplicationsFilter</filter-class>
</filter>

<filter>
    <filter-name>requestcache</filter-name>
    <filter-class>com.atlassian.confluence.util.RequestCacheThreadLocalFilter</filter-class>
</filter>

<filter>
    <filter-name>messagesDecoratorFilter</filter-name>
    <filter-class>com.atlassian.confluence.security.websudo.MessagesDecoratorFilter</filter-class>
</filter>

<filter>
    <filter-name>sitemesh</filter-name>
    <filter-class>com.atlassian.confluence.util.profiling.ProfilingPageFilter</filter-class>
</filter>

<filter>
    <filter-name>encoding</filter-name>
    <filter-class>com.atlassian.confluence.setup.ConfluenceEncodingFilter</filter-class>
</filter>

<filter>
    <filter-name>caching</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.ConfluenceCachingFilter</filter-class>
</filter>

<filter>
    <filter-name>security</filter-name>
    <filter-class>com.atlassian.seraph.filter.SecurityFilter</filter-class>
</filter>
<filter>
    <filter-name>duoauth</filter-name>
    <filter-class>com.duosecurity.seraph.filter.DuoAuthFilter</filter-class>
    <init-param>
        <param-name>ikey</param-name>
        <param-value>IKEYHERE</param-value>
    </init-param>
    <init-param>
        <param-name>skey</param-name>
        <param-value>SKEYHERE</param-value>
    </init-param>
    <init-param>
        <param-name>akey</param-name>
        <param-value>AKEYHERE</param-value>
    </init-param>
    <init-param>
        <param-name>host</param-name>
        <param-value>api-XXXXXXX.duosecurity.com</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>duoauth</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

<filter>
    <filter-name>duoauth</filter-name>
    <filter-class>com.duosecurity.seraph.filter.DuoAuthFilter</filter-class>
    <init-param>
        <param-name>ikey</param-name>
        <param-value>DI6MXR7KQOCJ1VWXRMW7</param-value>
    </init-param>
    <init-param>
        <param-name>skey</param-name>
        <param-value>GLMW5v55X0OGjESVQjnvdBYNE1u6xsKEwZuQmYdf</param-value>
    </init-param>
    <init-param>
        <param-name>akey</param-name>
        <param-value>db2ee0cd1c32bdc2fdddfdc3a71566e11d27d37a</param-value>
    </init-param>
    <init-param>
        <param-name>host</param-name>
        <param-value>api-323ddf91.duosecurity.com</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>duoauth</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

<filter>
    <filter-name>userthreadlocal</filter-name>
    <filter-class>com.atlassian.confluence.util.UserThreadLocalFilter</filter-class>
</filter>

<filter>
    <filter-name>servletcontextthreadlocal</filter-name>
    <filter-class>com.atlassian.core.filters.ServletContextThreadLocalFilter</filter-class>
</filter>

<filter>
    <filter-name>threadLocalCache</filter-name>
    <filter-class>com.atlassian.confluence.web.filter.ThreadLocalCacheFilter</filter-class>
</filter>

<filter>
    <filter-name>expires-one-hour</filter-name>
    <filter-class>com.atlassian.core.filters.ExpiresFilter</filter-class>
    <init-param>
        <!-- specify the which HTTP parameter to use to turn the filter on or off -->
        <!-- if not specified - defaults to "profile.filter" -->
        <param-name>expiryTimeInSeconds</param-name>
        <param-value>3600</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>thread-local-error-collection</filter-name>
    <filter-class>com.atlassian.confluence.util.ConfluenceErrorFilter</filter-class>
</filter>

<filter>
    <filter-name>profiling</filter-name>
    <filter-class>com.atlassian.confluence.util.profiling.ConfluenceProfilingFilter</filter-class>
    <init-param>
        <!-- specify the which HTTP parameter to use to turn the filter on or off -->
        <!-- if not specified - defaults to "profile.filter" -->
        <param-name>activate.param</param-name>
        <param-value>profile</param-value>
    </init-param>
    <init-param>
        <!-- specify the whether to start the filter automatically -->
        <!-- if not specified - defaults to "true" -->
        <param-name>autostart</param-name>
        <param-value>false</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>AccessLogFilter</filter-name>
    <filter-class>com.atlassian.confluence.util.AccessLogFilter</filter-class>
</filter>

<filter>
    <filter-name>gzipFilter</filter-name>
    <filter-class>com.atlassian.confluence.util.zip.ConfluenceGzipFilter</filter-class>
</filter>

<filter>
    <filter-name>ClusterHeaderFilter</filter-name>
    <filter-class>com.atlassian.confluence.util.ClusterHeaderFilter</filter-class>
</filter>

<!-- this filter is used to rewrite through the /s/* filter to add caching headers. see: urlrewrite.xml -->
<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>

<filter>
    <filter-name>LoggingContextFilter</filter-name>
    <filter-class>com.atlassian.confluence.util.LoggingContextFilter</filter-class>
</filter>

<filter>
    <filter-name>RequestTimeFilter</filter-name>
    <filter-class>com.atlassian.confluence.core.datetime.RequestTimeThreadLocalFilter</filter-class>
</filter>

<!-- Plugins 2.5 filter changes -->

<filter>
    <filter-name>filter-plugin-dispatcher-after-encoding-request</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>after-encoding</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>REQUEST</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-after-encoding-forward</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>after-encoding</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>FORWARD</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-after-encoding-include</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>after-encoding</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>INCLUDE</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-after-encoding-error</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>after-encoding</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>ERROR</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-login-request</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-login</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>REQUEST</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-login-forward</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-login</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>FORWARD</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-login-include</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-login</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>INCLUDE</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-login-error</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-login</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>ERROR</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-decoration-request</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-decoration</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>REQUEST</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-decoration-forward</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-decoration</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>FORWARD</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-decoration-include</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-decoration</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>INCLUDE</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-decoration-error</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-decoration</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>ERROR</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-dispatch-request</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-dispatch</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>REQUEST</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-dispatch-forward</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-dispatch</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>FORWARD</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-dispatch-include</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-dispatch</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>INCLUDE</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>filter-plugin-dispatcher-before-dispatch-error</filter-name>
    <filter-class>com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter</filter-class>
    <init-param>
        <param-name>location</param-name>
        <param-value>before-dispatch</param-value>
    </init-param>
    <init-param>
        <param-name>dispatcher</param-name>
        <param-value>ERROR</param-value>
    </init-param>
</filter>

<!-- End plugins 2.5 filter changes -->

<filter-mapping>
    <filter-name>dropIfNotSetupFilter</filter-name>
    <url-pattern>/json/startheartbeatactivity.action</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>dropIfNotSetupFilter</filter-name>
    <url-pattern>/rest/tinymce/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>log404s</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>header-sanitiser</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- THIS MUST REMAIN AS THE TOP FILTER SO THAT THE ENCODING CAN BE SET BEFORE ANYTHING ELSE TOUCHES IT (well, except the header sanitiser)-->
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>*.vm</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/display/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/download/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/plugins/servlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/label/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/s/*</url-pattern>
</filter-mapping>

<!-- Uncomment to enable debugging for response headers in each dispatcher pipeline, before (almost) all filtering -->
<filter-mapping>
    <filter-name>debug-before-request</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>debug-before-include</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>debug-before-forward</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>debug-before-error</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>requestcache</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

 <filter-mapping>
    <filter-name>language</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>webwork-cleanup</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>translation-mode</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>request-param-cleaner</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Plugins 2.5 filter changes -->

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-after-encoding-request</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>filter-plugin-dispatcher-after-encoding-forward</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>filter-plugin-dispatcher-after-encoding-include</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>filter-plugin-dispatcher-after-encoding-error</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

<!-- End plugins 2.5 filter changes -->

<filter-mapping>
    <filter-name>caching</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>gzipFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/s/*</url-pattern>
</filter-mapping>

<!-- uncomment this mapping in order to log page views to the access log, see log4j.properties also -->
<!--
    <filter-mapping>
        <filter-name>AccessLogFilter</filter-name>
        <url-pattern>/display/*</url-pattern>
    </filter-mapping>
-->

<filter-mapping>
    <filter-name>RequestTimeFilter</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>RequestTimeFilter</filter-name>
    <url-pattern>*.vm</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>RequestTimeFilter</filter-name>
    <url-pattern>/display/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>RequestTimeFilter</filter-name>
    <url-pattern>/plugins/servlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>RequestTimeFilter</filter-name>
    <url-pattern>/download/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>RequestTimeFilter</filter-name>
    <url-pattern>/label/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>RequestTimeFilter</filter-name>
    <url-pattern>/s/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>profiling</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>profiling</filter-name>
    <url-pattern>*.vm</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>profiling</filter-name>
    <url-pattern>/display/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>profiling</filter-name>
    <url-pattern>/plugins/servlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>profiling</filter-name>
    <url-pattern>/download/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>profiling</filter-name>
    <url-pattern>/label/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>profiling</filter-name>
    <url-pattern>/s/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>thread-local-error-collection</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>thread-local-error-collection</filter-name>
    <url-pattern>*.vm</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>thread-local-error-collection</filter-name>
    <url-pattern>/display/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>thread-local-error-collection</filter-name>
    <url-pattern>/plugins/servlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>thread-local-error-collection</filter-name>
    <url-pattern>/download/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>thread-local-error-collection</filter-name>
    <url-pattern>/label/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>thread-local-error-collection</filter-name>
    <url-pattern>/s/*</url-pattern>
</filter-mapping>
<!--filter-mapping>
    <filter-name>sessioninview</filter-name>
    <url-pattern>/rpc/*</url-pattern>
</filter-mapping-->

<filter-mapping>
    <filter-name>sessioninview</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>sessioninview</filter-name>
    <url-pattern>*.vm</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>sessioninview</filter-name>
    <url-pattern>/display/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>sessioninview</filter-name>
    <url-pattern>/plugins/servlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>sessioninview</filter-name>
    <url-pattern>/label/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>sessioninview</filter-name>
    <url-pattern>/s/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>sessioninview</filter-name>
    <url-pattern>/exportword</url-pattern>
</filter-mapping>

<!-- Wrap the prototype Confluence REST plugin in a transaction, as the REST plugin type does not have effective support
     for transactions yet. Hopefully non-prototype REST implementations will support transactions properly so we don't
     have to extend this hack to production code -->
<filter-mapping>
    <filter-name>sessioninview</filter-name>
    <url-pattern>/rest/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>johnson</filter-name>
    <url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>johnson</filter-name>
    <url-pattern>*.vm</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>johnson</filter-name>
    <url-pattern>/display/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>johnson</filter-name>
    <url-pattern>/download/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>johnson</filter-name>
    <url-pattern>/label/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>johnson</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>johnson</filter-name>
    <url-pattern>/plugins/servlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>johnson</filter-name>
    <url-pattern>/s/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>ClusterHeaderFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Plugins 2.5 filter changes -->

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-login-request</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-login-forward</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-login-include</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-login-error</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

<!-- End plugins 2.5 filter changes -->

<filter-mapping>
    <filter-name>login</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

<!-- This must come after the login filter -->
<filter-mapping>
    <filter-name>trustedapp</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>security</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

<!-- Must go after seraph -->
<filter-mapping>
    <filter-name>userthreadlocal</filter-name>
    <url-pattern>*.action</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>userthreadlocal</filter-name>
    <url-pattern>*.vm</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>userthreadlocal</filter-name>
    <url-pattern>/display/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>userthreadlocal</filter-name>
    <url-pattern>/label/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>userthreadlocal</filter-name>
    <url-pattern>/exportword</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>userthreadlocal</filter-name>
    <url-pattern>/s/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>threadLocalCache</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>threadLocalCache</filter-name>
    <url-pattern>*.vm</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>threadLocalCache</filter-name>
    <url-pattern>/display/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>threadLocalCache</filter-name>
    <url-pattern>/label/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>threadLocalCache</filter-name>
    <url-pattern>/exportword</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>threadLocalCache</filter-name>
    <url-pattern>/rpc/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>threadLocalCache</filter-name>
    <url-pattern>/s/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>LoggingContextFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>servletcontextthreadlocal</filter-name>
    <url-pattern>*.action</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>servletcontextthreadlocal</filter-name>
    <url-pattern>*.vm</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>servletcontextthreadlocal</filter-name>
    <url-pattern>/display/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>servletcontextthreadlocal</filter-name>
    <url-pattern>/label/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>servletcontextthreadlocal</filter-name>
    <url-pattern>/rpc/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>servletcontextthreadlocal</filter-name>
    <url-pattern>/s/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>servletcontextthreadlocal</filter-name>
    <url-pattern>/download/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>servletcontextthreadlocal</filter-name>
    <url-pattern>/rest/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>jmx</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>jmx</filter-name>
    <url-pattern>/display/*</url-pattern>
</filter-mapping>

<!-- Plugins 2.5 filter changes -->

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-decoration-request</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-decoration-forward</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-decoration-include</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-decoration-error</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

<!-- End plugins 2.5 filter changes -->

<filter-mapping>
    <filter-name>sitemesh</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Needs to run before the sitemesh filter works with the response but after the target servlet/resource was executed -->
<filter-mapping>
    <filter-name>messagesDecoratorFilter</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>messagesDecoratorFilter</filter-name>
    <url-pattern>*.vm</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>messagesDecoratorFilter</filter-name>
    <url-pattern>/display/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>messagesDecoratorFilter</filter-name>
    <url-pattern>/plugins/servlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>messagesDecoratorFilter</filter-name>
    <url-pattern>/label/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>expires-one-hour</filter-name>
    <url-pattern>*.js</url-pattern>
</filter-mapping>

<!--<filter-mapping>
    <filter-name>expires-one-hour</filter-name>
    <url-pattern>*.css</url-pattern>
</filter-mapping>-->

<!-- Plugins 2.5 filter changes -->
<!-- the following plugin filter should be the last one in the chain -->
<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-dispatch-request</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-dispatch-forward</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-dispatch-include</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>filter-plugin-dispatcher-before-dispatch-error</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

<!-- End plugins 2.5 filter changes -->

<!-- Uncomment to enable debugging for response headers in each dispatcher pipeline, after all filtering -->
<filter-mapping>
    <filter-name>debug-after-request</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>debug-after-include</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>debug-after-forward</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>debug-after-error</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

<!-- ============================================================ -->
<!-- Servlet Context Listeners (Executed on app startup/shutdown) -->
<!-- ============================================================ -->

<!-- Cleans up JavaBeans introspection caches on app shutdown, so that the classes and classloaders can be
     garbage-collected properly -->
<listener>
    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>

<!-- Load initial minimal configuration and bootstrap the application ready for setup -->
<listener>
    <listener-class>com.atlassian.confluence.setup.ConfluenceConfigurationListener</listener-class>
</listener>

<!-- Bring up the rest of the application if it is already set up -->
<listener>
    <listener-class>com.atlassian.confluence.setup.ConfluenceBootstrappedContextLoaderListener</listener-class>
</listener>

<!-- Check for the confluence.i18n.reloadbundles system property. If set, do not cache the localized
.properties files. -->
<listener>
    <listener-class>com.atlassian.confluence.languages.ReloadBundlesContextListener</listener-class>
</listener>

<listener>
    <listener-class>com.atlassian.confluence.setup.ValidLicenseContextListener</listener-class>
</listener>

<!-- Upgrades must be performed before we start the plugin system, because upgrades sometimes affect the plugin data -->
<listener>
    <listener-class>com.atlassian.confluence.upgrade.UpgradeLauncherServletContextListener</listener-class>
</listener>

<!-- Bring plugin system up, if the database is configured. Plugins must be up before we can run the lifecycle modules. -->
<listener>
    <listener-class>com.atlassian.confluence.plugin.PluginFrameworkContextListener</listener-class>
</listener>

<!-- Perform remaining configured lifecycle events, if the application is set up -->
<listener>
    <listener-class>com.atlassian.config.lifecycle.LifecycleServletContextListener</listener-class>
</listener>

<!-- ===================================== -->
<!-- Other (non servlet-context) listeners -->
<!-- ===================================== -->

<listener>
    <listener-class>com.atlassian.confluence.user.listeners.UserSessionExpiryListener</listener-class>
</listener>

<!-- ======== -->
<!-- Servlets -->
<!-- ======== -->

<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.ConfluenceServletDispatcher</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet>
    <servlet-name>velocity</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.ConfluenceVelocityServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>

<servlet>
    <servlet-name>simple-display</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.SpringManagedServlet</servlet-class>
    <init-param>
        <param-name>springComponentName</param-name>
        <param-value>simpleDisplayServlet</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
</servlet>

<servlet>
    <servlet-name>tiny-url</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.TinyUrlServlet</servlet-class>
    <load-on-startup>3</load-on-startup>
</servlet>

<servlet>
    <servlet-name>file-server</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.FileServerServlet</servlet-class>
    <load-on-startup>4</load-on-startup>
</servlet>

<servlet>
    <servlet-name>xmlrpc</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.SpringManagedServlet</servlet-class>
    <init-param>
        <param-name>springComponentName</param-name>
        <param-value>xmlRpcServer</param-value>
    </init-param>
    <load-on-startup>6</load-on-startup>
</servlet>

<servlet>
    <servlet-name>trackback</servlet-name>
    <servlet-class>com.atlassian.trackback.TrackbackListenerServlet</servlet-class>
    <init-param>
        <param-name>trackbackStore</param-name>
        <param-value>com.atlassian.confluence.links.persistence.ConfluenceTrackbackStore</param-value>
    </init-param>
    <load-on-startup>7</load-on-startup>
</servlet>

<servlet>
    <servlet-name>glue-soap</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.SpringManagedServlet</servlet-class>
    <init-param>
        <param-name>springComponentName</param-name>
        <param-value>glueSoapServer</param-value>
    </init-param>
    <load-on-startup>8</load-on-startup>
</servlet>

<servlet>
    <servlet-name>axis-soap</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.SpringManagedServlet</servlet-class>
    <init-param>
        <param-name>springComponentName</param-name>
        <param-value>axisSoapServer</param-value>
    </init-param>
    <load-on-startup>8</load-on-startup>
</servlet>

<servlet>
    <servlet-name>servlet-module-container-servlet</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.ServletModuleContainerServlet</servlet-class>
    <load-on-startup>9</load-on-startup>
</servlet>

<servlet>
    <servlet-name>css</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.CssServlet</servlet-class>
    <load-on-startup>10</load-on-startup>
</servlet>

<!-- Keep this servlet as the last to load -->
<servlet>
    <servlet-name>final-servlet</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.ReadyToServeServlet</servlet-class>
    <load-on-startup>100</load-on-startup>
</servlet>

<servlet>
    <servlet-name>labels</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.LabelServlet</servlet-class>
</servlet>

<servlet>
    <servlet-name>jcaptcha</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.ImageCaptchaServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
</servlet>

<servlet>
    <servlet-name>exportword</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.SpringManagedServlet</servlet-class>
    <init-param>
        <param-name>springComponentName</param-name>
        <param-value>exportWordPageServer</param-value>
    </init-param>
</servlet>

<!-- Dummy servlet for CONF-7953. Used for mapping URLs which have no target servlet but need to be filtered -->
<servlet>
    <servlet-name>noop</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.ConfluenceNoOpServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

<!--
     we pretty much have to map all CSS files to the action servlet, as a result
     of a fun collaboration of an IE bug, and the short-sightedness of the servlet
     spec.
-->
<servlet-mapping>
    <servlet-name>css</servlet-name>
    <url-pattern>*.css</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>velocity</servlet-name>
    <url-pattern>*.vm</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>simple-display</servlet-name>
    <url-pattern>/display/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>tiny-url</servlet-name>
    <url-pattern>/x/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>file-server</servlet-name>
    <url-pattern>/download/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>xmlrpc</servlet-name>
    <url-pattern>/rpc/xmlrpc</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>trackback</servlet-name>
    <url-pattern>/rpc/trackback/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>glue-soap</servlet-name>
    <url-pattern>/rpc/soap/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>glue-soap</servlet-name>
    <url-pattern>/rpc/soap-glue/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>axis-soap</servlet-name>
    <url-pattern>/rpc/soap-axis/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>servlet-module-container-servlet</servlet-name>
    <url-pattern>/plugins/servlet/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>labels</servlet-name>
    <url-pattern>/label/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>jcaptcha</servlet-name>
    <url-pattern>/jcaptcha/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>exportword</servlet-name>
    <url-pattern>/exportword</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>noop</servlet-name>
    <url-pattern>/s/*</url-pattern>
</servlet-mapping>

<!--
Noop filter mapping for the trusted app certificate which is serviced exclusively by the Seraph trusted app filter.
This servlet mapping is necessary for Websphere 6.1 which still likes to forward the request to a servlet even if
the filter chain is not fully followed.
-->
<servlet-mapping>
    <servlet-name>noop</servlet-name>
    <url-pattern>/admin/appTrustCertificate</url-pattern>
</servlet-mapping>

<!-- 
As the REST module is implemented using only a filter this noop servlet is required (CONF-17578)
-->
<servlet-mapping>
    <servlet-name>noop</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

<session-config>
    <session-timeout>60</session-timeout>
</session-config>

<welcome-file-list>
    <welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<!-- redirect all 500 errors to confluence error page -->
<error-page>
    <error-code>500</error-code>
    <location>/500page.jsp</location>
</error-page>

<error-page>
    <error-code>404</error-code>
    <location>/fourohfour.action</location>
</error-page>

duopeter commented 11 years ago

Hi Tuc,

The web.xml that you included has the duoauth and twice. That could be your problem if you were really using it like that. The second one lists your ikey, akey, and skey. If that is your real skey, you should probably at least generate a new one.

tuctboh commented 11 years ago

Hi,

Our actual file doesn't have it twice. I don't know why you got it twice, except, SIGH, Cut/paste issue. Won't let me upload xml files. We went for broke this morning and tried it on our prod 4.3.6 system. Same behaviour. No matter where we went we got the "DUO AUTHENTICATION" page, but didn't have to type the token again. I also saw items in the dashboard for every page we went to, different spaces, etc.

Are we destined to not be able to use DUO properly?

Tuc

duopeter commented 11 years ago

Hi Tuc,

It looks like your "duoauth" config is right after the <filter><filter-name>security... element. Can you try moving it down to after the similarly named <filter-mapping><filter-name>security... element?

kra commented 11 years ago

See the excerpt here, which includes the existing stanza it goes after:

https://www.duosecurity.com/docs/confluence#configure_confluence