A rubygem to support Soomo Glue messaging operations
Ruby
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
spec
.gitignore
.rspec
.ruby-version
Gemfile
README.md
Rakefile
soomo-glue.gemspec

README.md

Soomo Glue

This gem provides messaging features around Soomo Glue -- Soomo"s identity, entitlement and resource context management service.

Message Format

Messages are structured as follows.

The data part of the message is specified as JSON and contains a unique 'identifier' value for security, e.g.:

  {
    'identifier': "bb63ddbf-887e-4b6c-9342-c02496e4a62b",
    "myMessageName": "someData"
  }

The rest of the message formatting is determined by the application.

There is also a signature part:

  {
    "signer": "soomo-core"
    "digestMethod": "SHA1",
    "digest": "k7z/t3iPKiyY9P7B87FIsMxnlnk=",
    "signatureMethod": "RSA",
    "signature": "KvUrzGcwGsu8WMNogIRfAxxWlO4uKXhJrouOYaadkzUHvz1xbVURH35si6U8084utNAjXTjZyxfj qurEX7VgCw6Xn7Fxn4nJxD6FOP5x/iRk8KqCufipRNHwICq/VufqPkrP7sVLdymJyZ2Cu5QrEU23 qaIzjFf84Kfp4LVnlJY="
  }

The "signer" indicates to the receiver which public key to use to verify the signature is valid.

The digest is the SHA1 hash of the data part of the message in its Base64-coded textual representation. The message is shown here as JSON but the underlying coding can change as needed.

The signature is produced by encrypting the digest with the client"s private RSA key.

Times are specified in ISO8601 format (e.g. Time.now.utc.iso8601, Time.now.iso8601)

Message Format

Messages are modular, and contain parts. The basic message stub is:

{
  'identifier': "bb63ddbf-887e-4b6c-9342-c02496e4a62b",
  "issuerUri": "soomo://core",
  "issueInstant": "2004-12-05T09:17:05Z",
  "conditions": {
    "notBefore": "2004-12-05T09:17:05Z",
    "notOnOrAfter": "2004-12-05T09:27:05Z" }
}

Only the significant keys from this message stub will be repeated in subsequent message descriptions. The soomo-glue-gem handles creating these in the following fashion:

  Soomo::Glue::Message.create(message_data).
    issuerUri(issuerUri).
    issueInstant(Time.now).
    forwardingUri(uri).
    notBefore(Time.now).
    notOnOrAfter(Time.now + 60)

Identity Assertion (this can be used to initiate a session for a subject)

The data message part is specified as:

  {
    "forwardingUri": "http://webtexts.com/user/continue_login",
    "assertion": {
      "subject": {
        "identity": {
          "source": "soomo-core",
          'identifier': USERID },
        "attributes": {
          "name": "John Smith",
          "email": "john@smithfamily.com",
          "roles": [ "student" ]
        }
      }
    }
  }

User will be returned to "forwardingUri".

Session Initiation Response

Since this is just a response to the subject identity assertion, and since no queries were present, it contains no data.

  {
    "inResponseTo": "bb63ddbf-887e-4b6c-9342-c02496e4a62b",
    "conditions": {
      "notBefore": "2004-12-05T09:17:05Z",
      "notOnOrAfter": "2004-12-05T09:27:05Z" }
    "status": "success"
  }

If the message is invalid (and there is likely no recourse for this situation other than an immediate retry) the response will be:

  {
    "inResponseTo": "bb63ddbf-887e-4b6c-9342-c02496e4a62b",
    "conditions": {
      "notBefore": "2004-12-05T09:17:05Z",
      "notOnOrAfter": "2004-12-05T09:27:05Z" }
    "status": "failure"
  }

Authentication Query

  {
    "forwardingUri": "http://courses.soomopublishing.com/session",
    "query": {
      "authentication": true 
    }
  }

Authentication Response (Assertion)

  {
    "status": "success",
    "assertion": {
      "subject": {
        "identity": {
          "source": "soomo-core",
          'identifier': USERID },
        "attributes": {
          "name": "John Smith",
          "email": "john@smithfamily.com",
          "roles": [ "student" ],
          ...
        }
      }
    }
  }

