Thinking about PAX
Posted in Tech Notes on February 9th, 2012 by victor – Comments OffDeparting from my format of once or twice a year postings on random musings and life-changing events, I’m going to start a series (i.e. possibly more than one) of posts on technical stuff I’ve been thinking about.
I was at the Planetwork N2N meeting last month, and Mike Schwartz included in his presentation a recommendation that people have a look at the OpenID Connect standard. He thought it was a worthy simple replacement for the complexities of SAML in many cases. That evening when I got home, there was an email in my inbox to the IDCommons list from Mike Jones pointing to an article by Nat Sakimura called OpenID Connect in a nutshell. (This cast of characters will be familiar to current or former participants of the Internet Identity Workshops and/or the Oasis XRI/XDI technical committees.)
When something new (to me) gets mentioned twice in one day by independent sources, it’s the virtual equivalent of the proverbial book falling off the shelf and hitting me in the head — a “pay attention to this” message from the universe. So I read Nat’s article carefully.
As I said to Mike Schwartz when I saw him again two days later at a different meeting, I liked everything I’d read so far about OpenID Connect except the OpenID part. His response was that the only part of OpenID that remained in OpenID Connect was the name, which seems to be true. As Nat says in his post, “To turn an OAuth 2.0 request into an OpenID Connect request, simply include openid as one of the requested scopes.” The response then contains the standard OAuth access token, but also an “id token”. If I understand the point correctly, the server is basically saying that along with an access token to acquire data about this user, I’m certifying with the id token that this user was able to authenticate with me — thus facilitating SSO.
Evidently, the reason I needed to pay attention to OpenID Connect was to stimulate me to flesh out the affiliation feature of MetaConnectors. The point of this article is to propose what I think is an even simpler and imho better method for SSO and data exchange authorization than OpenID Connect — in the special case of peer affiliates. Until dissuaded I’m going to call it PAX, as in P(p2p and pki)A(affiliate)X(whatever). It’s also the Latin word for peace.
Peer-to-peer Public Key Infrastructure (PKI) is at the core of PAX. MetaConnectors publishes a public key (in the form of an X509 cert encapsulated in a JSON XRD) for each network and each user, for example this, or for human readability this (forgive the self-signed certs and resulting browser warnings – these will become CA-signed certs before we go into production). The corresponding private keys are held in our database. This is quite easy to do — all the popular programming languages support OpenSSL, and OpenSSL creates key pairs and reads and writes various types of certs. I chose X509 as the most venerable and familiar certificate format – it is after all just a standard container that includes the public key and some metadata about it. Ruby has good OpenSSL support, although the documentation for it is virtually nonexistent. I wrote and open-sourced a library to wrap the parts I needed, just to make it easier to understand and use.
PAX also makes use of the JSON Web Token (JWT). One of the things I liked best about OpenID Connect was the use of the JWT, which is basically a string divided into three fields (by “.” dots), where (when used in signature format) the third field is a base64url encoded signature over the first and second fields. The second field is a base64url encoded version of the plaintext JSON data structure. The first field is a header field with algorithm info, also in base64url encoded JSON. So clean, so simple. (Compare with the horror of XML DSIG.)
Other relevant standards are the Extensible Resource Descriptor (XRD) in JSON format (called a JRD), and Simple Web Discovery (SWD).
Affiliates in the PAX system have mutually agreed to affiliate beforehand by an out-of-band process (could be a phone call or email, or a more automated process involving web forms). As part of that process they have exchanged Simple Web Discovery and possibly host-meta URIs, which in turn supply various other service URIs used in the examples below. In a peer system each party can act as a client — the one who requires data, or a server — the one who offers data. I’ll describe several scenarios, and how PAX is used in each. In each case, a person who is participating in this process will be called a “user” and an organization or collection of users participating in the peer system as a collective entity will be called a “network”. For these examples we will imagine two affiliated networks, the Association of Affiliates (AOA) and the Network for a Better Planet (NBP). For the sake of clarity, the examples gloss over many details, some of which I’ll address in a later post.
Scenario 1. Client initiates single-sign on:
In this scenario, a user registered at NBP starts at the website of affiliated network AOA, wishing to be authorized by AOA as an affiliated user. AOA offers an affilate login form that says something like “Login as a participant in…” followed by a selection list of affiliated networks. The user chooses NBP from this list, which causes the user’s browser to be redirected to the NBP authentication URI, constructed like this (line breaks added):
https://nbp.org/authentication?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9. eyJpc3MiOiJhb2Eub3JnIiwiaWF0IjoxMzI4NzE2MjIzLCJleHAiOjEzMjg3MTY1MzMsImp 0aSI6IlZUT2FCdEY2enRmR3ZBIiwiYXVkIjoibmJwLm9yZyJ9. n53mdKp7NRcIiAd_USwqE1PnUNK-R5eUYHXtAkopjsyAba1Oi_ji7Yc3xzAr0CQMZrQZ5je vihIAeHinUiTnsr0ua-cIFXEu45vwMa5c7gmm281ugkGMMEmD5wf-v4xI8HYjjPTnAjmAYn G_71Jk3xFLewqH8NQxoDtarYEPCayZFz7pS-MV52OjLJRI4hh3Z4AHGnDMXm1j3NlMjXfMZ B_A-yk-QSxJmLcFlzUhr6IPwm6fk58ZfkIyEyppyPJ_UdgFM_NDZtCJXmIWabsBzrIQH0Tg 254qTZhWunE-u79P6qxm1p2kclzrHntKUiDtxYb7ktile2AHaJqZbGliCgNow, that’s one ugly URI to human eyes, but trust me it’s really a thing of beauty. It consists of NBP’s authentication URI template “https://nbp.org/authentication?jwt={jwt}” (discoverable via Simple Web Discovery and host-meta), with the {jwt} template variable replaced by an actual JSON Web Token. If you base64url decode the second field you get the JSON payload, aka the “JWT Claims Set” (here formatted for readability):
{ "iss":"aoa.org", "iat":1328716223, "exp":1328716533, "jti":"VTOaBtF6ztfGvA", "aud":"nbp.org" }The keys in the above example are all JWT Reserved Claim Names. They translate as follows: “iss” denotes the issuer of the claims set, “iat” is the “issued at” timestamp, “exp” is the time beyond which the JWT is no longer valid, and “aud” is the audience the claim set is meant for. A random value unlikely to repeat, sometimes known as a nonce, is here called a JWT ID, or “jti”. Taken together and signed, these values provide resistance to replay attacks.
The JWT is validated by the server by first retrieving AOA’s public key, either from cache if it hasn’t exceeded its expiry time, or via AOA’s JRD, then verifying the signature in the request and ensuring that the timestamps are within range, and that the jti hasn’t been seen before. The jti nonces should be kept by the server for some small increment beyond the expiration timestamp, so that the same nonce and timestamp combination can never be used again. I’ll refer to this whole sequence as “verifying the JWT” in the following examples.
In the examples that follow, I will also be adding Private Claim Names to the claims sets, i.e. names that are defined by PAX. I won’t hurt your eyes with any more JWT’s, but just show the URI templates and the JSON claims sets.
To proceed with Scenario 1, when the NBP authentication server receives the above request, it verifies the JWT. Now NBP knows that this request came from AOA. There are some phishing mitigation possibilities inherent which I will discuss in a later post. NBP then authenticates the user via whatever means NBP uses for that (probably user name and password for now). NBP then redirects the user to AOA’s authorization URI (cached or looked up), constructed like this:
https://aoa.org/authorization?jwt={jwt}with a JWT Claims Set like this:
{ "iss":"nbp.org", "iat":1328716253, "exp":1328716553, "jti":"wFnCyBMkqH33YQ", "aud":"aoa.org", "prn":"nbp.org/victor#1316743228" }Here the “prn” key is a JWT Reserved Claim Name denoting the subject (principal) of the claim. It should be a persistant non-reassignable pseudonym for the user in question. More on the way I’m constructing a non-reassignable pseudonym later.
When the user arrives at AOA’s authorization URI with those parameters, AOA proceeds as follows: first retrieve NBP’s public key, then verify, decode and validate the JWT. The user can then be considered by AOA to have been authenticated by NBP.
Scenario 2. Server initiates single-sign on:
The first scenario, where the user is redirected by the client contains inevitable phishing vulnerabilities. They can be mitigated somewhat, but since all phishing mitigation schemes require an alert user, and all users are at times tired, distracted and/or in a hurry, the danger can never be entirely eliminated. Safer for the user (and more efficient all around) is to begin SSO at the server, as follows: the user logs into a network where they have established an account directly, in this case nbp.org. The NBP website has a page listing affiliated networks. To SSO into an affiliated network, the user simply clicks on one of these links. This causes the user to be redirected to the chosen affilate’s authorization URI, constructed exactly as in the second part of Scenario 1, and the affiliate authorizes them the same way.
Scenario 3. Client requests data that is pre-authorized for affiliates:
AOA wishes to access data that is under the control of an NBP user (profile data, posts, pages, or whatever). The user has previously set permissions on their NBP account that permit affiliate organizations to access some or all of the data that they’ve entered at NBP. In this scenario the user is not necessarily present although they may be, but via previous interaction, AOA knows the user’s identifier at NBP. AOA sends a request to NBP’s data access URI constructed like this:
https://nbp.org/data_access?jwt={jwt}with a JWT Claims Set like this:
{ "iss":"aoa.org", "iat":1328818771, "exp":1328819071, "jti":"njbcHnRj7Nv4NA", "aud":"nbp.org", "prn":"nbp.org/victor#1316743228", "scope":"profile" }Here we have added a “scope” parameter, and its semantics and syntax are exactly the same as in OAuth. When NBP receives this request, it validates the JWT, then checks to see if this user has pre-authorized the release of all or part of the requested data to affilate organizations. NBP then responds with a JWT, the claims set of which includes a “scope” array, and a “data” object containing the requested data if authorized. The scope value should be an array of objects, one for each scope requested. The possible values for each scope object are “allowed”, “denied”, or “partial”. If no data was allowed to be sent consistent with the user’s pre-authorized settings, the data object will be null.
Scenario 4. Client requests data that requires user authorization:
This scenario most closely resembles the primary use case for OAuth. We accomplish it using almost exactly the same procedure as outlined in Scenario 3, except that the user must be present at AOA, and instead of AOA sending a data access request directly to NBP, it redirects the user to NBP with a data access request constructed as in Scenario 3, with the addition of a “request” value in the claims set, a token with which AOA can identify an asynchronous response. NBP must then present a UI to the user that shows what is being requested and by whom, and affording the user a way to approve or deny part or all of the request. Once the user has made her choices, she is redirected back to AOA’s data-available URI with a new JTW containing a claims set like this:
{ "iss":"nbp.org", "iat":1328818771, "exp":1328819071, "jti":"njbcHnRj7Nv4NA", "aud":"aoa.org", "prn":"nbp.org/victor#1316743228", "scope":"profile", "request":"PpLfO0bi8CKBCA", "authorization":"allowed" }The scope and request values repeat the corresponding values from the request, so that AOA can identify which request is being responded to. The possible values for the “authorization” parameter are “allowed”, “denied”, or “partial”, with the possible addition of a second space-separated value of “permanent”. The presence of the “permanent” value indicates that the user has chosen to permanently allow the selected access to the requesting client. The absence of the “permanent” value implies that a one-time only access has been made available. In that case, the server should have set temporary permissions for the selected data for the client organization only, which are then cancelled after one access.
The client may then make a new data request just as in Scenario 3.
Scenario 5. Server pushes data to subscribed clients.
This scenario makes use of the Evented API spec, which is an elaborated and constrained use of the Webhooks proposal.
One typical use case would be that AOA has acquired a copy of an NBP user’s profile data (using Scenario 3 or 4), and wishes to keep that profile copy current when the NBP user updates their authoritative profile at NBP.
AOA for example can subscribe to be notified of changes to the profile of the NBP user “nbp.org/victor#1316743228″, by sending an HTTP POST request to the NBP event-subscribe uri, with the POST body containing a JWT that might look like this:
{ "iss":"aoa.org", "iat":1328820639, "exp":1328820939, "jti":"CLQ5kLG5G7nG3g", "aud":"nbp.org", "prn":"nbp.org/victor#1316743228", "scope":"profile", "subscribe":true, "notify":"https://aoa.org/data-available" }Whenever an NBP user that AOA subscribes to updates their profile, NBP sends a POST request to the “notify” URI with a claims set like this:
{ "iss":"nbp.org", "iat":1328820951, "exp":1328821251, "jti":"lCZTYcO1XIBstQ", "aud":"aoa.org", "prn":"nbp.org/victor#1316743228", "scope":"profile", "_domain":"nbp.org", "_name":"update", "_timestamp":1328820950, "urls":["https://nbp.org/data_access?jwt={jwt}] }The last 4 keys in the above JWT are from the Evented API spec. AOA may then fetch the updated info using the same method as in Scenario 3.
Other use cases that could be serviced include users wishing to be notified when specific users from an affiliated network post new content, or when there is news from an affiliated network itself.
Once again, this proposal relates to the special case of data exchange and SSO between affiliate organizations and their participants, and serves their need to identify and securely interact with one another. I’ll follow up soon with an elaboration on some of the details of this proposal. I’ve added a JSON Web Token module to the CertLib ruby gem at https://github.com/victorgrey/cert_lib.

