What changes are needed to a 2.8 custom Authenticator to run in 4.3?

Peter Binney November 7, 2012

We have upgraded from 2.8 to 4.3 and find page fetch performance is significantly degraded when using a custom authenticator.

Though this is partly because of the increased page content in 4.3, performance is severely exacerbated when we enable our custom authenticator.

The support for this was why we chose Confluence in the first place, to integrate the Digital Certificate authentication used by all our applications.

There is some difference in the authentication chain in 4.3 that we need instruction about, or documentation for (there being none I can find online).

I attach the code for our current one (GdsConfluenceAuthenticator-2.8.java which won't build against 4.3 libraries) and the version that I derived from it (GdsConfluenceAuthenticator.java) - somewhat by trial and error (and by decompiling some of your .jar files!).

GdsConfluenceAuthenticator is enabled in the normal way, by modifying two files:

1. seraph-config.xml - changing the

2. web.xml - adding three fields:,and

I attach the modified files.

I enabled the Profiler while clicking on two links (/display/WebSolutions/Web+Solutions+IT and /display/WebSolutions/AskBIS+Development) with default (ie: name+password authentication) and our (GdsConfluenceAuthenticator) authentication.

In both scenarios I pre-clicked each link to get any browser-cacheable content loaded.

The load times reported by the profiler belie the actual time seen by a user. For name+password authentication (profile-passwords.log), the times are similar, but with GdsConfluenceAuthenticator (profile-certificatesE.log) the real time is longer.

The differing order of events, and the debugging I have enabled, muddy the output a bit. But if you diff the two files side-by-side, what stands out is that there are many more calls to UserAccessor.getUser() with GdsConfluenceAuthenticator than without.

This makes me think that there is some other step needed on initial login as well as AuthenticatedUserThreadLocal.setUser() (at line 48).

We cannot upgrade until we can get comparable performance out of 4.3

13 answers

1 accepted

0 votes
Answer accepted
Peter Binney November 8, 2012

Since this miserable website won't let me comment on Jamie Echlin's answer, I have to do so here by "answering" my own question:

Hi Jamie - I've switched to your ExampleSSOAuthenticator but sadly the performance problem is unchanged.

Authentication works (as it does with my original - which only really differs from yours in that it extends ConfluenceGroupJoiningAuthenticator rather than ConfluenceAuthenticator). All I have done to your code is, in getUser(), immediately below

if (existingUser != null)
{      // ....
       return existingUser;
}

I added this:

// No session, so "login" using GdsUser principal set up by gdsrealm.jar (or indeed any other JAAS LoginModule)
Principal result = request.getUserPrincipal();
if (result != null)
{
    String username = result.getName();
    Principal user = getUser(username); // Get the com.atlassian.user.User
    if (user != null)
    {
        putPrincipalInSessionContext(request, user);
        getElevatedSecurityGuard().onSuccessfulLoginAttempt(request, username);
        getEventPublisher().publish(new LoginEvent(this, username, request.getSession().getId(), request.getRemoteHost(), request.getRemoteAddr()));
        LoginReason.OK.stampRequestResponse(request, response);

        log.info("getUser() GDSREALM login for : " + username + " response: " + response + " user: " + user
               + " in " + (System.currentTimeMillis() - start) + "ms");
        return user;
    }
}
log.info("We never get here ...");

As with my original code, when compared with a session configured for name+password:
a) the performance is massively worse, and
b) it generates many more UserAccessor.getUser() calls (as shown with Confluence Profiling enabled).

So it feels to me that there must be something else that should be done during the initial SSO login.

An anomaly I see in the logging I make on initial login, is that there are two calls at the beginning of a new session. The first has "response" set to null and hence, I assume, fails to do whatever it then does on the second call when "response" is a HttpServletResponse object.

Any further thoughts would be very much appreciated!

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 8, 2012

Hrm... firstly it's not my code, but @Joseph Clark's, who is the right man to help you here.

I won't pretend this shizzle is not hard, it's much worse than trying to write a standard plugin imho.

Why are you extending GroupJoiningAuthenticator? You should not... what is the performance like extending the class that the sample extends? You don't need it to auto-join any groups, this is covered by the standard embedded crowd stuff. If the user is plucked from a directory that has the configuration where a user is auto-added to a group or list of groups, that will happen.

> b) it generates many more UserAccessor.getUser() calls (as shown with Confluence Profiling enabled).

But where is this being called from, can you mod the code to log a stack trace? Or stick a breakpoint in or something.

Um... you really need Joe Clarke's attentions on this one.


Peter Binney November 8, 2012

Sorry if my wording wasn't clear. I am now extending ConfluenceAuthenticator. I am using the exact code that you posted, with just the addition of the block I show above.

I've no idea where UserAccessor.getUser() is called from - I just note that there are many more of them in the Confluence Profiler output with ExampleSSOAuthenticator than using the out-of-the box name+password login. This may be a red herring. The Profiler shows each of them taking only 1 or 2ms, and there can't be more than about 30 additional ones.

I'll see if I can pester Joe Clark!

Peter Binney November 15, 2012

Hi Jamie - I've had no joy yet in raising a response from Joe or anyone at Atlassian.

I wonder if there is a problem with the 3 sections we add to web.xml (security-constraint, login-config and security-role) to get CLIENT-CERT authentication.

They are what we used in 2.8 (which used Java servlet 2.3 spec). I see 4.3 uses 2.4 spec, so maybe the syntax and/or ordering of sections needs to change.

What do you put in web.xml?

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 15, 2012

Hi Peter... I'd create a support request and beg for help from Joe.

Although we both use x.509 certs I'd guess we do things differently, although this doesn't account for the difference I think.

