Showing posts for tag "codefortim"

Arbitrary Authentication with an nginx Reverse Proxy

Mon Sep 22 18:33:37 EDT 2014

  1. Setting up nginx in Front of a Domino Server
  2. Adding Load Balancing to the nginx Setup
  3. Arbitrary Authentication with an nginx Reverse Proxy
  4. Domino and SSL: Come with Me If You Want to Live

I had intended that this next part of my nginx thread would cover GeoIP, but that will have to wait: a comment by Tinus Riyanto on my previous post sent my thoughts aflame. Specifically, the question was whether or not you can use nginx for authentication and then pass that value along to Domino, and the answer is yes. One of the aforementioned WebSphere connector headers is $WSRU - Domino will accept the value of this header as the authenticated username, no password required (it will also tack the pseudo-group "-WebPreAuthenticated-" onto the names list for identification).

Basic Use

So one way to do this would be to hard-code in a value - you could disallow Anonymous access but treat all traffic from nginx as "approved" by giving it some other username, like:

proxy_set_header    $WSRU    "CN=Web User/O=SomeOrg";

Which would get you something, I suppose, but not much. What you'd really want would be to base this on some external variable, such as the user that nginx currently thinks is accessing it. An extremely naive way to do that would be to just set the line like this:

proxy_set_header    $WSRU    $remote_user;

Because nginx doesn't actually do any authentication by default, what this will do will be to authenticate with Domino as whatever name the user just happens to toss in the HTTP Basic authentication. So... never do that. However, nginx can do authentication, with the most straightforward mechanism being similar to Apache's method. There's a tutorial here on a basic setup:

http://www.howtoforge.com/basic-http-authentication-with-nginx

With such a config, you could make a password file where the usernames match something understandable to Domino and the password is whatever you want, and then use the $remote_user name to pass it along. You could expand this to use a different back-end, such as LDAP, and no doubt the options continue from there.

Programmatic Use

What had me most interested is the possibility of replacing the DSAPI login filter I wrote years ago, which is still in use and always feels rickety. The way that authentication works is that I set a cookie containing a BASE64-encoded and XOR-key-encrypted version of the username on the XPages side and then the C code looks for that and, if present, sets that as the user for the HTTP request. This is exactly the sort of thing this header could be used for.

One of the common nginx modules (and one which is included in the nginx-extras package on Ubuntu) adds the ability to embed Lua code into nginx. If you're not familiar with it, Lua is a programming language primarily used for this sort of embedding. It's particularly common in games, and anyone who played WoW will recognize its error messages from misbehaved addons. But it fits just as well here: I want to run a small bit of code in the context of the nginx request. I won't post all of the code yet because I'm not confident it's particularly efficient, but the modification to the nginx site config document is enlightening.

First, I set up a directory for holding Lua scripts - normally, it shouldn't go in /etc, but I was in a hurry. This goes at the top of the nginx site doc:

lua_package_path "/etc/nginx/lua/?.lua;;";

Once I did that, I used a function from a script I wrote to set an nginx variable on the request to the decoded version of the username in the location / block:

set_by_lua $lua_user '
	local auth = require "raidomatic.auth"
	return getRaidomaticAuthName()
';

Once you have that, you can use the variable just like any of the build-in ones. And thus:

proxy_set_header    $WSRU    $lua_user;

With that set, I've implemented my DSAPI login on the nginx site and I'm free to remove it from Domino. As a side benefit, I now have the username available for SSO when I want to include other app servers behind nginx as well (it works if you pass it LDAP-style comma-delimited names, to make integration easier).

Another Potential Use: OAuth

While doing this, I thought of another perfect use for this kind of thing: REST API access. When writing a REST API, you don't generally want to use session authentication - you could, by having users POST to ?login and then using that cookie, but that's ungainly and not in-line with the rest of the world. You could also use Basic authentication, which works just fine - Domino seems to let you use Basic auth even when you've also enabled session auth, so it's okay. But the real way is to use OAuth. Along this line, Tim Tripcony had written oauth4domino.

In his implementation, you get a new session variable - sessionFromAuthToken - that represents the user matching the active OAuth token. Using this reverse-proxy header instead, you could inspect the request for an authentication token, access a local-only URL on the Domino server to convert the token to a username (say, a view URL where the form just displays the user and expiration date), and then pass that username (if valid and non-expired) along to Domino.

With such a setup, you wouldn't need sessionFromAuthToken anymore: the normal session variable would be the active user and the app will act the same way no matter how the user was authenticated. Moreover, this would apply to non-XSP artifacts as well and should work with reader/author fields... and can work all the way back to R6.

Now, I haven't actually done any of this, but the point is one could.


So add this onto the pile of reasons why you should put a proxy server (nginx or otherwise) in front of Domino. The improvements to server and app structure you can make continue to surprise me.

Code for Tim: LESS CSS for XPages

Sun May 25 16:39:10 EDT 2014

When OpenNTF announced the "Code for Tim" initiative, I browsed Tim's GitHub repository list and one stuck out to me: the "xspless" stub repository for adding LESS CSS support to XPages. I'd latently wished for this sort of feature for a while, but hadn't yet set out down the path. It seems Tim had had the same desire, and had taken at least one more step than me.

I've decided to try my hand at making this desire a reality, and it's borne some fruit so far. I've created a fork of his project to house my attempts:

https://github.com/jesse-gallagher/xspless

So far, I've made functional drafts of two tacks:

  • A servlet plugin for Domino, in the "org.openntf.xsp.less" and ".feature" projects. This servlet is available at "/xspless" within each database (behavior outside of a database is not handled) and it processes the named file (can be a Stylesheet resource, File Resource, or file in WebContent) just-in-time and delivers the result as normal CSS
  • A builder plugin for Designer, in the "org.openntf.xsp.less.builder" and ".feature" projects. This builder adds a new Eclipse Nature to Designer (activated per-project by right-clicking the app and choosing "Add/Remove LESS CSS Nature") that compiles Stylesheet resources named in the form of "foo.less.css" (Designer automatically appends the ".css") and other File or WebContent resources named in the form of "foo.less" and stores the compiled results in the NSF

My ideal goal would be the ability to write .less files in Designer without any plugins and have the server treat them as normal CSS files with pre-processing, including them in resource-aggregation chains. Since I don't currently know how to have files processed on the fly and also included in aggregation, I created the two routes, with the latter being the likely-preferred route. Though it requires installing a plugin on each developer's system, it has the distinct advantage of the resultant files working perfectly with the normal resource aggregation pipleline of the server.

In their current state, these plugins seem to do their job. If I find out a way to hook into the resource chain on the server transparently, I'll look to improve the server plugin, but for now the Designer plugin seems promising. I plan to give a shot to using it for normal development; it will likely be a refreshing change of pace to be able to use LESS to write cleaner CSS. After a bit of testing, I'll likely create a project on OpenNTF.