Setup Google Authentication in Nginx with Ansible
TL;DR :
- Using Google authentication in nginx is a thing,
- In this blog post I explain how it can be built from source code in an amazonlinux container and share the ansible configuration to set it up.
- Also I show how Google authentication can be used beyond
Hello world
with a few examples.
Motivation
User management is a problem. Especially if you are trying to accomplish a simple task but it requires authentication/authorization mechanism. In this case you don’t have many options, if you have time constraint then you go with Basic Authentication, which is very basic, easy to break, and not recommended to use. If you have to employ more security, then you might try to implement an authentication/user management system; which doubles the complexity of your simple system.
My current company, as well as previous ones, uses Google for company emails, therefore it’s very convenient to use these emails to authenticate people.
Installation Steps
I will show briefly what is required to install here, you can find the exact installation steps in my ansible configuration from here. Requirements for nginx with google authentication are:
- nginx with lua support
- cjson
- resty.http
I have extra a few requirements for nginx which are required almost all applications:
- ngx devel kit module
- http ssl module
At the time of this blogpost was published, following versions were available & stable for above requirements:
- nginx-1.12.2
- openresty-lua-nginx-module-0.10.11
- simplresty-ngx-devel-kit-0.3.0
- lua-cjson-2.1.0
- lua-resty-http-0.12
The download, extraction, source building steps can be found in my ansible configuration.
Nginx installation
Assuming the steps in my ansible configuration has been followed, after extracting & building the sources, we need to configure nginx to run with lua:
export LUAJIT_LIB=/opt/nginx-source/luajit-2.0.5/lib
export LUAJIT_INC=/opt/nginx-source/luajit-2.0.5/include/luajit-2.0
./configure --prefix=/opt/nginx \
--with-ld-opt="-Wl,-rpath,/opt/nginx-source/luajit-2.0.5/lib" \
--add-module=/opt/nginx-source/ngx_devel_kit-0.3.0 \
--add-module=/opt/nginx-source/lua-nginx-module-0.10.11 \
--with-http_ssl_module
And then install nginx:
cd /opt/nginx-source/nginx-1.12.2
export LUAJIT_LIB=/opt/nginx-source/luajit-2.0.5/lib
export LUAJIT_INC=/opt/nginx-source/luajit-2.0.5/include/luajit-2.0
make install
This installation process creates nginx binary under /opt/nginx/sbin/nginx
and
all required nginx configurations under /opt/nginx/conf/
.
Google Authentication Usage
Cloudflare example is very extensive and easy to setup with the provided Docker image. Basically after adding these lines to your nginx configuration, you are done:
lua_package_path '/etc/nginx/lua/?.lua;';
server {
...
set $ngo_client_id "abc-def.apps.googleusercontent.com";
set $ngo_client_secret "abcdefg-123-xyz";
set $ngo_token_secret "a very long randomish string";
set $ngo_secure_cookies "true";
set $ngo_http_only_cookies "true";
access_by_lua_file "/etc/nginx/lua/nginx-google-oauth/access.lua";
...
}
If you have configured your Google project properly, you should be redirected to Google authentication & back again.
Only you & the people who share the same domain with you can be granted access. (except of course generic domains like @gmail.com
, I mean the company domains here.)
Let’s see some good usages now:
Selectively securing endpoints
Let’s say you have a public application and you want to secure only certain endpoints, like /admin
.
Then your nginx configuration should look like this:
lua_package_path '/etc/nginx/lua/?.lua;';
server {
...
set $ngo_client_id "abc-def.apps.googleusercontent.com";
set $ngo_client_secret "abcdefg-123-xyz";
set $ngo_token_secret "a very long randomish string";
set $ngo_secure_cookies "true";
set $ngo_http_only_cookies "true";
location /admin {
access_by_lua_file "/etc/nginx/lua/nginx-google-oauth/access.lua";
root ...;
}
location /public {
root ...;
}
...
}
By copying the access_by_lua_file
directive to under location blocks, you can make that location guarded by Google authentication.
In this example, every request going to /admin
endpoint will require Google authentication, while /public
endpoint will not.
Custom authorization
This example handles the authentication, you can implement a custom authorization mechanism by proxying the requests to a middleware:
lua_package_path '/etc/nginx/lua/?.lua;';
server {
...
set $ngo_client_id "abc-def.apps.googleusercontent.com";
set $ngo_client_secret "abcdefg-123-xyz";
set $ngo_token_secret "a very long randomish string";
set $ngo_secure_cookies "true";
set $ngo_http_only_cookies "true";
set $ngo_user "unknown@example.com";
access_by_lua_file "/etc/nginx/lua/nginx-google-oauth/access.lua";
location / {
proxy_set_header "google-user" $ngo_user;
proxy_pass 127.0.0.1:8080;
}
...
}
Assuming there is an application running at port 8080
. In this application, you can check google-user
header
and see who is making the request. Then you can use it to grant permissions to the user, or not.
I am planning to implement a simple application to showcase authorization
with Google authentication for my next blog post.
Conclusion
Google authentication within nginx made the development environment flow very effective in my current company. One less password to remember, one less user to manage, less possibility of security/password breach, and everybody is happier than a password-oriented system.