INTRODUCTION
The first few sections, below, help make sure you're set up properly. Please don't skip them, except maybe the 'get a decent text editor' section. Also, in each section (with the gracious help of
Scott Cantor) I've added URL links to the Shibboleth wiki, in case you need to dive deeper.
How does Shibboleth work?
Most explanations of Shibboleth tell you how it acts in the abstract, but not how it
works from a programming perspective. I wish sombody had written out how it works somewhere, ANYWHERE, on the internet so that I wouldn't have had to spelunk through it.
The way shib works is by running a demon called !!shibd at the same time apache (which is actually the executable !!httpd ) runs, and the apache mod you install called !!mod_shib.so knows how to talk to shibd. The shibboleth authors did this, I suspect, to decrease maintenance burden on !!shibd when apache changes (
wiki).
When web requests come in, apache directs them to mod_shib, amd/or mod_PHP, mod_passenger (ruby) or whatever language you're using. You have to configure apache to hand off the right requests to the right module (more about that later).
The daemon !!shibd looks at the file !!shibboleth2.xml to see how to act, and uses !!attribute-map.xml to know what attribs to get from the IdP(s) you're connecting to.
You tell Apache which directories are protected by shib in your !!httpd.conf files using the !!<Location> tag. It is typical, by convention, to protect the directory !![WebRoot]/shibboleth so that when a user visits it !!mod_shib and !!shibd perk up and start handling things (
wiki).
To be secure, you really should be using SSL, so you'll install that on Apache before you do anything else, and your protected directories will go into a Virtual Host that uses SSL. If this is all greek to you, I'm afraid you better go google up: SSL, self-signed certificate, and Apache Virtual Host.
In addition to protected directories, shibboleth also needs to own a directory !![WebRoot]/Shibboleth.sso/ . Underneath that directory are a bunch of things it uses to get the job done. For example, when the IdP needs to know how to talk to your site it will ask for a file called !![WebRoot]/Shibboleth.sso/Metadata which shibd will auto-magically construct and deliver. That directory and file will
never actually exist in your file system.
Another thing that happens under !!/Shibboleth.sso/ is that all the communication between shibd and the IdP happens down there, in subdirectories named things like !!/Shibboleth.sso/SAML . You can ignore that - again, shibd will do it all for you.
The last convention is that, when there are errors, shib will look for !!/shibboleth-sp/ to contain a .css file and your logo so it can draw decent error pages. But you can ignore this convention when setting up your error handling. Details below.
Once a user has logged in with the IdP, !!shibd causes apache to pass your code all the attributes you asked for with your !!"attribute-map.xml" file. The IdP will pass back only what you're authorized to see. Don't worry if you ask for too many attributes - it won't cause the process to fail. Shib passes attribs EITHER in environment vars (preferred method!), OR http request headers. Either way, you are responsible for picking them out of there with your own code.
There are more details below about what attributes to use, and what they mean, and how to read them after a login.
BTW, Scott points out "
unless you have some evidence that the Ubuntu packages have been maintained (that is to say patched), they are probably insecure. But if they're Debian packages those are typically patched."
Restarting and Logs
As you fumble your way through endless configuration and code, youwill need to restart lots of things and look at their logs to see what went wrong. And you'll forget how. So here they all are, for reference:
Apache
[Mac]
$$ sudo apachectl restart
[Ubuntu]
$$ sudo /etc/init.d/apache2 restart
(you can also use !!apachectl, but using init.d is consistent with how you will restart shibd, so I prefer it)
check it started with the log file:
$$ tail -f /private/var/log/apache2/error_log
Shibd
[Mac]
$$ sudo launchctl unload -Fw /Library/LaunchDaemons/org.macports.shibd.plist
$$ sudo launchctl load -Fw /Library/LaunchDaemons/org.macports.shibd.plist
[Ubuntu]
$$ sudo /etc/init.d/shibd restart
(BTW the init.d directory contains everything that will get auto-started when the OS boots)
check it with the log file:
$$ tail -f /opt/local/var/log/shibboleth/shibd.log
or, for just warnings,
$$ tail -f /opt/local/var/log/shibboleth/shibd_warn.log
Passenger
$$ touch [AppRoot]/tmp/restart.txt
check it with the log file:
$$ tail -f [AppRoot]/log/development.log
Get a Decent Editor
If you're not using sublime-text-2 you should go get it, and then configure it as described here:
Here are a list of must-have installs, in order:
https://github.com/mhartl/rails_tutorial_sublime_text
(command line)
(basic config)
(copy auxiliary files)
https://github.com/n00ge/sublime-text-haml-sass
http://wbond.net/sublime_packages/package_control
https://github.com/eddorre/SublimeERB
Don't forget Cmd-P for general file opening, and Cmd-Shift-P for package management.
Take care of your apache basics
Make sure you have the basics in place for Apache
edit /etc/apache2/httpd.config
ServerAdmin your.email@domain.com
ServerName [WebRoot]:80
DocumentRoot "[AppRoot]"
BEWARE: It is common to try to make a new doc root for this, but don't forget to chmod that folder to give access permission to the user that apache logs in as. In !!httpd.conf search for !!User and !!Group to determine what apache's logins are.
The commands needed to give _www access to your new directory are:
$$ sudo dscl . -append /Groups/_www GroupMembership [myUsername]
$$ sudo chown -R _www .
$$ sudo chgrp -R _www .
Make sure Apache is running with SSL
You'll have to generate your own certs and install them, then configure apache
http://blog.andyhunt.info/2011/11/26/apache-ssl-on-max-osx-lion-10-7/
The instructions below are extracted from this URL, just in case.
- Generate a host key
$$ mkdir /etc/apache2/ssl
$$ cd /etc/apache2/ssl
$$ sudo ssh-keygen -f server.key
- Create the certificate (with a so-called 'request file') - LEAVE PASSCODE BLANK or you'll regret it
$$ sudo openssl req -new -key server.key -out request.csr
$$ sudo openssl x509 -req -days 365 -in request.csr -signkey server.key -out server.crt
Here is a sample of what I put in for the request.csr file (my responses are after the colons):
Country Name (2 letter code) [AU]: !!US
State or Province Name (full name) [Some-State]: !!Texas
Locality Name (eg, city) []: !!Austin
Organization Name (eg, company) [Internet Widgits Pty Ltd]: !!YourOrganization
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []: !!https://[WebRoot]
Email Address []: !!your.email@domain.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Configure Apache
The good news is that configuring apache doesn't vary much between Mac, Ubuntu or any other operating system.
The bad news is that it is a pain. I could go on all day about how to configure apache properly - not just for Shibboleth, but in general. Do you know that most apache configs load seventy modules but only use ten? Worse yet, modern "best practices" with apache are to load and configure modules from LOTS of .conf and .load files, making it a horrible chore to actually
know what is going on with your configuration. And don't get me started on the fact that
module load order matters and yet this so-called "best practice" loads in a random, unpredictable order. Yuck.
So chances are good that your !!httpd.conf file is a huge mess. And on some systems it will be called apache.conf, or something else. You'll just have to figure things out. Sorry.
NOTE: There is a sample all-in-one !!httpd.conf file at the end of this document. Take a look if you want to see the simplest, viable configuration you can have.
- edit !![Apache]/httpd.conf
You'll probably find these in the file and uncomment each of them.
LoadModule ssl_module [Mods]/mod_ssl.so
Include [Apache]/extra/httpd-ssl.conf
- edit !![Apache]/extra/httpd-ssl.conf
Point to your certs with the lines that start with !!SSLCertificateFile, !!SSLCertificateKeyFile:
SSLCertificateFile "[Apache]/ssl/server.crt"
SSLCertificateKeyFile "[Apache]/ssl/server.key"
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
- Also check these values in !![Apache]/extra/httpd-ssl.conf
These might vary with your system, but make sure they exist in the ssl config file. They should exist OUTSIDE any virtualHost directive.
Listen 443
SSLPassPhraseDialog builtin
SSLSessionCache "shmcb:/private/var/run/ssl_scache(512000)"
SSLSessionCacheTimeout 300
SSLMutex "file:/private/var/run/ssl_mutex"
Warning: Apache's default !!httpd-ssl.conf file takes some liberties, for example forcing the existence of a custom log file with the directive !!CustomLog . You might choose to simply delete everything except what you absolutely need.
- Now on to configuring your VirtualHost. These things can be confusing, but the main thing to know is that:
* Apache will listen on a port (with the Listen [portnum] directive you set up)
* When traffic comes in on that port, apache looks at the "request url" (the first like of every HTTP request has the request url in it)
* it then looks in !!httpd.conf for a ServerName www.mysite.com directive
* If that directive is in a <VirtualHost> block on the right port, it over-rides any default directives with all the values in that block.
* This also means your virtual host inherits directives; for example, all the SSL stuff you set up will be inherited if you simply stick the SSLEngine on directive into your vhost.
So which file should you configure your virtual host in? If you're going uber-simple, put it into !!httpd.conf . On some systems it will be extras/httpd-vhost.conf and on others it should be in a file under mods-enabled/ - YMMV.
<VirtualHost *:443>
SSLEngine on
ServerName [WebRoot]
DocumentRoot "[AppRoot]"
</VirtualHost>
To test it, put an index.html file into the appropriate directory and try to access it.
- Check your work so far
$$ sudo apachectl configtest (This will tell if your config is valid, mostly)
$$ sudo apachectl restart (Do this each time you need to reboot)
You shouldn't see any major problems.
Open a web browser and navigate to https://localhost and see if you get the !!index.html file
Install shibd and mod_shib on Apache
This will vary wildly depending on your operating system, so read carefully and don't be surprised if I get a directorty name wrong. Also, it is
critical that you know which version of shibboleth you are dealing with. If you go looking online for help, as I did, you'll see instructions for version 2.3.1, or 2.5, or whatever, but nobody will ever mention which version. And things you do for a later version will be
wrong for an earlier version!
In my case, after struggling to get a 2.5 install working, I later discovered that Ubuntu's pre-packaged shibboleth install only supported up to 2.3.1, and there were a lot of differences bwteen the versions, especially in the !!shibboleth2.xml file.
Get Shibboleth on Mac OSX
For reference, here is the 'official' how-to on installing a Shib SP on Mac. But parts of it didn't work for me, so I wrote instructions below. I recommend following the instructions at this page
and reading my instructions below.
https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPMacInstall
In summary, here is what you need to do:
- Get MacPorts
* visit http://www.macports.org/
* click 'installing MacPorts' in the left-hand menu
* follow the instructions
* Try to use the .pkg installer if possible
* Don't forget you might need xcode from https://developer.apple.com/xcode/
* AND before FIRST USE you might have to accept the xcode EULA by running xcodebuild -license
- Get Shibboleth
These instructions differ slightly from those online because the 'boost' library is a pig.
$$ sudo -s
$$ port install curl +ssl
$$ sudo port -v install boost build.jobs=1 (see below)
$$ port install shibboleth
WARNING:
To get boost to build properly, I had to use that crazy build.jobs=1 parameter, and it took two hours to finish.
Get Shibboleth on Ubuntu
This can be easy, or very hard. It's a deal with the devil really: take the easy way (using apt-get) and you end up with an older v2.3.1, harder to configure version of Shibboleth. Take the hard way (by manually installing v2.5) and your shib configuration just got a lot easier.
I'm only going to cover the easy install here. Sorry.
$$ sudo apt-get install shibboleth-sp2-schemas libshibsp-dev
$$ sudo apt-get install libshibsp-doc libapache2-mod-shib2 opensaml2-tools
You might have to generate your own keys after doing this, but I found that I didn't have to do so for my already-installed version of shibboleth.
- Make Apache aware of Shibboleth
BEWARE: Ignore the instructions at the shib wiki /NativeSPMacInstall/ page and do NOT blindly Include [Shib]/apache22.config in !!httpd.conf. Instead, edit !!httpd.conf yourself step-by-step so you don't end up with an insecure or double-configured apache.
edit !!/etc/apache2/httpd.conf
Tell apache where to find the mod_shib you just installed (assumes you are using Apache 2.2)
LoadModule mod_shib [Shib]/mod_shib_22.so
WARNING: Module load order matters! Make sure shib is loaded FIRST before php, ruby, passenger, or whatever language you're using.
Install and configure shibd
The way shib works is by running a demon called shibd at the same time apache runs, and then !!mod_shib.so knows how to talk to !!shibd. They did this to decrease maintenance burden on !!mod_shib when apache changes.
- Configure [Shib]/shibboleth2.xml
This file tells !!mod_shib and !!shibd all about your setup. It is probably already full of data, but be careful - you need to configure it to know which IdP you're connecting to.
Also note that there are many IdP's that have scripts to generate your shibboleth2.xml file for you, but of course the setup they produce is only for them. AND beware that if they're generating for 2.5 and you're on 2.3.1 you can use what they created.
UT's generator: http://utdirect.utexas.edu/shibboleth/shibboleth_config.WBX
WARNING: If you are using an automatically-generated shibboleth2.xml file, you still need to read through this - in particular, pay attention to "forceAuthn" and error handling.
- Make a clean copy of the file:
$$ cd [Shib]
$$ cp shibboleth2.xml.dist shibboleth2.xml
- Make sure the 'entityID' points at your machine:
<ApplicationDefaults REMOTE_USER="eppn persistent-id targeted-id" entityID="https://[WebRoot]/shibboleth">
Now you would think that because the entityID is a URL, that maybe that URL has to exist on
your server. NOPE! It's just an identifier, pure and simple. It might as well be a GUID for
all shibd cares (but don't try that!) - (wiki)
- Configure the IdP you want to use.
For example, to use the handy testshib.org IdP you would do this:
<SSO entityID="https://idp.testshib.org/idp/shibboleth">SAML2 SAML1</SSO>
or if you wanted to use University of Texas:
<SSO entityID="https://idp.its.utexas.edu/idp/shibboleth" discoveryURL="https://idp.its.utexas.edu/idp/DS/WAYF" discoveryProtocol="SAMLDS" forceAuthn="true"> SAML2 SAML1 </SSO>
- Also, setup where the metadata will come from:
<MetadataProvider type="XML" uri="http://www.testshib.org/metadata/testshib-providers.xml" backingFilePath="testshib-two-idp-metadata.xml" reloadInterval="180000"/>
or if you wanted to use University of Texas:
<MetadataProvider type="XML" reloadInterval="86400" backingFilePath="/etc/shibboleth/UTfed-metadata.xml" uri="https://idm.utsystem.edu/downloads/UTfed-metadata.xml"/>
- Pray that all the <Handler> tags are correct. No idea what these do.
- Check your Certs
Remember that although SSL creates a secure COMMUNICATION layer, shib has it's own additional certs that it uses to talk to IdP's. That is the <CredentialResolver> tag.
- Make sure your error handling will work properly.
<Errors styleSheet="/shibboleth-sp/main.css" logoLocation="/shibboleth-sp/logo.jpg" supportContact="your.email@domain.com"/>
You need to point 'styleSheet' and 'logoLocation' to real assets on your server. You can make your own /shibboleth-sp/ directory, or just point them to other assets you've already got. For example, mine are pointed to:
styleSheet="/stylesheets/base.css"
logoLocation="/images/appsoma_logo.png"
- Force Authentication if needed
If you aren't exactly protecting resources with Shibboleth, but are instead using it to link to a logal account (as I was) you will learn that "logging out" doesn't exist. So if a new person comes to the machine, you need to make sure they don't get logged in as the prior user! The way to do this is for force the user to have to re-login every time their browser points to your protected shibboleth directory.
To make this work, in the <SSO> tag add the element:
forceAuthn="true"
- Configure your Metadata file
If you read the instructions at the shibboleth site they seem to VERY STRONGLY IMPLY that you need to construct your own Metadata file for an SP. It is PARTLY true.
To start off with, let !![WebRoot]/Shibboleth.sso/Metadata provide a Metadata file for you. !!shibd will create one on-the-fly and serve it to you auto-magically.
So, if somebody asks you for your "SP Metadata File", just visit:
https://[WebRoot]/Shibboleth.sso/Metadata
and you'll be served your own Metadata file.
Scott points out: "Constructing your own metadata file is often a requirement for
effective use of SAML... there are substantial operational constraints when you don't control metadata independently of a configuration."
When you might need to generate a metadata file by hand, whether for SAML config or because you need to give it to your IdP and your shibd setup is too broken to serve the Metadata file as described above. In a case like that, the easiest way to generate the Metadata file is to use the bash script that comes with shibboleth:
$$ cd [Shib]
$$ sudo bash metagen.sh -h [WebRoot] > Metadata_myUniqueSiteName
Configure shibboleth attributes
Edit the file !![Shib]/attribute-map.xml and uncomment
any attributes that you might need. Don't forget that most institutions
will want you to confer with them and tell them which attribs you need - if you
don't, your code will ask for them and get nothing.
- About Attributes
There are two pieces to an attribute - a long unique 'name' and a short, more
readable 'id'. It's the 'id' that you'll use in your code to access these things.
<Attribute name="[LongPainfulUniqueName]" id="[ShortIdYouWillUseInYourCode]"/>
A wrinkle: Because there are multiple versions of SAML/Shibboleth, common attribs have
TWO definitions. Uncomment them BOTH. For example:
<Attribute name="urn:mace:dir:attribute-def:mail" id="mail"/>
<Attribute name="urn:oid:0.9.2342.19200300.100.1.3" id="mail"/>
The fact is that MOST attribs are common across institutions, and you can typically
just find them and un-comment them in attribute-map.xml (wiki)
- Picking Attributes
So, which attribs do you want? Well, if you're going for a simple login situation,
I suggest:
!!eppn - This is a unique identifier for a user. It happens to stand for "eduPersonPrincipalName"
which isn't really a name. It's a UID. Most institutions make this !!username@institution.edu
!!mail - The email address
!!sn - stands for 'surname' which is the person's last name
!!givenName - the person's first name
!!affiliation - which institution is the person from
There is obviously a lot more (wiki), but this is a start.
Test !!shibd to make sure it will launch
Here is the Shib wiki shibd command line reference: https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPshibd
Here is the Ubuntu shibd command line reference: http://manpages.ubuntu.com/manpages/natty/man8/shibd.8.html
- Run this by hand and see if there are any errors:
$$ sudo /opt/local/sbin/shibd -f -c [Shib]/shibboleth2.xml -p /opt/local/var/run/shibboleth/shibd.pid -t
(the -t means 'check the configuration and give me errors if it is broken')
When you get errors you can inspect them here:
/opt/local/var/log/shibboleth/
- Once the -t version checks out, try to run it with this:
$$ sudo /opt/local/sbin/shibd -f -c [Shib]/shibboleth2.xml -p /opt/local/var/run/shibboleth/shibd.pid
(if it complains it can't start it's listener, reboot.)
- Make sure the shibd demon will start automatically when your machine starts
[Mac]
$$ sudo launchctl load -Fw /Library/LaunchDaemons/org.macports.shibd.plist
(this will also start the demon at the same time)
... and conversely to uninstall it when needed ...
$$ sudo launchctl unload -Fw /Library/LaunchDaemons/org.macports.shibd.plist
By the way, in the spirit of "No Mysteries" there is a file link at the location above. It is XML and tells how to launch the shibd demon. The original lives at !!/opt/local/etc/LaunchDaemons/org.macports.shibd What is really happening is that MacPorts' launcher is, in turn, launching shibd. The raw command line to this appears to be:
/opt/local/bin/daemondo --label=shibd --start-cmd /opt/local/sbin/shibd -F -f -p /opt/local/var/run/shibboleth/shibd.pid
You don't get to kill !!daemondo, because it runs and auto-relaunches from Apple's !!launchd service (known as !!xinetd in normal Linux land)
[Ubuntu]
$$ sudo chmod +x /etc/init.d/shibd
$$ sudo update-rc.d shibd defaults
To restart shibd see the instructions near the top of this file.
- Test that shibd thinks your configuration is OK
$$ shibd -check
Setup a shibboleth-protected directory
- edit !!/etc/apache2/extra/httpd-ssl.conf
Configure a shibboleth directory by inserting the following lines into the <VirtualHost> within the SSL conf file. This assumes the directory !!/shibboleth is the dir you want protected with shib. (wiki)
I tried the !!SetHandler directive, which forces Apache to use !!mod_shib.so when processing this location, but it did bad things with the content type. I've seen some people refer to it online as helpful for force !!shibd to handle a directory or location. YMMV.
<Location /auth/shibboleth/callback>
# this Location directive is what redirects apache over to the IdP.
AuthType shibboleth
ShibRequestSetting requireSession 1
require valid-user
</Location>
More details here:
https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPApacheConfig
- Important Detail
In !!httpd.conf place this directive just below the !!DocumentRoot directive:
UseCanonicalName on
TEST IT
Open a browser and visit https://[WebRoot]/shibboleth/index.html
NOTE: I experienced a bug in which Shibboleth+Apache sometimes don't seem to respect the DirectoryIndex directive! If you get this, something is fundamentally wrong (never figured out what). Check your Apache config against the one at the end of this tutoprial.
You should now be done configuring Apache, SSL and Shib. If you code in Ruby, see below for more.
Mike Flynn says: There is another command you can execute against the SP to see what the IdP is sending - /shibboleth.sso/Session. That will give you session details and the names of the attributes passed in that session. Very handy to see what an IdP is sending. You can also configure it to display the values passed in the attributes by updating shibboleth2.xml's Status handler stanza:
<!-- Status reporting service. -->
<Handler type="Session" Location="/Session" showAttributeValues="true" />
INTEGRATE OMNI-AUTH into your APP
Let me apologize in advance for the fact that this is more of a sketch than complete instructions on how to do this. You'll get Passenger and Omniauth installed, and get most of your programming done, but you'll have to take things the 'last mile' yourself, by truly understanding the code and integrating with your own solution.
Install Passenger
- install ruby and rubygems (you probably already have them)
- Get the Passenger gem
$$ sudo gem install passenger
$$ rvmsudo passenger-install-apache2-module (this differs from what it says on the phusion passenger website)
- Install passenger into apache
Add the following lines into httpd.conf
LoadModule passenger_module /SOMEWHERE/.rvm/gems/ruby-1.9.3-p194/gems/passenger-3.0.17/ext/apache2/mod_passenger.so
PassengerRoot /SOMEWHERE/.rvm/gems/ruby-1.9.3-p194/gems/passenger-3.0.17
PassengerRuby /SOMEWHERE/.rvm/wrappers/ruby-1.9.3-p194/ruby
- Configure hosts file
If testing locally, edit /etc/hosts to include the line
127.0.0.1 [WebRoot]
- Make apache aware of the rails project
<VirtualHost *:80>
ServerName "[WebRoot]"
DocumentRoot "[AppRoot]/public"
<Directory [AppRoot]/public>
Options Indexes FollowSymLinks MultiViews
Order allow,deny
Allow from all
AllowOverride all
Options -MultiViews
</Directory>
</VirtualHost>
Configure your project to diagnose problems
- Make sure to use settings that let you diagnose the inevitable failures.
In !!config/development.rb set
config.cache_classes = false
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
Also, if you are using the 'assets' module, include this:
config.assets.compile = true
config.assets.debug = true
- Make sure you're running in development mode.
In !!config/environment.rb add this as the very first line:
ENV['RAILS_ENV'] = 'development'
Remember that you need to restart Passenger when you make changes to the .rb files.
- Install omniauth
Install all the omni-auth gems you will need.
edit the [AppRoot]/Gemfile and add
gem 'omniauth-github'
gem 'omniauth-openid'
gem 'omniauth-shibboleth'
then run $$ bundle install
Include omniauth in the project
You'll make changes to all of the following files in [AppRoot] in order to integrate:
/config/initializers/omniauth.rb
/app/models/authorization.rb
/app/models/user.rb
/app/controllers/sessions_controller.rb
- Populate the file [AppRoot]/config/initializers/omniauth.rb with:
require 'openid/store/filesystem'
Rails.application.config.middleware.use OmniAuth::Builder do
provider :shibboleth, {
:shib_session_id_field => "Shib-Session-ID",
:shib_application_id_field => "Shib-Application-ID",
:uid_field => "eppn",
:name_field => "displayName",
:debug => false,
:extra_fields => [
:givenName,
:sn,
:eppn,
:mail,
:affiliation,
:entitlement
]
}
provider :github, "GITHUB_KEY", "GITHUB_SECRET"
end
NOTE: The so-called 'extra_fields' named here should be customized to match your attribute_map.xml file.
- create !![AppRoot]/app/models/authorization.rb
You'll notice that I'm extracting a lot of difference information from the shibboleth response. You might not need as much as this. Remember that my purpose was to make a local account,
so I contract "john smith" to "jsmith" in this code.
class Authorization < ActiveRecord::Base
attr_accessible :provider, :uid, :user_id
belongs_to :user
validates :provider, :uid, :presence => true
def self.extract_info(auth_hash)
if auth_hash == nil
return nil
end
account = auth_hash["uid"].split('@')[0]
idpdomain = auth_hash["uid"].split('@')[1]
begin
name = auth_hash["extra"]["raw_info"]["givenName"][0,1].downcase + auth_hash["extra"]["raw_info"]["sn"].downcase
rescue
name = auth_hash["uid"].split('@')[0]
end
email = auth_hash["extra"]["raw_info"]["mail"]
if email == nil
email = ""
end
return Hash["name" => name, "account" => account, "idpdomain" => idpdomain, "email" => email, "provider" => auth_hash["provider"], "uid" => auth_hash["uid"] ]
end
def self.find_via_info(info)
auth = find_by_provider_and_uid(info["provider"], info["uid"])
return auth
end
def self.create_for_user( user_id, info )
Rails.logger.debug "KD: creating auth linkage for = "+user_id.inspect
auth = create :user_id => user_id, :provider => info["provider"], :uid => info["uid"]
auth.save
return auth
end
end
- In !![AppRoot]/app/models/user.rb
make sure these are all in the declarations:
attr_accessible :email, :name
has_many :authorizations
validates :name, :email, :presence => true
and also declare:
def add_provider(auth_hash)
# Check if the provider already exists, so we don't add it twice
unless authorizations.find_by_provider_and_uid(auth_hash["provider"], auth_hash["uid"])
Authorization.create :user_id => self.id, :provider => auth_hash["provider"], :uid => auth_hash["uid"]
end
end
- Follow this tutorial:
http://net.tutsplus.com/tutorials/ruby/how-to-use-omniauth-to-authenticate-your-users/
NOTE: It doesn't mention things "everyone should know", for example:
* after you edit the Gemfile, $$ bundle install
* after you change any model, $$ rake db:migrate
* If testing with GitHub, be aware the tutorial is wrong about which parts of auth_hash hold what. You'll have to debug it yourself.
If you want to test with GitHub, be sure to sign up for an OAuth2 Application ID and Secret on the GitHub Applications Page.
https://github.com/settings/applications
* Application Name: !!whateverYouWish
* Main URL: !!http://[WebRoot]
* Callback URL: !!http://[WebRoot]/auth/github/callback
REFERENCE MATERIAL
A few handy links
Main shibboleth web site
http://shibboleth.net/
How to make a certificate:
https://www.switch.ch/aai/docs/shibboleth/SWITCH/2.3/sp/deployment/mac-ports.html#selfsignedcert
Shibboleth's X509 Keys and Cert locations:
key: [Shib]/sp-key.pem
cert: [Shib]/sp-cert.pem
A shib plugin for rails' omniauth:
https://github.com/toyokazu/omniauth_shibboleth/wiki
UT's Shib pages:
http://www.utexas.edu/its/help/shibboleth/593
Upgrade Shibboleth
$ sudo port sync
$ sudo port upgrade shibboleth
Sample httpd.conf file
This single file puts ALL directives in one place, and takes a minimalist approach to loading modules. If you're just trying to setup a simple site, use this. By the way, if your apaches setup uses !!/mods-enabled/ you might consider NOT using that directory for mod_shib.
Remember that the !!<Location> directives may vary if you're not using passenger with omniauth.
Also, this particular setup used env vars, so anywhere you see ${...} it is an environment variable reference. Here are the env vars we happened to be using:
APACHE_RUN_USER=www-data
APACHE_RUN_GROUP=www-data
APACHE_PID_FILE=/var/run/apache2.pid
APACHE_RUN_DIR=/var/run/apache2
APACHE_LOCK_DIR=/var/lock/apache2
APACHE_LOG_DIR=/var/log/apache2
### BASIC APACHE BEHAVIOR ###
LockFile ${APACHE_LOCK_DIR}/accept.lock
PidFile ${APACHE_PID_FILE}
Timeout 60
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15
User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}
NameVirtualHost *:80
Listen 80
Listen 443
DefaultType text/plain
UseCanonicalName on
### CAREFULLY SCREENED MODULES THAT WE ACTUALLY NEED ###
LoadModule authz_host_module [Mods]/mod_authz_host.so
LoadModule ext_filter_module [Mods]/mod_ext_filter.so
LoadModule filter_module [Mods]/mod_filter.so
LoadModule deflate_module [Mods]/mod_deflate.so
LoadModule env_module [Mods]/mod_env.so
LoadModule setenvif_module [Mods]/mod_setenvif.so
LoadModule status_module [Mods]/mod_status.so
LoadModule info_module [Mods]/mod_info.so
LoadModule dir_module [Mods]/mod_dir.so
LoadModule alias_module [Mods]/mod_alias.so
ServerName appsoma.com
UseCanonicalName on
### MIME TYPES ###
LoadModule mime_module [Mods]/mod_mime.so
# Unclear whether this is really needed - we SHOULD know every file's type by extension...
# LoadModule mime_magic_module [Mods]/mod_mime_magic.so
TypesConfig /etc/mime.types
AddCharset UTF-8 .utf8
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
AddType application/x-bzip2 .bz2
AddType text/html .shtml
### FALLBACK DIRECTORY BEHAVIOR ###
<Directory />
Options FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
</Directory>
DirectoryIndex index.html
### SSL ###
LoadModule ssl_module [Mods]/mod_ssl.so
SSLCertificateFile /etc/apache2/ssl/appsoma.com.crt
SSLCertificateKeyFile /etc/apache2/ssl/appsoma.com.key
SSLCertificateChainFile /etc/apache2/ssl/gd_bundle.crt
SSLRandomSeed startup builtin
SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect builtin
SSLRandomSeed connect file:/dev/urandom 512
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl
SSLSessionCache shmcb:${APACHE_RUN_DIR}/ssl_scache(512000)
SSLSessionCacheTimeout 300
SSLMutex file:${APACHE_RUN_DIR}/ssl_mutex
SSLCipherSuite HIGH:MEDIUM:!ADH:!MD5
SSLProtocol all -SSLv2
### SHIBBOLETH ###
LoadModule mod_shib [Mods]/mod_shib_22.so
### PASSENGER ###
LoadModule passenger_module /home/deploy/.rvm/gems/ruby-1.9.2-p290/gems/passenger-3.0.14/ext/apache2/mod_passenger.so
PassengerRoot /home/deploy/.rvm/gems/ruby-1.9.2-p290/gems/passenger-3.0.14
PassengerRuby /home/deploy/.rvm/wrappers/ruby-1.9.2-p290/ruby
### FIX BUSTED BEHAVIOR IN EARLY BROWSERS ###
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0
### MULTI-PROCESS SETUP ###
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
</IfModule>
<IfModule mpm_worker_module>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxClients 150
MaxRequestsPerChild 0
</IfModule>
<IfModule mpm_event_module>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxClients 150
MaxRequestsPerChild 0
</IfModule>
AccessFileName .htaccess
<Files ~ "^\.ht">
Order allow,deny
Deny from all
Satisfy all
</Files>
HostnameLookups Off
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%i\" \"%i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %O \"%i\" \"%i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%i -> %U" referer
LogFormat "%i" agent
<VirtualHost *:80>
ServerName [WebRoot]
DocumentRoot [AppRoot]
<Directory [AppRoot]>
Allow from all
Options -MultiViews
</Directory>
<Location "/Shibboleth.sso">
SetHandler shib-handler
PassengerEnabled off
</Location>
<Location /auth/shibboleth/callback>
AuthType shibboleth
ShibRequestSetting requireSession 1
Require valid-user
</Location>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost _default_:443>
ServerAdmin you@domain.com
ErrorDocument 503 /503.html
ServerName [WebRoot]
DocumentRoot [AppRoot]
<Directory [AppRoot]>
Allow from all
Options -MultiViews
</Directory>
<Location "/Shibboleth.sso">
SetHandler shib-handler
PassengerEnabled off
</Location>
<Location /auth/shibboleth/callback>
AuthType shibboleth
ShibRequestSetting requireSession 1
Require valid-user
</Location>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
<FilesMatch "\.(shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
BrowserMatch "MSIE [2-6]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>