Skip to content

Instantly share code, notes, and snippets.

@mondain
Last active September 19, 2025 19:24
Show Gist options
  • Select an option

  • Save mondain/3d4067393311d2033add171f85ab6717 to your computer and use it in GitHub Desktop.

Select an option

Save mondain/3d4067393311d2033add171f85ab6717 to your computer and use it in GitHub Desktop.
Web Application Authentication in Red5

To provide exclusion for WISH URI, add this to your web.xml as well if you're adding security to live

<!-- Public resources: explicitly marked as accessible -->
<security-constraint>
    <web-resource-collection>
        <web-resource-name>No auth area</web-resource-name>
        <url-pattern>/whip/*</url-pattern>
        <url-pattern>/whep/*</url-pattern>
    </web-resource-collection>
    <auth-constraint />
    <user-data-constraint>
        <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
</security-constraint>
<?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:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd">
<!-- War deployer removed (no longer configured via Spring)-->
<!-- Transports for HTTP/S and WS/S
Connection properties available for TomcatConnector in Red5 2.0.10:
protocols="TLSv1.2,TLSv1.3"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
-->
<bean id="tomcat.server" class="org.red5.server.tomcat.TomcatLoader" depends-on="context.loader" lazy-init="true">
<property name="secureEnabled" value="${secure.enabled}" />
<property name="websocketEnabled" value="${websocket.enabled}" />
<property name="webappFolder" value="${red5.root}/webapps" />
<property name="connectors">
<list>
<bean name="httpConnector" class="org.red5.server.tomcat.TomcatConnector">
<property name="protocol" value="org.apache.coyote.http11.Http11Nio2Protocol" />
<property name="address" value="${http.host}:${http.port}" />
<property name="redirectPort" value="${https.port}" />
<property name="connectionProperties">
<map>
<entry key="maxHttpHeaderSize" value="${http.max_headers_size}"/>
<entry key="maxKeepAliveRequests" value="${http.max_keep_alive_requests}"/>
<entry key="keepAliveTimout" value="-1"/>
<entry key="useExecutor" value="true"/>
<entry key="maxThreads" value="${http.max_threads}"/>
<entry key="acceptCount" value="100"/>
<entry key="acceptorThreadCount" value="${http.acceptor_thread_count}"/>
<entry key="processorCache" value="${http.processor_cache}"/>
<entry key="connectionTimeout" value="20000"/>
<entry key="maxConnections" value="-1"/>
<entry key="relaxedQueryChars" value="[,]"/>
<entry key="useLowerCaseHeaders" value="false"/>
</map>
</property>
</bean>
<bean name="httpsConnector" class="org.red5.server.tomcat.TomcatConnector">
<property name="secure" value="true" />
<property name="protocol" value="org.apache.coyote.http11.Http11Nio2Protocol" />
<property name="address" value="${http.host}:${https.port}" />
<property name="redirectPort" value="${http.port}" />
<property name="connectionProperties">
<map>
<entry key="keystoreType" value="JKS" />
<entry key="keystoreFile" value="${rtmps.keystorefile}" />
<entry key="keystorePass" value="${rtmps.keystorepass}" />
<entry key="truststoreType" value="JKS" />
<entry key="truststoreFile" value="${rtmps.truststorefile}" />
<entry key="truststorePass" value="${rtmps.truststorepass}" />
<entry key="allowUnsafeLegacyRenegotiation" value="false" />
<entry key="maxHttpHeaderSize" value="${http.max_headers_size}"/>
<entry key="maxKeepAliveRequests" value="${http.max_keep_alive_requests}"/>
<entry key="keepAliveTimout" value="-1"/>
<entry key="useExecutor" value="true"/>
<entry key="maxThreads" value="${http.max_threads}"/>
<entry key="acceptorThreadCount" value="${http.acceptor_thread_count}"/>
<entry key="processorCache" value="${http.processor_cache}"/>
<entry key="connectionTimeout" value="20000"/>
<entry key="relaxedQueryChars" value="[,]"/>
<entry key="useLowerCaseHeaders" value="false"/>
</map>
</property>
</bean>
</list>
</property>
<property name="baseHost">
<bean class="org.apache.catalina.core.StandardHost">
<property name="name" value="${http.host}" />
</bean>
</property>
<property name="valves">
<list>
<bean id="valve.access" class="org.apache.catalina.valves.AccessLogValve">
<property name="directory" value="log" />
<property name="prefix" value="${http.host}_access" />
<property name="suffix" value=".log" />
<property name="pattern" value="common" />
<property name="rotatable" value="true" />
</bean>
</list>
</property>
<property name="realm">
<bean class="org.apache.catalina.realm.MemoryRealm" />
</property>
</bean>
</beans>

Red5 Web Application Authentication

Authentication for Red5 webapps may be accomplished with the following examples below, these are the most simple examples and are not intended for public production use. Change roles, users, and passwords before using this on your site. For production, consider realms backed by a database (JDBCRealm) or LDAP (JNDIRealm). MemoryRealm stores cleartext passwords and is best suited for testing or internal use.

Add a realm to Red5's embedded Tomcat server

We're using the MemoryRealm realm provided by Tomcat, due to its ease-of-use and defaults. In embedded Red5, Tomcat’s UserDatabaseRealm requires a JNDI-bound UserDatabase resource, which isn’t available out-of-the-box. MemoryRealm avoids that dependency and directly reads conf/tomcat-users.xml. To get started, place this property within the tomcat.server bean in your conf/jee-container.xml:

<property name="realm">
    <bean class="org.apache.catalina.realm.MemoryRealm" />
</property>

The complete tomcat.server bean after adding the realm looks like this:

<bean id="tomcat.server" class="org.red5.server.tomcat.TomcatLoader" depends-on="context.loader" lazy-init="true">
    <property name="secureEnabled" value="${secure.enabled}" />
    <property name="websocketEnabled" value="${websocket.enabled}" />
    <property name="webappFolder" value="${red5.root}/webapps" />
    <property name="connectors">
        <list>
            <bean name="httpConnector" class="org.red5.server.tomcat.TomcatConnector">
                <property name="protocol" value="org.apache.coyote.http11.Http11Nio2Protocol" />
                <property name="address" value="${http.host}:${http.port}" />
                <property name="redirectPort" value="${https.port}" />
                <property name="connectionProperties">
                    <map>
                        <entry key="maxHttpHeaderSize" value="${http.max_headers_size}"/>
                        <entry key="maxKeepAliveRequests" value="${http.max_keep_alive_requests}"/>
                        <entry key="keepAliveTimout" value="-1"/>
                        <entry key="useExecutor" value="true"/>
                        <entry key="maxThreads" value="${http.max_threads}"/>
                        <entry key="acceptCount" value="100"/>
                        <entry key="acceptorThreadCount" value="${http.acceptor_thread_count}"/>
                        <entry key="processorCache" value="${http.processor_cache}"/>
                        <entry key="connectionTimeout" value="20000"/>
                        <entry key="maxConnections" value="-1"/>
                        <entry key="relaxedQueryChars" value="[,]"/>
                        <entry key="useLowerCaseHeaders" value="false"/>
                    </map>
                </property>
            </bean>
            <bean name="httpsConnector" class="org.red5.server.tomcat.TomcatConnector">
                <property name="secure" value="true" />
                <property name="protocol" value="org.apache.coyote.http11.Http11Nio2Protocol" />
                <property name="address" value="${http.host}:${https.port}" />
                <property name="redirectPort" value="${http.port}" />
                <property name="connectionProperties">
                    <map>
                        <entry key="keystoreType" value="JKS" />
                        <entry key="keystoreFile" value="${rtmps.keystorefile}" />
                        <entry key="keystorePass" value="${rtmps.keystorepass}" />
                        <entry key="truststoreType" value="JKS" />
                        <entry key="truststoreFile" value="${rtmps.truststorefile}" />
                        <entry key="truststorePass" value="${rtmps.truststorepass}" />
                        <entry key="allowUnsafeLegacyRenegotiation" value="false" />
                        <entry key="maxHttpHeaderSize" value="${http.max_headers_size}"/>
                        <entry key="maxKeepAliveRequests" value="${http.max_keep_alive_requests}"/>
                        <entry key="keepAliveTimout" value="-1"/>
                        <entry key="useExecutor" value="true"/>
                        <entry key="maxThreads" value="${http.max_threads}"/>
                        <entry key="acceptorThreadCount" value="${http.acceptor_thread_count}"/>
                        <entry key="processorCache" value="${http.processor_cache}"/>
                        <entry key="connectionTimeout" value="20000"/>
                        <entry key="relaxedQueryChars" value="[,]"/>
                        <entry key="useLowerCaseHeaders" value="false"/>
                    </map>
                </property>
            </bean>
        </list>
    </property>
    <property name="baseHost">
        <bean class="org.apache.catalina.core.StandardHost">
            <property name="name" value="${http.host}" />
        </bean>
    </property>
    <property name="valves">
        <list>
            <bean id="valve.access" class="org.apache.catalina.valves.AccessLogValve">
                <property name="directory" value="log" />
                <property name="prefix" value="${http.host}_access" />
                <property name="suffix" value=".log" />
                <property name="pattern" value="common" />
                <property name="rotatable" value="true" />
            </bean>
        </list>
    </property>
    <property name="realm">
        <bean class="org.apache.catalina.realm.MemoryRealm" />
    </property>
</bean>

Go here to learn more about other realms straight from Tomcat.

Configure credentials

This covers the MemoryRealm to match our example herein. The MemoryRealm is a simple demonstration implementation of the Tomcat Realm interface. It is not designed for production use. At startup time, MemoryRealm loads information about all users, and their corresponding roles, from an XML document (by default, this document is loaded from conf/tomcat-users.xml. Changes to the data in this file are not recognized until Red5 is restarted.

User File Format

The users file (by default, conf/tomcat-users.xml must be an XML document, with a root element <tomcat-users>. Nested inside the root element will be a <user> element for each valid user, consisting of the following attributes:

  • name - Username this user must log on with.
  • password - Password this user must log on with (in clear text if the digest attribute was not set on the <Realm> element, or digested appropriately as described here otherwise).
  • roles - Comma-delimited list of the role names associated with this user.

Example file contents:

<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">
    <role rolename="user"/>
    <user username="red5user" password="red5pass" roles="user"/>
</tomcat-users>

Note: You must restart Red5 after editing tomcat-users.xml. MemoryRealm only loads the file at startup.

Adding Security to Web Applications

After the JEE part is configured, one must add security to any webapps where required or they will continue with default openness. The example below is for a webapp named webrtcexamples located in webapps/webrtcexamples on a Red5 Pro Server. Normally this webapp is not loaded as a JEE application and exists as a vanilla website on the server; here we will add the WEB-INF subdirectory and a webapp descriptor file, our full path would then be webapps/webrtcexamples/WEB-INF/web.xml; here are the files contents:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <display-name>webrtcexamples</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
    <!-- Authentication method -->
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>ExampleRealm</realm-name>
    </login-config>
    <!-- Declare the role -->
    <security-role>
        <role-name>user</role-name>
    </security-role>
    <!-- Protect everything under /* -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Secure Area</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <!-- Require a role -->
        <auth-constraint>
            <role-name>user</role-name>
        </auth-constraint>
    </security-constraint>
    <!-- Additional security constraints -->
	<security-constraint>
		<web-resource-collection>
			<web-resource-name>Forbidden</web-resource-name>
			<url-pattern>/WEB-INF/*</url-pattern>
		</web-resource-collection>
		<auth-constraint />
	</security-constraint>
</web-app>

The various XML nodes in play are:

  • login-config - the authentication method to be used; BASIC will cause a browser pop-up expecting credentials. Since this isn't using more complicated realms like JNDI, the ExampleRealm is merely a place holder.
  • security-role - a role specified in the conf/tomcat-users.xml file
  • security-constraint - triggers the authentication enforcement, the url-pattern denotes the path being protected with the example /* implying the entire site under webrtcexamples

Note: BASIC auth is the browser popup, and if one wants custom login pages they can switch to FORM; additional details are outside this scope.

The final constraint is standard for protecting webapp private information.

<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users xmlns="http://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">
<role rolename="user"/>
<user username="red5user" password="red5pass" roles="user"/>
</tomcat-users>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment