The Fenrir Project

Transport, encryption, authentication protocol

This project is maintained by Luca Fulchir

RSS feed
Posted:

Federated Authentication

Today we are going to have an in-depth look at the algorithm behind the federation and how the tokens, the lattices are used.

The algorithm per-se is extremely easy, so we will look at what information we use and how. There’s no cryptography involved here :)

We will look at the authentication multiple times, adding new complexity each time, so that you should be able to understand how it all works out.

The Players

First of all, let’s get the names straight. The players in this games are:

Their roles should be pretty self-explanatory, but anyway: The application is your browser, or your chat client, mail client, or whatever. It can not do any authentication by itself, so it needs a client manager. This runs on the same device as the application, and is responsible for the authentication of all applications.

Then we have the Service, which can be a mail server, an http server, or anything that provides a service (who would have guessed?). Services must not have anything to do with the user database, so they need someone else to authenticate the clients, and that’s the job of the Authentication Server.

User Passwords and tokens

The more a user has to use a password, or his login credential in general, the more we risk using weak secrets, or risk writing them somewhere, or leaving everything unlocked by default.

Strong, unreadable passwords are good, but people won’t have anything to do with that. So we take those away.

The only time you use your password must be when you register your account in the client manager. Only once. No more. So how do we authenticate then, if we can’t reuse the passwords?

The answer is, obviously, Tokens. A token can include signed or encrypted data, but in Fenrir we only have two requirements, the uniqueness and unguessability of the token.

After the initial password authentication, the client manager is granted a token. This token will be used every time the manager has to connect to the authentication server, so that we won’t have to ask for the user password. It’s a bit like the TGT (Ticket Granting Tikcet) in kerberos, except that in Fenrir we don’t draw much distinction between the type of tokens.

So now we can authenticate with a username and a token, but what does the workflow look like?

Fenrir Workflow

As explained in the Architecture page, the application tells the manager it wants to connect somewhere, the manager does the handshake, authentication with the authentication server, which gives the key and the user info to both the manager and the service.

Now the client manager gives the keys to the application, which can connect to the service without handshakes or any other information.

By having one token per service, we can have the authentication server check which devices and applications accessed which services. Remember: the authentication server is a trusted source, and should be owned by you or someone you trust. That is the whole purpose of the federation.

So by now we know how to authenticate, and how to avoid using passwords. But we are only authenticating in our own domain, how do we do this federation thing?

The Federation

I do like Star Trek, but it’s not that federation we are talking about…

Since the services receive encryption keys and user data from the authentication servers, it can obviously trust only the authentication servers for its own domain.

So how do we authenticate elsewhere? To keep things simple, we won’t introduce different handshakes or different messages.

It’s actually simple. The authentication server receives an authentication request for a username, and a token. If we force usernames to be in the form name@domain.tld it will be pretty easy to know whether the authentication request we received is for our domain or some other domain.

At this point, the authentication server simply has to contact the other authentication server, give it the information on the client, the token, and it will reply with a success of failure message.

All of this puts a lot of trust on the authentication server, which is why you should only use an authentication server you trust. I am experimenting in ways to prevent the authentication server from impersonating a client in other domains, but it remains impossible to give this protection inside your domain. If you think about it, you never had it in the first place, even now.

Ok, now we know how the federation works. But do we really identify the user only with the token? We could do much more…

What a Token represents

Tokens are a wonderful way to authenticate without using the user password, but what does one represent, and what’s inside a token?

A lot of kerberos-like protocols use long, signed tokens, with information that is either in clear text or encrypted. We do nothing like that. As said before, tokens must be unique and unguessable, but do not need anything else. 256bit of random data are completely unguessable.

This simplifies a lot the handling of the token, and has only one drawback: we have to check the validity of the token with the authentication service every time we use it.

If you think this check is too much, recall that this is exactly what the Internet is doing with the OCSP protocol, even though todays certificate have expiration dates, and we have certificate revocation lists. It turns out this is the only reliable way.

Identifying the user

If we just wanted to identify the user, we could tie a token just to the username. We could use a TGT (Ticket-Granting-Ticket) - TGS (Ticket-Granting-Service), just like kerberos does. But it would be limited, we have so much more information we can use, and it all can be tracked by our authentication server, can we really do nothing with it?

Let’s see what we can track, aside from the username:

Does it look like not much? By tracking the user device, we can deactivate a user device remotely. Remember how each authentication required confirmation from the right authentication server? How there are no clocks to be checked to know if a token is valid, how the token per-se has no information? And that forces us to verify the token with its authentication server? This lets us instantly identify and even close connections done with a stolen token if we want.

By tracking the service for which we requested the token, we can do the same deactivation thing, but one service at a time.

I decide to not keep track of the applications in the authentication server, because for how the authorization work it would have meant more exchanged messages, a lot more complexity, and a little too much information on what is going on in the final user devices.

The final idea is to manage every authorization from the interface provided by your authentication server. This way you will have a clear, simple yet detailed view of how your account is being used in each device.

Imagine a hierarchical view, where you first choose your device, then you choose the service, and you can generate new tokens for that, delete the token or specify a single authorization

The authorization

Remember the Authorization Lattice? It’s a hierarchical way of representing what the account can do on a specific service.

If we tie each token to an authorization, that token can be used for all authorizations below the one we tied it to.

So now if your client manager has a token, tied to a specific authorization, and you want to give a smaller authorization to one of your applications, it does not have to exchange more messages with the authentication server.

The client manager will track the applications and their authorizations, so that things will be managed locally instead of remotely.

What does this mean? It means that your authentication server will not know what applications you are running, and that your client manager will be able to control all applications, down to how much you trust them.

But each service must have its own authorization lattice. While we might standardize on the common authorizations for well-known services, like email, a lot of things like websites are way too specific to find any common ground. So we have to synchronize the authentication lattice between the service, the authentication server and the client manager.

Note that the application does not know anything about this!

But it is still a problem. Now the authentication service has to ask the lattice to the service, and the client manager has to ask it from the authentication server.

That sounds like a lot of transfers. We have to put some limits on the size of the authentication lattice. We can actually have a pretty compact representation of this graph, but what can make it explode is the length of the node names. We limit those to 25 characters, and have a maximum of 64 nodes (plus top and bottom), and we can transmit the whole lattice, maximum size, in just 2 packets.

Now the lattice is small enough not to be a problem for the authentication service and for the client manager.

Conclusion

We have a federated authentication, independent from any content we want to put in our tokens and have a very fine control over the applications.

We never have to give any authentication to the applications, which do not need to know how to do any handshake or authentication.

The services do not need to know how to authenticate the user, or about the handshakes and have no access to the user database.

We finally have as much separation of authentication data from user data as possible, and applications and services development has gotten simpler.

I really can’t think of other features you’d want :)

-Luker