Skip to content

AuthenticationAuthorization

Martin Goellnitz edited this page Dec 8, 2015 · 6 revisions

Authentication and Authorization

Tangram provides a set of components to deal with authentication and authorization. While the authorization parts a very simple, then authentication architecture should be sufficient for nearly any use case. Of course the user's view to these features must be implemented suiting the needs of the web application.

The authentication and authorization in Tangram heavily relies on the pac4j project and consists of three main components:

The authorization which is tailored towards the internal needs of tangram, using a subset of the authentication, defining URLs which do not need any authorization by the base system, and defining users which are authorized to use the internal components of tangram like the importer and exporter and the [Tangram Generic Editor] (Editor).

The authentication component provides an abstraction layer for user authentication so that the web application has a uniform way to handle users and their logins. Also it supports login pages or login module on pages.

Still the authentication component is independent of the login backend in use relying on a list of so called login providers which handle the login depending on the backend in use.

Password checking Interceptor

All the remaining bits and pieces of this chapter heavily rely on an interception instance which checks each and every http call if it is authenticated.

Without this instance which provides essential handling of logged in users, non of the following components will work.

There is no additional configuration of this component except the one presented here for the other components, since it is needed for cooperation with these components.

Due to the fact that we have different types of web integation - Springframework and all the others using the Java Servlet API directly - the details of the configuration of this interceptor vary, since there are two implementations of it: One as a Servlet API Filter, one as a Springframework interceptor.

Springframework password interceptor configuration:

(TODO)

Google Guice configuration example with Guicy:

(TODO)

dinistiq configuration example:

(TODO)

Login Providers

A login provider is nothing else than a pac4j Client implementation configured for your application using the Dependency Injection framework in use. The only thing Tangram adds to you configuration is the URL handling for login callbacks so that you don't have to deal with that at all.

In the default configurations Tangram comes with the form based login and http basic authentication login providers set up. Their are only missing a user base which is added through a username to password mapping (see below).

Other logins can be easily added to be able to use twitter, google, Yahoo, and so on.

E.g. to use OAuth based twitter logins with the provider name twitter you will have to setup an instance of the class org.pac4j.oauth.client.TwitterClient with the name twitter and a secret and a key provided by twitter.

  <!-- Example twitter login client -->
  <bean id="yahooLogin" class="org.pac4j.oauth.client.TwitterClient">
    <property name="name" value="twitter"/>
    <property name="key" value="providedbytwitter"/>
    <property name="secret" value="providedbytwitter"/>
  </bean>

Yahoo OpenID based login are even easier to set up, since the only need a name attached. The Springframework example for this case is

  <!-- Example additional login client -->
  <bean id="yahooLogin" class="org.pac4j.openid.client.YahooOpenIdClient">
    <property name="name" value="yahoo"/>
  </bean>

Don't forget to add the OpenID dependecy for pac4j in this case:

dependencies {
  ...
  // For Yahoo OpenID example
  runtime "org.pac4j:pac4j-openid:$versions.pac4j"
  ...
}

For its internal purposes Tangram holds a list of login providers as a subset of the login providers configured. This list is used when checking authorizations for the use of the internal facilities and redirecting to a login when the user is not authorized.

Your application may decide to use this list or directly use any providers configured.

Authentication Service

When your application decides, that the user needs to authentice himself, you simply ask the authentication service for the login target to redirect to.

TargetDescriptor target = authenticationService.getLoginTarget(loginProviders);

You will need to pass as set of login provider names to this call so that you application can decide which external services should be allowed for the user.

If this list is just the same as you use for Tangram internally, there is a short cut in the authorization service to handle this and also deal with the handling of a return url bringing the user pack to the originating page after the login.

TargetDescriptor target = authorizationService.getLoginTarget(request);

If you don't like the default login page, you can easily override it with the standard Tangram view means.

Protected Content

No automatic redirect to login pages.

Login may be a fragment.

Be aware to hide stuff yourself.

If you don't like the default login page are login fragment you can easily override it with the standard Tangram view means.

