Rick van Rein

wo 18 maart 2020


Identity 13: Be Your Own IDentity Provider

If you want to Bring Your Own IDentity (BYOID) to foreign servers you will somehow need to offer an identity provider to them. How would that work?

The idea of BYOID is that you can use your own domain's user@domain.name identity, along with a plethora of forms to login to foreign servers. This means that you need protocols to help you, for which we have two forms in the making:

  • KXOVER can serve organisations already using Kerberos today. We expect users of the InternetWide Architecture to migrate to this technology because of its single-signon properties;
  • SXOVER, described below, is easier-to-get-going, because it uses SASL that can be as clever as Kerberos with KXOVER but also as dumb as password authentication (until your admin understands why he should disable that). SASL with SXOVER is a perfect transition technology.

We shall now explain what SXOVER is about. If the technical details are overwhelming, be sure to skip ahead to the short final section for a smashing conclusion.

Your own Identity Provider (IdP)

To be able to make statements about identity, you need to run an identity provider of some kind, and let foreign servers find it to authenticate you. Some magic with TLS, DNSSEC and DANE would help those foreign servers to trust the statement of the domain (or "secure realm") as the owner of user names under the realm. In specifications, it is common to use ASCII art to draw that:

   +--------+    SASL     +--------+    SASL    +---------+
   | Client |-----------> | Server | ---------> |  Realm  |
   +--------+  AppProto   +--------+  Diameter  +---------+
       ||                     ||                    ||
john@example.com        find SRV, TLSA          example.com
  & credential            relay SASL           authentication

The path between the client and (foreign) server runs over SASL in any application protocol, for example HTTP, and the backend simply relays the SASL communication to the identity provider for the client's own realm.

There are several similar designs, but these are typically web-specific, and may require manual intervention and/or constrain the client's choices. The design proposed above embraces virtually all protocols; this happens to include the popular web protocol, but not exclusively. It is difficult to expand a web-specific design to include other protocols, but it tends to be easy to add web-specific frails to a system that is designed to be generic.

Diameter to carry SASL

Diameter is the sequel to RADIUS, a very old protocol that was invented in the times of dial-in modems that ran PPP and had to check username/password combinations. Using RADIUS, that question was transported from the modem pool to an identity provider that would check the password and either send back success or failure to the modem pool, which then allowed client access or withhold it.

RADIUS was designed to run on a confined, internal network where nothing bad was happening. It has since been patched to run over TLS, but in a way that scales poorly, and certainly is no good basis for trust. Diameter on the other hand, is a re-design that can hold up in the questionable context of the Internet and, when combined with DNSSEC and DANE, can provide strong guarantees about a remote peer being authoritative for a domain. Furthermore, connections are pooled and can easily be setup or torn down, it runs over SCTP to avoid technicalities about request ordering and it is designed for applications of authentication (proof of identity) and authorisation (access control).

SASL is used in many-many-many protocols for the authentication part, and we have our efficient ACL technology even including group facilitation for authorisation immediately afterwards, so SASL over Diameter sounds like a useful idea.

Diameter however, has no profile for carrying SASL. So that's what we are adding now. The protocol is easily flexible enough to carry it, nobody just thought of its usefulness! But with it, you could have a foreign server (like a web server) that is blissfully unaware of any client identities but knows where to turn to have them checked. It simply turns to your domain's Diameter server and relays any SASL inquiries that it gets. Cracking the web server won't reveal any credentials of such clients!

Diameter/SASL flow for Anonymous Access

The information in Diameter is packaged into attributes, formally known as AVPs. These have a name and intended use; we are merely adding a few for use with SASL.

Let's start simple, and assume the foreign server has no clue about the presence of SASL. It might send a Diameter message with the command AA-Request, which means that it wants to do authentication and authorisation. The server would send a response command AA-Answer, holding in it a challenge with the following attribute:

  • SASL-Mechanism set to the string ANONYMOUS SCRAM-SHA-256
  • No State has been builtup

This is an invitation to use one of the named SASL mechanisms. The mentioned State attribute is used to avoid the need to store any state in a Diameter server, so it is passed back and must be repeated in the following request. This is not yet done here.

