NAME

Authen::NZRealMe - Integrate with RealMe login and identity services (formerly "igovt logon")

DESCRIPTION

Provides an API for integrating your application with the New Zealand RealMe login service and the RealMe assertion service (for verified identity and address details) using SAML 2.0 messaging.

Note: If you are looking at this code as an example implementation of SAML2, then you can safely ignore any code referring to "iCMS" - it is a (deprecated) supplementary API provided by the RealMe IdP, which uses WS-Trust protocols.

The distribution also includes a command-line tool called nzrealme which can be used for:

  • generating certificate/key pairs for signing and SSL encryption

  • creating/editing the Service Provider metadata file

  • creating a bundle (zip file) containing metadata and certs for upload to the IdP

  • generating AuthnRequest URLs

  • decoding/dumping AuthnRequest URLs

  • resolving SAMLart artifact responses and validating the response

Run nzrealme --help for more information about using the command-line tool.

GETTING STARTED

You cannot simply drop some config files in a directory and start authenticating users. Your agency will need to establish a Service Provider role with the logon service and complete the required integration steps. Your first step should be to make contact with the DIA/RealMe team and arrange a meeting.

CODE INTEGRATION

To integrate the RealMe login service with your application, you will need to:

  1. complete a number of configuration steps (see "CONFIGURATION" below)

  2. link this module into your application to initiate the logon (by redirecting the user to the RealMe login service) and to 'consume' the login information when the user is redirected back to your site

To understand how this module must be linked into your application, it helps to understand the SAML protocol interaction that is followed for each user logon:

  Agency Web Site                                 RealMe login server

                     .-------------------------.
                     | 1. user visits agency   |
               .-----|    web site and clicks  |
               |     |   'RealMe login' button |
               v     '-------------------------'
  .-------------------------.
  | 2. SAML AuthnRequest    |
  |    passed back to user  |-------------------------.
  |    via 302 redirect     |                         v
  '-------------------------'           .--------------------------.
   API call                             | 3. Logon service prompts |
                                   .----|    for username/password |
                                   v    '--------------------------'
                      .------------------------.
                      | 4. user enters         |
                      |    username/password   |------.
                      '------------------------'      v
                                        .--------------------------.
                                        | 5. SAML 'artifact'       |
              .-------------------------|    returned via redirect |
              v                         '--------------------------'
 .-------------------------.
 | 6. SAML ArtifactResolve |
 |    sent direct to IdP   |--------------------------.
 '-------------------------'                          v
  API call                              .--------------------------.
                                        | 7. SAML ArtifactResponse |
              .-------------------------|    sent back to SP       |
              v                         '--------------------------'
 .-------------------------.
 | 8. FLT to identify user |
 |    extracted from resp. |
 '-------------------------'
  API call returns

The RealMe login server is a SAML Identity Provider or 'IdP'. However the only attribute the login service provides is the 'Federated Logon Tag' - a unique identifier associating the user's login account with the agency web site.

The RealMe assertion server is also a SAML IdP and can be accessed using the same process described above. The response returned from the assertion server will include details of the user's verified identity and/or address (the user must first consent to sharing the requested details).

The agency web site is a SAML Service Provider or 'SP'. The Authen::NZRealMe module implements the SAML SP role on behalf of the agency web app.

To integrate this module with your application, you need to make two calls to its API: the first to generate the authentication request (step 2 above) and the second to resolve the returned artifact and return the Federated Logon Tag (FLT) which identifies the user (steps 6 thru 8).

It is your responsibility to create a persistent association in your application data store between your user record and the RealMe FLT for that user.

Authentication Request

You will add the RealMe login button image to your application templates. The button does not link directly to the RealMe login server, but instead links to your application which in turn uses the Authen::NZRealMe module to generate a SAML AuthnRequest message encoded in a URL and returns it as a 302 redirect.

The request includes a unique 'Request ID' which you must save in the user session for use when resolving the artifact response later. The example below uses generic framework method calls to save the Request ID and return the redirect URL, you will need to replace these with specific calls for the framework you are using:

  use Authen::NZRealMe;

  my $sp  = Authen::NZRealMe->service_provider(
      type      => 'login',
      conf_dir  => $path_to_config_directory
  );
  my $req = $sp->new_request(
      allow_create => 0,         # set to 1 for initial registration
      # other options here
  );

  $framework->set_state(login_request_id => $req->request_id);

  return $framework->redirect($req->as_url);  # Use HTTP status 302

Your code does not need to explicitly reference the RealMe login service domain or URL - these details are handled automatically by the configuration.