I used to do it like you do, we had the stuff in the web.xml and java libs for decoding the cert etc. At some point though I switched to having the ssl connection terminated at apache, and apache just sets a request header with the authenticated user name. The authenticator takes this and stuffs the user in the session as per usual. For this bit apache to tomcat is via ajp.

The other main difference is that I only use two-way SSL for hitting a special url called /loginsso.action, everything else is redirected to http. The /loginsso is redirected to https. So to all intents and purposes, unless the user is logging in, then the auth module just behaves like the standard one.

I'm quite happy with this method, because I only need to change minimal code in all the atlassian products, and not add any jars or anything.

Don't know if that helps you, but thought I'd expand a bit.

Can you add some debug to your code to verify that once the user is logged in and in the session, they never go through your pki bit of code?

jamie

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 15, 2012

So to answer your question, nothing is put in the web.xml (anymore).

Peter Binney November 15, 2012

Hi Jamie - many thanks for that. As it happens we also use an Apache fronting server do the cert negotiation, with it AJP-ing to the Tomcat. But, we also like to support direct client-cert access to the Tomcat.

We use a (JAAS, I believe) "realm" to handle either scenario. This, from my understanding, has to be enabled in web.xml (if it isn't request.getUserPrincipal() returns null).

I have logging in (Joe's) ExampleSSOAuthenticator which shows our realm-based lookup only happens at session setup.

All following calls return at the top of the method because getUserFromSession(request) has a non-null value.

I have a ticket with Atlassian, but they say this is "out of scope issue for Atlassian Support", that I should pursue via this answers.atlassian discussion and that "hopefully [Joe] will be there replying soon".

Forgive my (as must be becoming clear!) ignorance, but how do you configure so that your /loginsso.action is called at login?

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 15, 2012

> but how do you configure so that your /loginsso.action is called at login?

I want to support both SSO and forms-based login. So I've just modified the login.jsp page to have a new link called Secure Sign-On, that points to /loginsso.action. Then apache rewrites that to https://.../login.action. So there is not really a different action...

> All following calls return at the top of the method because getUserFromSession(request) has a non-null value

In that case I really don't understand why you'd see a performance difference... baffled.

Peter Binney November 20, 2012

I've found the problem: it was in the <security-constraint> we add to web.xml to enable "realm" authentication.

In Confluence 2.8 (Java servlet 2.3) it was set (possibly over-archingly) to <url-pattern>/*</url-pattern>
With 4.3 (servlet 2.4), when I restricted this to <url-pattern>/login.action</url-pattern> performance became normal.

Related wrinkles in the unlikely event that anyone else is upgrading from 2.8 (I believe the 2.8 -> 3.5 is the crucial change):

  • 4.3 does not use atlassian-user.xml and you must manually create a new LDAP Directory.
  • Key attributes of the Directory:
    - " Read Only, with Local Groups"

    - "Auto-add users to: confluence-users" - thus allowing the authenticator to extend ConfluenceAuthenticator (rather than ConfluenceGroupJoiningAuthenticator and manually doing the auto-add, as we had to do in 2.8).
  • Atlassian's documented migration path if you were using atlassian-user.xml is flawed.
    It creates a Directory that does ignores the <userSearchFilter> and so links all objects in the LDAP directory, which (also) kills performance!

Very many thanks again Jamie for your pointers and feedback.

1 vote
JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 7, 2012

I'd start by blowing off your old authenticator completely and rewriting based on https://bitbucket.org/jaysee00/example-confluence-sso-authenticator.

BTW nothing is attached to your question so hard to comment further.

Our custom authenticator handles x.509 certs, which I assume is what you have too, and there is no performance hit. Once you have retrieved the user you put them in the session and then the profile should be no different than with the out of the box authenticator.

0 votes
Peter Binney November 11, 2012

Here's an attempt to add the two .log files directly after Jira support tells me that .java and .xml are not supported on the "Upload" button: (profile-certificatesE.log) and

0 votes
Peter Binney November 8, 2012

I'm getting distinctly fed up with this website! I just tried to post a comment to Jamie Echlin's answer below which was rejected with "Sorry, our spambot thinks your comment is spam. Please post an answer instead".

But when I try and answer it then says: "Please make sure you are providing an answer to your own question. Otherwise, choose "add comment" to continue a conversation about a given answer or to clarify your question. For more information, see the FAQ."

0 votes
JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 8, 2012

But easier to add them to gist.gitbub.com and link from here.

0 votes
JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 8, 2012

One for @Jeremy Largman.

0 votes
Peter Binney November 8, 2012

Sadly that's blocked from my work. The files are innocuous, so I'll upload them at the weekend onto my noddy website which isn't.

But am continuing with your template SSO - many thanks again!

0 votes
Peter Binney November 8, 2012

That doesn't seem to work. I'm clicking the "Upload" arrow button and selecting a file called GdsConfluenceAuthenticator.java : but nothing appears to be uploaded :-(

0 votes
Peter Binney November 8, 2012

But, I think I can upload a .log file ... profile-certificatesE.log ...

0 votes
Peter Binney November 8, 2012

Nope . That didn't work either. The .log "upload" behaved differently from the .xml and .java ones in that an apparrant link to the file appeared in this editor. But, when I pressed "Comment" it disappeared

0 votes
JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 8, 2012

If you create a new answer or comment you can upload them.

0 votes
Peter Binney November 8, 2012

Many thanks Jamie. I have effectively done what you suggested. But I'll try again from the one you link to.

Sorry about the missing attachments - this issue was auto-created from a post to Atlassian support and I didn't notice that the files were missing. I'll try and attach them here...

... hmm that doesn't seem to work. Any idea how to attach files here?

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events