Project

smart_id

0.01
No release in over 3 years
Low commit activity in last 3 years
Smart ID wrapper libary for using Smart ID in Ruby applications
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 2.0
>= 0
~> 10.0
~> 3.0

Runtime

 Project Readme

SmartId

This gem provides a wrapper around Smart ID API. All the necessary checks, listed in point 3.5 are implemented. Currently this gem only supports authentication actions.

TODO

  • Add authentication functionality
  • Add Signing functionality (see if possible)
  • More test coverage

Installation

Add this line to your application's Gemfile:

gem 'smart_id', "~> 0.1"

And then execute:

$ bundle

Or install it yourself as:

$ gem install smart_id

Usage

Configuration

configuration can be done, by creating an initializer file and loading it before the application starts.

SmartId.configure do |config|
    config.relying_party_uuid = "MySmartIdUUID"
    config.relying_party_name = "My Smart ID name"
    config.environment = "demo" # possible options ar "demo" and "production", uses according smart-id parameters and keys
    config.default_certificate_level = "ADVANCED" # Possible options are "ADVANCED" or "QUALIFIED". Defaults to "ADVANCED"
    config.poller_timeout_secods = 10 # seconds to wait when fetching authentication confirmation
end

Authentication types

Authentication can be done either with providing user's national identity number or an identity document number

For national identity number use

SmartId::Api::Authentication::IdentityNumber

For document number use

SmartId::Api::Authentication::Document

Smart ID authentication is done in 2 steps - initializing the authentication and then getting confimation from Smart ID service. Those two steps happen asynchronously, so some parameters should be persisted either in session storage or in database

  • Back-end initializes authentification - user can see verification code on the app, and receives smart ID request to input PIN in they're mobile

  • Back-end authenfication confirmation - check whether user has authenticated by correctly typing in they're PIN on the mobile device

Authentication Request

To initialize authentication make a controller action.

National identity number

class UserController < AplicationController
    #...
    def authenticate_smart_id
        # authentication hash by default will generate random bytes, that will be hashed for signature check
        # if you wish to provide your own randomization, you can pass a parameter to AuthenticationHash with the random string
        # authentication_hash = SmartId::Utils::AuthenticationHash.new(SecureRandom.hex(64))
        # each authentication should have a unique random string passed
        authentication_hash = SmartId::Utils::AuthenticationHash.new

        auth_response = SmartId::Api::Authentication::IdentityNumber.authenticate(
            country: params[:country], # 2 character ISO 3166-1 alpha-2 format(for example EE, LT, LV, KZ)
            identity_number: params[:identity_number],
            authentication_hash: authentication_hash
        )

        session[:smart_id_session] = auth_response.session_id
        session[:auth_hash] = authentication_hash.hash_data

        # Screen/page after this call should show the user verification code, to see if it matches
        # the one they see on their mobile device
        render json: { verification_code: auth_response.verification_code }

    end
    #...
end

Document number

class UserController < AplicationController
    #...
    def authenticate_smart_id
        # authentication hash by default will generate random bytes, that will be hashed for signature check
        # if you wish to provide your own randomization, you can pass a parameter to AuthenticationHash with the random string
        # authentication_hash = SmartId::Utils::AuthenticationHash.new(SecureRandom.hex(64))
        # each authentication should have a unique random string passeds
        authentication_hash = SmartId::Utils::AuthenticationHash.new

        auth_response = SmartId::Api::Authentication::Document.authenticate(
            document_number: params[:document_number],
            authentication_hash: authentication_hash
        )

        session[:smart_id_session] = auth_response.session_id
        session[:auth_hash] = authentication_hash.hash_data

        # Screen/page after this call should show the user verification code, to see if it matches
        # the one they see on their mobile device
        render json: { verification_code: auth_response.verification_code }

    end
    #...
end

Authentication Confirmation

Create another controller action

class UserController < AplicationController
    #...
    def confirm_smart_id
        # use hash_data saved on authentication initialization as parameter
        authentication_hash = SmartId::Utils::AuthenticationHash.new(session[:auth_hash])

        confirmation_response = SmartId::Api::Authentication::ConfirmationPoller.confirm(
            session_id: session[:smart_id_session],
            authentication_hash: authentication_hash,
            # if true, will continously make requests to smart-id and return only after verification is completed
            # you can set this parameter to false, to handle polling yourself
            poll: true # default - true 
        )
    end
    #...