Free URLs

Some URLs must not be considered when checking for login and redirecting to a login page in any case. These URLs are called "free URLs" and at least need to contain URLs for login handling. Be aware that also external login providers need a redirecting URL internal to your application to come back after login.

spring free URL list example from an application.xml configuration file:

<util:set id="freeUrls" value-type="java.lang.String">
    <value>${tangram.servlet.path}/stats</value>
    <value>${tangram.servlet.path}/login</value>
    <value>${tangram.servlet.path}/callback</value>
    <value>${tangram.servlet.path}/login-form</value>
    <value>${tangram.servlet.path}/redirect/form</value>
    <value>${tangram.servlet.path}/redirect/basic</value>
    <value>${tangram.servlet.path}/redirect/yahoo</value>
    <value>${tangram.servlet.path}/redirect/twitter</value>
    <value>${tangram.servlet.path}/redirect/google</value>
</util:set>

guicy free URL list from an example application's tangram.properties file:

# urls free to access
freeUrls=/s/stats,/s/login,/s/callback,/s/redirect/gae,/s/redirect/form,\
         /s/redirect/yahoo,/s/redirect/twitter,/s/login-form)

dinistiq free URL list in an application.properties example file:

freeUrls=java.util.Set(/s/stats,/s/login,/s/callback,/s/redirect/form,\
                       /s/redirect/yahoo,/s/redirect/twitter,/s/login-form)

Username Password Mapping

The basic authentication and the form authentication need a username to password mapping in order to check, if a login with username and credentials was valid.

Internally this is achieved by a simple map mapping usernames to SHA256 hashes. When using the form or basic authentication this map must be present but obviously should only contain a very minimal set of logins which do not change very often (and at least one admin login).

spring username password mapping example from an application xml configuration file:

<util:map key-type="java.lang.String" value-type="java.lang.String"
          id="usernamePasswordMapping">

  <entry key="user"
         value="04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb" />
  <entry key="admin"
         value="8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918" />

</util:map>

guicy username password mapping from an application.groovy configuration example:

log.info("configuring name password mapping")
Map<String,String> mapping = new HashMap<>()
mapping.put('admin',
            '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918')
mapping.put('user',
            '04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb')
module.bind(module.stringStringMap).
  annotatedWith(Names.named("usernamePasswordMapping")).
  toInstance(mapping)

dinistiq username password mapping in a usernamePasswordMapping.properties example:

admin=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
user=04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb

Authorization

Since the authorizations of a logged in user are a very application specific part, Tangram itself only deals with the needs of some internal components. Furthermore Tangram for this purpose only defined one role which is considered an "admin" role. Admins are allowed to use the Tangram Generic Editor and other tools from the Tangram based application.

Internally Tangram holds a list of admin users. Each user in this list is defined by the login provider to use and the username within that provider. (s.a.)

spring admin list example from an application xml configuration file:

<util:set id="adminUsers" value-type="java.lang.String">
  <value>form:admin</value>
</util:set>

guicy admin list from an example application's tangram.properties file:

# admin users to be allowed to edit content
adminUsers=form:admin,basic:admin

dinistiq admin list in an application.properties example file:

adminUsers=java.util.Set(form:admin,basic:admin)

Closed Applications

(TODO)

Dynamic Extensions

Since users need to be added and removed more often than you might want to deploy your application, users and admin role can be defined in the repository.

You have to create and maintain a code resource with the annotation users.properties and the mime type text/plain. Each line of this resource maps a username to a SHA256 hash value like in the dinistiq example for the static case above.

jeff=2e0b8d61fa2a6959d254b6ff5d0fb512249329097336a35568089933b49abdde

Also some of the users - be they defined within the application configuration or the repository - can be added to the list of users in the "admin" role. You simply have to add a mapping line "admins" with a comma separated list of additional admin users not presented statically in the application configuration.

jeff=2e0b8d61fa2a6959d254b6ff5d0fb512249329097336a35568089933b49abdde
admins=form:user,form:jeff
Clone this wiki locally