Authentication response can contain arbitrary attributes as offered and required by other services. If metadata grows to the point where it is prohibitive to deliver it all with each authentication response, it can be queried separately (e.g. a metadata query).

Authorization Request

  {
    "forwardingUri": "http://courses.soomopublishing.com/session",
    "query": {
      "authorization": [
        { "resource": "soomo-resource://courses.soomopublishing.com/course/COURSEID" }
      ]
    }
  }

Note the authorization request may include multiple resources if multiple resources are expected to require authorization.

TODO: How do we get the context token into the return request URI? Maybe it already contains it since if the service itself is requesting authorization, it already has the token. (It receives the token when the user arrives from Glue.)

Authorization Response

  {
    "inResponseTo": "bb63ddbf-887e-4b6c-9342-c02496e4a62b",
    "status": "success",
    "assertion": {
      "authorization": [
        { 
          "resource": "soomo-resource://courses.soomopublishing.com/course/COURSEID",
          "decision": "permit",
          ...
        }
      ]
    }
  }

Message may contain more subject information, but will at least contain the "soomo-id". Each authorization decision part can contain additional elements as necessary, e.g. to specify when the authorization will currently expire, or to specify other conditions related to this decision.

Combined Authentication / Authorization Request

  {
    "forwardingUri": "http://courses.soomopublishing.com/session",
    "query": {
      "authentication": true,
      "authorization": {
        "resource": "soomo-resource://courses.soomopublishing.com/course/COURSEID"
      }
    }
  }

Combined Authentication / Authorization Response (assertion only)

  {
    "inResponseTo": "bb63ddbf-887e-4b6c-9342-c02496e4a62b",
    "status": "success",
    "assertion": {
      "subject": { ... },
      "authorization": [
        { 
          "resource": "soomo-resource://courses.soomopublishing.com/course/COURSEID",
          "decision": "permit",
          ...
        }
      ]
    }
  }

Context Assertion

  {
    "forwardingUri": "http://courses.soomopublishing.com/session",
    "assertion": {
      "priorContext": "PRIOR_CONTEXT_TOKEN",
      "context": {
        // Arbitrary context data can be inserted here and will be returned when requested.
      }
    }
  }

Context Query

  {
    "forwardingUri": "http://courses.soomopublishing.com/session",
    "query": {
      "context": "CONTEXT_TOKEN"
      }
    }
  }

Resource Forwarding

Resource forwarding operates by simply adjusting the "forwardingUri" value in the message. In addition, it's likely there will have to be a context provided, so it can be included either by direct assertion or by token reference.

Here a token reference is shown. The token could have been obtained with a previous message asserting the context, with a self-referencing return URI.

  {
    "issuerUri": "soomo://core",
    "forwardingUri": "soomo://reader/book/12",
    "assertion": {
      "context": "CONTEXT_TOKEN_VALUE_AND_NOT_A_HASH"
    }
  }

NOTE: This is probably not implemented as it's not that useful.

Some obligatory message parts are left out here, but you can see the issuerUri differs from the forwardingUri -- so the response to this message (essentially a no-op since there is no query part) will be to simply forward the user to the specified Reader book.

Combined Authentication / Authorization / Context Assert / Forwarding Request

  {
    "forwardingUri": "soomo://courses/course/COURSEID",
    "assertion" {
      "context"
    }
    "query": {
      "authentication": true,
      "authorization": {
        "resource": "soomo://courses/course/COURSEID"
      },
    }
  }

Typical Flows

  1. Assert Subject / Entitlements / Context and Request Authentication / Authorization / Context / Forwarding

This happens when a user is forwarded from Soomo Core to a service destination like SLE. Core assers the identity of the subject, states relevant entitlement details, provides other context information, and specified the service destination. It also anticipates a request on behalf of the destination (SLE in this example) so that the entire exchange can happen with a single bounce to Glue. It requests authentication, authorization and context for SLE.

In this case, Core specifies a URI for the SLE service rather than a URL. This invokes Glue"s simple service resolver

If SLE needs something else it can re-request details from Glue.

{
  "forwardingUri": "soomo://courses/COURSEID",
  "assertion": {
    "subject": { ... }

  },
  "query": {

  }
}