If you wish to use the assertion service rather than the login service, simply change the type parameter when creating the service_provider object:

  my $sp  = Authen::NZRealMe->service_provider(
      type      => 'assertion',
      conf_dir  => $path_to_config_directory
  );

Artifact Resolution

Once the user has provided a valid username and password to the logon service, they will be redirected back to your application and an 'artifact' will be passed in a URL parameter called 'SAMLart'. You set up which URL you want the logon service to redirect back to when you generate your service provider metadata (see "CONFIGURATION"). This URL is known as the Assertion Consumer Service or 'ACS'.

A single method call is used to:

  • generate a SAML ArtifactResolve message

  • pass it to the IdP over a backchannel

  • accept the SAML ArtifactResponse message

  • validate the assertion

  • extract and return the attributes (or error detail) in a response object

The method call will return a response object containing either the attribute details or details of the condition which meant the logon was unsuccessful. In the case of an unexpected error, the method call will generate an exception which you will need to catch and log.

A response from the login service will only include an FLT attribute, whereas a response from the assertion service may contain a number of identity attributes. See Authen::NZRealMe::ResolutionResponse for details of methods provided to access the attribute values.

  my $sp   = Authen::NZRealMe->service_provider( conf_dir => $path_to_config_directory );
  my $resp = eval {
      $sp->resolve_artifact(
          artifact   => $framework->param('SAMLart'),
          request_id => $framework->get_state('login_request_id'),
      );
  };
  if($@) {
      # handle catastrophic failures (e.g.: malformed response) here
  }
  if($resp->is_success) {
      $framework->set_state(login_flt => $resp->flt);
      # ... redirect to main menu etc
  }
  elsif($resp->is_timeout) {
      # Present logon screen again with message
  }
  elsif($resp->is_cancel) {
      # Present logon screen again with message
  }
  elsif($resp->is_not_registered) {
      # Only happens if allow_create set to false
      # and user does not have a logon for our site
  }
  else {
      # Some other failure occurred, user might like to try again later.
      # Should present $resp->status_message to user and also give contact
      # details for RealMe Help Desk
  }

Note: there are two different categories of 'error': the resolve_artifact() method might throw an exception (caught by eval, details in $@); or a response object might be returned but with $resp->is_success set to false. The details of an exception should be logged, but not displayed back to the user. In the event that your application displays the contents of $resp->status_message you should ensure that you apply appropriate HTML escaping.

For reference documentation about the Service Provider API, see Authen::NZRealMe::ServiceProvider.

CONFIGURATION

This module is configuration-driven - when making an API call, you specify the path to the config directory and the module picks up everything it needs to talk to the RealMe login service IdP (Identity Provider) from metadata files and certificate/key-pair files used for signing/encryption.

Config Files Overview

The files in the config directory use the following naming convention so you just need to point the module at the right directory. The filenames are:

metadata-login-sp.xml

This file contains config parameters for the 'Service Provider' - your end of the authentication dialog - which will talk to the login service. Once you have generated the SP metadata file (see: "Generating Config Files") you will need to provide it to the RealMe logon service to install at their end. You will need to generate separate metadata files for each of your development, staging and production environments.

metadata-login-idp.xml

The login service IdP or Identity Provider metadata file will be provided to you by RealMe/DIA. You will simply need to copy it to the config directory and give it the correct name.

metadata-assertion-sp.xml

This file is only required if you are using the assertion service and can be omitted if you are only using the login service.

This file contains config parameters for the 'Service Provider' - your end of the authentication dialog - which will talk to the assertion service. Once you have generated the SP metadata file (see: "Generating Config Files") you will need to provide it to the RealMe logon service to install at their end. You will need to generate separate metadata files for each of your development, staging and production environments.

metadata-assertion-idp.xml

This file is only required if you are using the assertion service and can be omitted if you are only using the login service.

The assertion service IdP or Identity Provider metadata file will be provided to you by RealMe/DIA. You will simply need to copy it to the config directory and give it the correct name.

metadata-icms.wsdl

This file is only required if you are both using the assertion service and need to resolve the opaque token into an FLT. It can be omitted if you are only using the login service or do not need the user's FLT.

The WSDL file will be provided to you by RealMe/DIA. You will simply need to copy it to the config directory and give it the correct name.

sp-sign-crt.pem

This certificate file is used for generating digital signatures for the SP metadata file and SAML authentication requests. For your initial integration with the RealMe login service development IdP ('MTS'), certificate key-pair files will be provided to you. For staging (ITE) and production, you will need to generate your own and provide the certificate files (not the private key files) to the RealMe login service.

sp-sign-key.pem

This private key is paired with the sp-sign-crt.pem certificate.

sp-ssl-crt.pem

This certificate is used for negotiating an SSL connection on the backchannel to the IdP artifact resolution service.

