Rapid Connect Integration

Integration Examples


1. JWT Code Examples

The following code examples have been developed by AAF and may assist your understanding when writing your own integration code. We have provided code written in Ruby, Python and PHP.

Ruby

  require 'sinatra'
  require 'json'
  require 'json/jwt'
   
  use Rack::Session::Pool, :expire_after => 3600
   
  get '/' do
    erb :index
  end
   
  get '/welcome' do
    if session[:attributes]
      @attributes = session[:attributes]
      @jwt = session[:jwt]
      erb :welcome
    else
      redirect '/'
    end
  end
   
  get '/logout' do
    session.clear
    redirect '/'
  end
   
  post '/auth/jwt' do
    jws = params[:assertion]
   
    if jws
      begin
        jwt = JSON::JWT.decode(jws.to_s, "SECRET")
   
        # In a complete app we'd also store and validate the jti value to ensure there is no replay attack
        if jwt['iss'] == 'https://rapid.aaf.edu.au' && jwt['aud'] == 'https://aaf-echo.herokuapp.com' && 
           Time.now > Time.at(jwt['nbf']) && Time.now < Time.at(jwt['exp'])
          attributes = jwt['https://aaf.edu.au/attributes']
          session[:attributes] = attributes
          session[:jwt] = jwt
          redirect '/welcome'
        else
          halt 500, "Audience or timings are invalid"
        end
      rescue Exception => e
        halt 500, "Signature was invalid or JWT was otherwise erroneous"
      end
    else
      halt 500, "JWS was not found in request"
    end
  end


Python

  import webapp2
  import os
  import jwt
  
  from webapp2_extras import sessions
  from google.appengine.ext.webapp import template
  
  config = {}
  config['webapp2_extras.sessions'] = {
      'secret_key': 'LOCAL_SECRET',
  }
  config['aaf.edu.au'] = {
    'iss': 'https://rapid.aaf.edu.au',
    'aud': 'https://aaf-echo.appspot.com',
  }
  
  class BaseHandler(webapp2.RequestHandler):
    def dispatch(self):
      self.session_store = sessions.get_store(request=self.request)
  
      try:
        webapp2.RequestHandler.dispatch(self)
      finally:
        self.session_store.save_sessions(self.response)
  
    @webapp2.cached_property
    def session(self):
        return self.session_store.get_session()
  
  class RootHandler(BaseHandler):
    def get(self):
      print self.session
      self.response.out.write(template.render('views/index.html', {}))
  
  class WelcomeHandler(BaseHandler):
    def get(self):
      if 'attributes' in self.session:
        self.response.out.write(template.render('views/welcome.html', {'attributes':sorted(self.session['attributes'].iteritems()), 'jwt':sorted(self.session['jwt'].iteritems()), 'jws':self.session['jws']}))
      else:
       self.redirect('/')
  
  class AuthHandler(BaseHandler):
    def post(self):
      try:
        # Verifies signature and expiry time
        verified_jwt = jwt.decode(self.request.POST['assertion'], "SECRET")
        
        # In a complete app we'd also store and validate the jti value to ensure there is no replay attack
        if verified_jwt['aud'] == config['aaf.edu.au']['aud'] &&
           verified_jwt['iss'] == config['aaf.edu.au']['iss']:
          self.session['attributes'] = verified_jwt['https://aaf.edu.au/attributes']
          self.session['jwt'] = verified_jwt
          self.session['jws'] = self.request.POST['assertion']
          self.redirect('/welcome')
        else:
          self.status = 403
          self.response.write('Error: Not for this audience')
      except jwt.ExpiredSignature:
        self.status = 403
        self.response.write('Error: Security cookie has expired')
  
  class LogoutHandler(BaseHandler):
    def get(self):
      self.session.clear()
      self.redirect('/')
  
  app = webapp2.WSGIApplication([
    (r'/', RootHandler),
    (r'/welcome', WelcomeHandler),
    (r'/auth/jwt', AuthHandler),
    (r'/logout', LogoutHandler),
  ], config=config)


PHP

  <?php
  
  use JWT\Authentication\JWT;
  
  Route::get('/', function()
  {
    return View::make('root');
  });
  
  Route::get('/welcome', function()
  {
    $jwt = Session::get('jwt');
    $jws = Session::get('jws');
    $attributes = $jwt->{'https://aaf.edu.au/attributes'};
    return View::make('welcome', array('jws' => $jws, 'jwt' => $jwt, 'attributes' => $attributes));
  });
  
  Route::get('/logout', function()
  {
    Session::flush();
    return Redirect::to('https://aaf-echo.gopagoda.com');
  });
  
  Route::post('/auth/jwt', function()
  {
    $jws = Input::get('assertion');
    $jwt = JWT::decode($jws, 'SECRET');
  
    # In a complete app we'd also store and validate the jti value to ensure there is no replay attack
    $now = strtotime("now");
    if( $jwt->iss == 'https://rapid.aaf.edu.au' && 
        $jwt->aud == 'https://aaf-echo.gopagoda.com' && $now > $jwt->nbf && $now < $jwt->exp) {
      Session::put('jws', $jws);
      Session::put('jwt', $jwt);
      return Redirect::to('https://aaf-echo.gopagoda.com/welcome');
    } else {
      App::abort(403,"JWS was invalid");
    }
  });


2. AAF Rapid Connect - Ruby Sample App

For a more developed example, refer to this Ruby sample application. It is provided purely for illustrative purposes. It should be noted that the code presented here should not be used as a base to build your application, but is provided to give you an idea of the concepts behind connecting a service, so you can pick it apart (everybody’s requirements are different and just cutting and pasting the code won’t generally work if you decide to do that). No effort has been made to audit the code’s security, or make it production-ready.

Up Next:

7. Integration