end 

Response structure

confirmation response will have the following attributes

authentication_hash = SmartId::Utils::AuthenticationHash.new(session[:auth_hash])

confirmation_response = SmartId::Api::Authentication::ConfirmationPoller.confirm(
    session_id: session[:smart_id_session],
    authentication_hash: authentication_hash,
    # if true, will continously make requests to smart-id and return only after verification is completed
    # you can set this parameter to false, to handle polling yourself
    poll: true # default - true 
)

confirmation_response.confirmation_running? # => true/false whether the user has finished authentication. Relevant, only if polling is not handled by the gem (with `poll` parameter set to false)
confirmation_response.end_result  # => end result of the verification. possible values are "OK"/"USER_REFUSED"/"TIMEOUT"/"DOCUMENT_UNUSABLE", see details in https://github.com/SK-EID/smart-id-documentation#5-session-end-result-codes
confirmation_response.document_number #=> document number for user
confirmation_response.certificate_level #=> certificate level for user - values are "ADVANCED" or "QUALIFIED"

confirmation_response.certificate.content.given_name #=> given name for user
confirmation_response.certificate.content.surname #=> surname for user
confirmation_response.certificate.content.serial_number #=> string, that includes user's national identity number
confirmation_response.certificate.date_of_birth_from_attribute #=> user's date of birth (available even for users who's latvian identity number starts with 32)

Customization options

You can provide extra parameters when initializing authentication (for both - identity number and document)

SmartId::Api::Authentication::Document.authenticate(
    document_number: "", # REQUIRED - document number
    authentication_hash: obj, # REQUIRED - authentification hash object of SmartId::Utils::AuthenticationHash
    certificate_level: "", # OPTIONAL - Either "ADVANCED" or "QUALIFIED" - if none are provided, default certificate level is used
    display_text: nil, # OPTIONAL - Text that user will see on their mobile device when asked for authentication
    multiple_choice: false, # OPTIONAL - If true, user will be asked to choose the correct verification code from supplied options on their device
)

SmartId::Api::Authentication::IdentityNumber.authenticate(
    country: "", # REQUIRED - 2 character ISO 3166-1 alpha-2 format(for example EE, LT, LV, KZ)
    identity_number: "", # REQUIRED - natioanl identity number
    authentication_hash: obj, # REQUIRED - authentification hash object of SmartId::Utils::AuthenticationHash
    certificate_level: "", # OPTIONAL - Either "ADVANCED" or "QUALIFIED" - if none are provided, default certificate level is used
    display_text: nil, # OPTIONAL - Text that user will see on their mobile device when asked for authentication
    multiple_choice: false, # OPTIONAL - If true, user will be asked to choose the correct verification code from supplied options on their device
)

Exceptions

All exceptions inherit from SmartId::Exception

Exception class Description
SmartId::InvalidParamsError either country or identity_number were not provided when trying to authenticate with identity number
SmartId::ConnectionError authentication/confirmation request failed, when rescuing see e.original_error for more details
SmartId::NoUserFoundError user with the supplied parameters (id number, document number, country) does not exist in smart ID system
SmartId::SSLCertificateNotVerified SSL certificate for smart ID service was not verified. Check for newest version of this gem to always keep cerficates updated
SmartId::InvalidResponseCertificate Certificate used in confirmation response is invalid
SmartId::InvalidResponseSignature Signature used in confirmation response is invalid.
SmartId::IncorrectAccountLevelError User's Smart ID account is below the required level by the authentication request ( "ADVANCED" < "QUALIFIED")
SmartId::InvalidPermissionsError Relying Party has no permission to issue the request. This may happen when Relying Party has no permission to invoke operations on accounts with ADVANCED certificates.
SmartId::OutdatedApiError API used by the gem is outdated, please see if you are running the newest version of the gem
SmartId::SystemUnderMaintenanceError Smart ID System is under maintenance, try again later

Testing

Smart ID demo environment has provided some sample values to use when testing applications see Smart ID WIKI page

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rspec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/zippyvision/smart-id-ruby.

License

The gem is available as open source under the terms of the MIT License.