After enabling SSO, existing users can bypass SAML authentication and keep logging in with their password locally.
Since version 2.1.0, this can be disabled (see .Disable password login with nosso-parameter v2.1.0), but this still does not disable password authentication completely.

In order to accomplish this, some configuration in Jira or Confluence is required.

Bitbucket Server

In Bitbucket Server, just enable Block Password Authentication on the plugin configuration page.
After that, only users with System Administrator privileges or members of a group named allow-password-login can use a password for authentication.
You need to create that group if it doesn't exist yet.

Passwords will work again as soon as the SAML SSO app is disabled or uninstalled.

Jira and Confluence

In Jira and Confluence, password authentication can be blocked by installing a special authenticator in the system. Please paste the following link into your browser to download it: http://builds.resolution.de/denypasswordauthenticator-3.2.0.jar

This was also working in Bamboo up to version 8.0.0 but is no longer working for higher versions.


New in Version 3.2.0

added new init-parameters deniedUsers, groupAllowOverDeny and allowWithoutApplicationAccess

New in Version 3.1.0

added a new init-param allowedUsers for whitelisting usernames.

New in Version 3.0.0

The authenticator can now be configured with init-params. Instead of checking for the fixed group allow-password-login, group names can be configured.

Installation

Copy denypasswordauthenticator-<version>.jar into the applications lib-folder, e.g. /opt/atlassian/jira/jira/WEB-INF/lib for Jira or /opt/atlassian/confluence/confluence/WEB-INF/lib in Confluence.
Ensure that only one version of this file is in that directory, delete any older version.

Configuration

Edit seraph-config.xml in the classes folder, e.g. /opt/atlassian/jira/atlassian-jira/WEB-INF/classes/seraph-config.xml. Comment out the existing authenticator-definition and replace it with de.resolution.samlsso.authenticator.JiraDenyPasswordAuthenticator in Jira or de.resolution.samlsso.authenticator.ConfluenceDenyPasswordAuthenticator in Confluence. Add init-params to the needed section as described below. Here you see all the possibilities from the latest version. Only the required init-params need to be defined in the final configuration:

<!-- <authenticator class="com.atlassian.jira.security.login.JiraSeraphAuthenticator"/>  -->
<authenticator class="de.resolution.samlsso.authenticator.JiraDenyPasswordAuthenticator">
    <init-param>
        <param-name>allowedUsers</param-name>
        <param-value>admin</param-value>
    </init-param>
    <init-param>
        <param-name>deniedUsers</param-name>
        <param-value>youMustNotLogin</param-value>
    </init-param>
     <init-param>
        <param-name>groupAllowOverDeny</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>allowWithoutApplicationAccess</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>allowedGroups</param-name>
        <param-value>allow.*,withpassword</param-value>
    </init-param>
    <init-param>
        <param-name>deniedGroups</param-name>
        <param-value>block.*,nopassword</param-value>
    </init-param>
    <init-param>
        <param-name>allowSysadmins</param-name>
        <param-value>true</param-value>
    </init-param>
</authenticator>

The application must be restarted after changing the seraph configuration file.

Parameters

deniedUsers

Users can not use their passwords if their usernames match one of these regular expressions, the group checks and the checks from allowedUsers are not applied in this case. Multiple entries are separated with ',':

<init-param>
    <param-name>deniedUsers</param-name>
    <param-value>passwordOnly</param-value>
</init-param>

allowedUsers

Users can use their passwords if their usernames match one of these regular expressions, the group checks are not applied in this case. Multiple entries are separated with ',':

<init-param>
    <param-name>allowedUsers</param-name>
    <param-value>admin.*,root</param-value>
</init-param>

allowWithoutApplicationAccess

If this parameter is set to true, users without application-access (usually customers in Jira Service Management) can use a password.

<init-param>
    <param-name>allowWithoutApplicationAccess</param-name>
    <param-value>true</param-value>
</init-param>

allowedGroups

The user can use a password if he is a member of at least one of the groups matching these regular expressions. Multiple entries are separated with ','. In this example all users in groups starting with allow and/or belong to group withpassword can login with basic authentication:

<init-param>
    <param-name>allowedGroups</param-name>
    <param-value>allow.*,withpassword</param-value>
</init-param>

deniedGroups

The user can use a password if he is NOT member of any of the groups matching these regular expressions. Multiple entries are separated with ','. In this example all users in groups starting with block and/or belong to group no password login cannot use basic authentication. All other users not belonging to those groups can use basic authentication:

<init-param>
    <param-name>deniedGroups</param-name>
    <param-value>block.*,nopassword</param-value>