The client now chooses a mechanism and starts it with:

  • SASL-Mechanism set to ANONYMOUS
  • According to the ANONYMOUS spec, the client may include a "trace identity" for debugging purposes; this would go in a SASL-Token attribute.
  • No State needs to be passed

If the server accepts this, it will respond with an AA-Answer command indicating success.

This being the ANONYMOUS mechanism, it does not actually authenticatate a user, but it may be used to (explicitly) grant guest access. An added use is that the AA-Request and AA-Answer may carry access control information, detailing what access rights are provided. Any rights would be minimal for ANONYMOUS but should allow more after serious authentication.

Diameter/SASL in a Complete Example

After this simple, but still somewhat useful example, let's now turn to a more realistic flow, using the SXOVER mechanism GS2-SXOVER-PLUS as defined below. We shall skip the first step which is not always necessary anyway.

The client initiates an AA-Request holding:

  • SASL-Mechanism set to GS2-SXOVER-PLUS
  • SASL-Token set to the initial message, which is named C2S-Init in the SXOVER spec
  • at least one SASL-Channel-Binding attribute (explained further below)
  • No State can be passed

The server sees no State, so this initiates a new exchange. Since there is no SASL-Mechanism, it knows it does not need to list possible mechanisms as described before.

The mechanisms that an identity provider supports may vary:

  • If it is used behind internal services like an IMAP mail server, it might welcome many SASL mechanisms, such as SCRAM-SHA-256 and GSSAPI.
  • If it relays ACL information, it may be useful to have an ANONYMOUS option sharing that.
  • In support of Realm Crossover with SASL, it must support GS2-SXOVER-PLUS and it may also support GS2-KRB5-PLUS.

We will assume that the SASL mechanism GS2-SXOVER-PLUS is supported, as our identity provider intends to support realm crossover. So, the server now starts the corresponding SASL mechanism and passes it the SASL-Token attribute value (if one was given, otherwise it passes no token).

Now it starts to loop around...

The SASL mechanism responds with either accept or reject, or the need to continue. Furthermore, it may yield a token. After making the step, the SASL state would be exported. Now, the Diameter server constructs an AA-Answer response:

  • If SASL decided to reject or accept, this will be reflected in the response; if it decided to continue, this will lead to a challenge response.
  • If SASL provided a token, then a SASL-Token attribute is filled with its value; note that it is possible to receive no token, which means that this attribute is not sent.
  • If SASL made a decision, the server may include extra attributes, such as the User-Name that was authenticated (the part before the @domain.name).
  • If SASL made no decision, its exportes state is signed/encrypted and stored in a State attribute. The client will be expected to return this in follow-up requests.

When the client receives this AA-Answer with a challenge and a State, it knows it should continue. It passes the SASL-Token into its local SASL client process and may harvest another token to send. This is then sent to the server in another AA-Request:

  • If a token was produced, it is stored in a SASL-Token attribute.
  • The State from the previous AA-Answer is cloned in this follow-up request.

The server sees a State attribute and knows it has to continue. After decryption and signature checking, it imports the state into SASL to reconstruct the server state and mechanism choice, and then it makes another step, passing it the value in the SASL-Token attribute if it is provided.

...and then it loops back!

At some point, the client receives an AA-Answer that either rejects or accepts the request. At this point, it can harvest any responses, which may include the User-Name attribute. The client, which may be in need of this value, appends @domain.name where the domain.name is the Diameter-verified realm of the Diameter server, and now has the full user@domain.name form that forms the client's globally unique BYOID form of identity.

Plus, while doing this, the client has used its own realm which enabled it to slip in an alias or pseudonym, which is best done when leaving the identity perimeter as is the job of the Diameter identity provider.

In all this, the server (which is stateless thanks to the State attribute) is really simple to define:

IF   have a State attribute
THEN process_next_sasl_step()
ELSE IF   have a SASL-Mechanism attribute
     THEN process_first_sasl_step()
     ELSE send_sasl_mechanism_list()

Security: Encryption