sp-ssl-key.pem

This private key is paired with the sp-ssl-crt.pem certificate.

Generating Config Files

You must first decide which directory your config files will be stored in. The examples below assume a config directory path of /etc/nzrealme.

Certificates

Once you've decided on a location, you need to generate two SSL certificates and their corresponding private keys. The first will be used for signing the SAML AuthnRequest messages and the second will be used for mutual SSL encryption of communications over the back-channel.

It is not necessary to generate the certificates on the same machine where they will be used however you must have the openssl command-line tools installed on the machine where you wish to generate them.

The process for generating certificates will depend on which environment you are connecting to:

MTS (Development)

You do not need to generate certificates at all for the MTS environment - simply use the files provided in the MTS integration resources pack. Copy them into your config directory and rename as follows:

  mts_mutualssl_saml_sp.pem => sp-sign-key.pem
  mts_mutualssl_saml_sp.cer => sp-sign-crt.pem
  mts_saml_sp.pem           => sp-ssl-key.pem
  mts_saml_sp.cer           => sp-ssl-crt.pem
ITE (Staging)

For the ITE environment you can generate self-signed certs. The nzrealme tool can prompt you interactively for the required parameters:

  nzrealme --conf-dir /etc/nzrealme make-certs

or you can provide them on the command-line:

  nzrealme --conf-dir /etc/nzrealme make-certs --env ITE \
    --org="Department of Innovation" --domain="innovation.govt.nz"
PROD (Production)

For the production environment you can use the nzrealme tool to generate Certificate Signing Requests which you will then submit to a Certification Authority who will issue signed certificate files. Save them in the config directory using the filenames listed above.

  nzrealme --conf-dir /etc/nzrealme make-certs --env PROD ...

SP Metadata

After you have generated the certificates, you can generate a metadata file with the command:

  nzrealme --conf-dir /etc/nzrealme make-meta

You will be prompted to provide the necessary details and can re-run the command to revise your answers.

Note: You can't simply edit the XML metadata file, because a digital signature is added when the file is saved.

You will need to provide the SP metadata file to the RealMe login service (via an upload to the shared workspace). For ITE and PROD you will also need to provide the certificate files. You can assemble a 'bundle' of the required files with this command:

  nzrealme --conf-dir /etc/nzrealme make-bundle

TESTING

Normally your application would generate an authentication request URL and redirect the client to it, however it is also possible to generate one from the command-line:

  nzrealme --conf-dir /etc/nzrealme make-req

You can paste this URL into a browser and complete a log on. Once you have logged on you will be redirected back to the URL for the ACS (as specified in the SP metadata file that you uploaded). You can copy the ACS URL from your browser and paste it into the following command to resolve the artifact passed in the URL to an FLT:

  nzrealme --conf-dir /etc/nzrealme resolve <ACS URL> <Request ID>

The ACS URL will contain special characters that may need to be quoted. You'll also need to supply the Request ID which was output by the original make-req command.

API REFERENCE

The Authen::NZRealMe class provides entry points for interactions with the RealMe login service and is also responsible for dispatching the various command implemented by the nzrealme command-line utility.

service_provider( conf_dir => $path_to_config_directory )

This method is the main entry point for the API. It returns a service_provider object that will then be used to generate AuthnRequest messages and to resolve the returned artifacts. Unless you have set up alternative class mappings (see below), this method is a simple wrapper for the Authen::NZRealMe::ServiceProvider constructor.

class_for( identifier )

This method forms half of a simple dependency injection framework. Rather than hard-code the classnames for the various parts of the API, this method is used to turn a simple functional name (e.g.: 'service_provider') into a classname like Authen::NZRealMe::ServiceProvider. This method will also load the package using require.

You would not usually call this method directly - instead you would use the service_provider method which calls this.

register_class( identifier => package )

This method forms the other half of the dependency injection implementation and is used to override the default mappings. The most common reason to use this method is to inject mock object classnames for use during automated testing.

run_command( command, args )

This method is called by the nzrealme command-line tool, to delegate tasks to the appropriate classes. For more information about available commands, see nzrealme --help

Your application should only need to directly interface with the Service Provider module (as shown above). The service provider will delegate to other classes as required. Reference documentation is available for these other classes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Authen::NZRealMe

You can also look for information at:

Commercial support and consultancy is available through Catalyst IT Limited http://www.catalyst.net.nz.

LICENSE AND COPYRIGHT

Copyright (c) 2010-2019 Enrolment Services, New Zealand Electoral Commission

Written by Grant McLean <grant@catalyst.net.nz> and Haydn Newport <haydn@catalyst.net.nz>.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.