</init-param>

If both allowedGroups and deniedGroups are configured, a user must be a member of a group matching an entry of allowedGroups AND MUST NOT be a member of a group matching an entry of deniedGroups.

groupAllowOverDeny

By default, groupAllowOverDeny is set to false. If both allowedGroups and deniedGroups are configured, users that need to log in with a local password must be member of a group matching an entry of allowedGroups AND MUST NOT be member of a group matching an entry of deniedGroups. If groupAllowOverDeny is set to true, the allowedGroups parameter takes precedence over the deniedGroups. That means users can use a password when being members of the deniedGroups but also being members of the separate allowedGroups.

<init-param>
<param-name>groupAllowOverDeny</param-name>
<param-value>true</param-value>
</init-param>

allowSysadmins

By default, all users with Sysadmin privileges can use a password to log in. This can be changed by setting allowSysadmins to false.

<init-param>
    <param-name>allowSysadmins</param-name>
    <param-value>false</param-value>
</init-param>

When setting this to false and not configuring allowedGroups properly, password authentication is disabled completely!

This can make the instance completely inaccessible if other authentication methods fail (e.g. if the SAML Identity Provider fails)

If the password access for System-Administrators is blocked, using Jira as a directory for other applications like Confluence will no longer work.

Caveats/ Limitations

Jira

When using a custom authenticator like the deny password authenticator, Jira will automatically disable Web Sudo.
Atlassian doesn't support this for Jira, only for Confluence (see below) and they decided to not do the same in Jira: https://jira.atlassian.com/browse/JRASERVER-62615

Confluence

If you install the deny password authenticator in Confluence, some functionality that relies on password authentication is automatically disabled:

  • Web Sudo
  • Captcha
  • Password confirmation on email change

To overwrite this behaviour, please use the password.confirmation.disabled as a system property, set to false: https://confluence.atlassian.com/doc/configuring-system-properties-168002854.html
This is an extract of a Linux setenv.sh file, containing that additional parameter in line 17

# Set the JVM arguments used to start Confluence.
# For a description of the vm options of jdk 8, see:
# http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
# For a description of the vm options of jdk 11, see:
# https://docs.oracle.com/en/java/javase/11/tools/java.html

CATALINA_OPTS="-XX:+IgnoreUnrecognizedVMOptions ${CATALINA_OPTS}"
CATALINA_OPTS="-XX:-PrintGCDetails -XX:+PrintGCDateStamps -XX:-PrintTenuringDistribution ${CATALINA_OPTS}"
CATALINA_OPTS="-Xlog:gc+age=debug:file=$LOGBASEABS/logs/gc-`date +%F_%H-%M-%S`.log::filecount=5,filesize=2M ${CATALINA_OPTS}"
CATALINA_OPTS="-Xloggc:$LOGBASEABS/logs/gc-`date +%F_%H-%M-%S`.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=2M ${CATALINA_OPTS}"
CATALINA_OPTS="-XX:G1ReservePercent=20 ${CATALINA_OPTS}"
CATALINA_OPTS="-Djava.awt.headless=true ${CATALINA_OPTS}"
CATALINA_OPTS="-Datlassian.plugins.enable.wait=300 ${CATALINA_OPTS}"
CATALINA_OPTS="-Xms1024m -Xmx1024m -XX:+UseG1GC ${CATALINA_OPTS}"
CATALINA_OPTS="-Dsynchrony.enable.xhr.fallback=true ${CATALINA_OPTS}"
CATALINA_OPTS="-Dorg.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE=32768 ${CATALINA_OPTS}"
CATALINA_OPTS="-Dpassword.confirmation.disabled=false ${CATALINA_OPTS}"
CATALINA_OPTS="-Djava.locale.providers=JRE,SPI,CLDR ${CATALINA_OPTS}"
CATALINA_OPTS="${START_CONFLUENCE_JAVA_OPTS} ${CATALINA_OPTS}"
CATALINA_OPTS="-Dconfluence.context.path=${CONFLUENCE_CONTEXT_PATH} ${CATALINA_OPTS}"
CATALINA_OPTS="-Djdk.tls.server.protocols=TLSv1.1,TLSv1.2 -Djdk.tls.client.protocols=TLSv1.1,TLSv1.2 ${CATALINA_OPTS}"
CATALINA_OPTS="-XX:ReservedCodeCacheSize=256m -XX:+UseCodeCacheFlushing ${CATALINA_OPTS}"

export CATALINA_OPTS
CODE

Please refer to this ticket for more information.