# Super Identity [![Gem Version][GV img]][Gem Version] [![Build Status][BS img]][Build Status] [![Dependency Status][DS img]][Dependency Status] [![Code Climate][CC img]][Code Climate] [![Coverage Status][CS img]][Code Climate] [Gem Version]: https://rubygems.org/gems/super-identity [Build Status]: https://codeship.com/projects/152151 [Dependency Status]: https://gemnasium.com/ausaccessfed/super-identity [Code Climate]: https://codeclimate.com/github/ausaccessfed/super-identity [GV img]: https://img.shields.io/gem/v/super-identity.svg [BS img]: https://img.shields.io/codeship/5e340b30-fd4e-0133-ed5c-7e176884dbc2/develop.svg [DS img]: https://img.shields.io/gemnasium/ausaccessfed/super-identity.svg [CC img]: https://img.shields.io/codeclimate/github/ausaccessfed/super-identity.svg [CS img]: https://img.shields.io/codeclimate/coverage/github/ausaccessfed/super-identity.svg [AAF Identity Enhancement](https://github.com/ausaccessfed/identity-enhancement-service.git) (IdE) client library for Ruby applications. ![](http://i.imgur.com/oYfImQj.png) ``` Copyright 2016, Australian Access Federation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ``` ## Installation Add the `super-identity` dependency to your application's `Gemfile`: ``` gem 'super-identity' ``` Use Bundler to install the dependency: ``` bundle install ``` ## Querying IdE from your application AAF typically uses this library along with [rapid-rack][] or [shib-rack][], although it can be used anywhere that you have access to a user's `auEduPersonSharedToken`. This example shows a simple `SubjectReceiver` class for rapid-rack which is using `SuperIdentity::Client` to query IdE: [rapid-rack]: https://github.com/ausaccessfed/rapid-rack [shib-rack]: https://github.com/ausaccessfed/shib-rack ```ruby class SubjectReceiver # Include the client mixin, which provides the `identity_enhancements` and # `entitlements` methods. We'll be using `entitlements`. include SuperIdentity::Client # Map attributes from the attribute claim, as normal. In particular note we # have the 'auedupersonsharedtoken' here, which is needed when querying IdE. def map_attributes(_env, attrs) { shared_token: attrs['auedupersonsharedtoken'], display_name: attrs['displayname'], mail: attrs['mail'] } end # Provision a Subject based on the attributes, and call the `assign_roles` # method defined below. def subject(_env, attrs) subject = Subject.find_or_initialize_by(shared_token: attrs[:shared_token]) assign_roles(subject) subject.update!(attrs) end # Query IdE, and set the admin flag on the Subject based on the presence of # the entitlement we're using for authorization. def assign_roles(subject) # Here, `values` is an Array of String values which represent the # entitlements that were returned from IdE. values = entitlements(subject.shared_token) # Usually you'd do something more sophisticated, but boolean access control # works fine in a README :) subject.admin = values.include?('urn:mace:aaf.edu.au:ide:test-only') end # SuperIdentity::Client requires that this method be defined on the including # class. To access IdE, it needs the hostname and an client keypair. The # certificate must be issued by https://certs.aaf.edu.au and granted access to # the ide[.test].aaf.edu.au, otherwise requests will fail. def ide_config { host: 'ide.test.aaf.edu.au', cert: 'config/api-client.crt', key: 'config/api-client.key' } end end ``` ## Testing code which queries IdE A test helper is provided which uses [webmock][] to return a set of entitlements which are provided by the test cases. [webmock]: https://github.com/bblimke/webmock Example setup in RSpec: ```ruby # spec/spec_helper.rb require 'webmock/rspec' RSpec.configure do |config| # Include the `TestStub` mixin, which provides the `stub_ide` method for use # by your test cases. config.include SuperIdentity::TestStub end ``` The complete test code: ```ruby # spec/lib/subject_receiver_spec.rb RSpec.describe SubjectReceiver do # The `cert` and `key` files provided here should actually exist in your # project, though they shouldn't be a real keypair, since you'd typically # commit these to source control. A self-signed certificate is recommended # here (see below for more information). let(:ide_config) do { host: 'ide.example.edu', cert: 'spec/api.crt', key: 'spec/api.key' } end # Override the real `ide_config` in the class under test. before { allow(subject).to receive(:ide_config).and_return(ide_config) } # Empty Rack env, because the code under test isn't using it. let(:env) { {} } # User attributes let(:attrs) do { shared_token: shared_token, display_name: 'Super Identity Test', mail: 'superidentity@example.edu' } end context 'when the expected entitlement is present' do # Define the shared_token and entitlements which will be returned from the # stubbed web request. let(:shared_token) { SecureRandom.urlsafe_base64(20) } let(:entitlements) { ['urn:mace:aaf.edu.au:ide:test-only'] } before do # This `stub_ide` method is provided by the `SuperIdentity::TestStub` # mixin. It takes `shared_token` and `entitlements` keyword arguments, and # sets up the response payload in webmock. stub_ide(shared_token: shared_token, entitlements: entitlements) end it 'assigns an administrator' do # Call the `SubjectReceiver` new_subject = subject.subject(env, attrs) # The `admin?` predicate will be true if the expected entitlement was # returned from IdE. expect(new_subject).to be_admin end end end ``` If you aren't familiar with generating certiicates, here's a suggested method of creating the `spec/api.crt` and `spec/api.key` files required for this test case. ``` openssl genrsa -out spec/api.key 512 openssl req -new -x509 -key spec/api.key -out spec/api.crt -subj '/CN=test_api_client/' ``` ## Contributing Refer to [GitHub Flow](https://guides.github.com/introduction/flow/) for help contributing to this project.