We mentioned that State attributes must be signed and encrypted. The reason for having this attribute is to offload state from the server, so it can be small and reactive. Clients will drop the state when they loose interest, but servers might not know and keep it around for far too long. Passing the State through the client who must send it back on the next round helps, but is also a security hazard. To avoid abuse by the client, this state is signed and encrypted.

Precautions against the client (and perhaps the foreign server acting on its interest) are not the only concern. SASL is not in general designed for this kind of passing through potentially hazardous foreign servers. It is designed for local use, directly between a client and its client realm. The foreign server should not be allowed to inspect the SASL traffic, which precisely what the purpose for GS2-SXOVER-PLUS is; it is an encrypted tunnel in which another SASL mechanism flows. As far as the foreign server is concerned, the only data in this stream is the realm, which it needs to find out the Diameter server to connect to and to learn the @domain.name part of the client identity. The rest is random bits that it simply passes back and forth.

The inner SASL mechanism can now be as stupid as a password authentication, as that will not be seen by to the foreign server. This means, among other things, that you can pick one strong password to use with all servers. For a password mechanis, that is not entirely bad. But SASL allows you to choose, and to migrate to better mechanisms such as Kerberos.

Security: Channel Binding

Not mentioned above, there is an attribute called SASL-Channel-Binding. This helps with yet another form of security, and it is obliged for all SASL mechanisms ending in -PLUS, including the one we described here.

It is really simple to take a SASL exchange from one protocol and forward it into another. The value of Diameter as a server for GS2-SXOVER-PLUS is that it will not offer any actual resource access, but merely decides between accept or reject. There is no value to be had from that.

Now imagine that we allowed GS2-SXOVER-PLUS to end in another server. Perhaps an IMAP server, or an LDAP server, both examples that may store information considered sensitive. Don't call us mad; similar things have happened. Doing this means that any foreign server might put on a nice face (or a sexy face, which is supposed to be the common lure) and pass the client's SASL tokens to this IMAP or LDAP backend server. The client enters its token, all the way until acceptance, and the foreign server either serves the client or falsely shows a rejection, while extracting all your sensitive data from the backend IMAP or LDAP server -- to which you just authenticated.

This nightmare scenario looks like this:

   +--------+    SASL     +--------+    SASL    +---------+    SASL    +---------+
   | Client |-----------> | Server | ---------> |Mail/Data| ---------> |  Realm  |
   +--------+  AppProto   +--------+ IMAP/LDAP  +---------+  Diameter  +---------+
       ||                     ||                    ||
john@example.com        find SRV, TLSA          example.com            example.com
  & credential            relay SASL           under attack           authentication

This is the big challenge of Realm Crossover; to balance the flexibility against stringent security. In this case, the solution is quite simple; the backend should verify that it is talking to a server seen by the client. This is established with channel binding.

Channel binding includes bits of the TLS session in which the SASL-enabled protocol runs, in such a way that it cannot possibly be forged. This would be the expected addition when passing SASL into Diameter, but no IMAP or LDAP server would expect or tolerate it. There is not even a mechanism in any mechanism but for Diameter to express this! So the scenario above is completely impossible.

Channel binding is cryptographically bound into the SASL mechanism used. Not every mechanism supports it, but GS2-SXOVER-PLUS does, and its end-to-end encrypting tunnel will fail to work without it. The server needs the channel binding information to be available, because it does not see the TLS connection between the client and foreign server, but it is not in the interest of the foreign server to lie -- nor could it, because the client will be certain to include the channel binding information and require its inclusion from the server as well.

Returning to Diameter, and its possible provisioning of ACL data, this too might be considered a valuable resource to try to tap. Attacks can easily be stopped however, by only returning ACL data to Diameter servers that have been listed as trustworty. It is completely useless passing ACL data to an audience that is not listening, so there will be an assumed relationship anyway. This is precisely what we are thinking of when we speak of plugin services as part of our next phase ServiceHub. To be continued!

And yet... it is Simple to Use

In spite of all this technical complexity, the interaction of SASL for access to a foreign server is straightforward; you cannot use all SASL mechanisms on any foreign server, but it should always be safe to use GS2-SXOVER-PLUS to login anywhere, so it can be a default/anywhere mechanism.

Go Top