Some of you may have read my blog post on OAuth vs. LDAP. That topic seems to be interesting for quite some time now. I think it may be a topic people talk about because it may not be too simple to see the difference of those two. Just recently I was told that it would be good to get a comparison between OAuth, LDAP and OpenID Connect.
This post is providing that comparison.
LDAP (Lightweight Directory Access Protocol)
An LDAP server (full disclosure: I am not an expert on LDAP) is a directory that contains details, attributes about users. It may contain a username, firstname, lastname, password (or the hash of a password), address, certificates, date of birth, roles, all kinds of stuff. The data of an LDAP gets accessed for different purposes:
- authenticate a user: compare the given username and password against values found in the LDAP
- retrieve attributes: retrieve firstname, lastname, role for a given username
- authorize users: retrieve access level for directories for a given username
I believe that most developers, at some point in time, had to deal with an LDAP server. So I also believe that most developers will agree with what I just described.
OAuth is a framework that enables applications (clients) gain access to resources without receiving any details of users they are being used by. To make it a little more visual I am introducing an example:
The very cool app 'FancyEMailClient'
In the old days:
- for each email provider the user provides details such as smtp server, pop3 server, username, password on a configuration page within FancyEMailClient
- FancyEMailClient now accesses all configured email accounts on behalf of the user. More precise, FancyEMailClient is acting AS the user!
- The user has shared all details with FancyEMailClient ... I must say, it feels a little fishy ... don't you agree?
In the days of OAuth:
- FancyEMailClient is an oauth client and gets registered at each email provider that should be supported
- FancyEMailClient does not ask users for any email provider details whatsoever
- FancyEMailClient delegates authentication and authorization to the selected email provider via a redirect_uri
- FancyEMailClient retrieves an access_token and uses this token at an API such as /provider/email to retrieve the users emails. The access_token may be granted for 'scope=email_api'
- FancyEMailClient has no clue who the user is and has not seen any details such as username or password
- This is perfect in regards to the users privacy needs ... However, FancyEMailClient would like to display a message such as 'Hello Sascha' if 'Sascha' is the user ... but it cannot ...
As I explained above a client does not get any details about the current user. But since most applications would at least like to display a friendly message such as 'Hello Sascha' there needs to be something to help them.
To stick to the email provider example, before OpenID Connect (OIDC) was born, these providers simply created oauth protected APIs (resources) that would return details about the current user. Users would first give their consent, afterwards the client would get the username or firstname and would display 'Hello Sascha'.
Since this became a requirement for almost any oauth clients we now have a common way of doing that, specified in OpenID Connect. OIDC has specified SCOPE values, a /userinfo API and an 'id_token' which represents an authenticated user.
In order to enhance the oauth version of FancyEMailClient the developer of it would only have to do a few little things:
- when requesting access to emails, also request access to user details. The request would now have to include something like '...&scope=openid+profile+email+email_api&...' (scope == permissions like access control)
- during the authentication and authorization flow the user would not only grant access to his emails but also to his personal details
- FancyEMailClient would now receive an access_token which could not only be used at /provider/email but also at /provider/userinfo
- FancyEMailClient can now display 'Hello Sascha'!
Now the big question: how does it all come together?
LDAP servers are the only component that exists without OAuth and OpenID Connect. LDAP servers are always the source of users (and maybe also clients and other entities). LDAP servers have always been used to authenticate users and authorize them for resources. OAuth and OpenID Connect cannot be supported if no LDAP server is available. OAuth and OpenID Connect are protocols only, not systems to manage users.
Below is a picture which I have created to show an example system:
My former manager Jay would now lean back in his chair, put his hands behind his head, put his feet onto a table and would say: Let me explain!
- When a user selects an email provider within FancyEMailClient his browser gets redirected to that provider. It is an OAuth authorization request and includes oauth SCOPE values. To access the API /provider/email a SCOPE value such as 'email_api' may be included. I say 'may' because there is no standard SCOPE for that. To also gain access to the user details other SCOPE values need to be included. That is more straight forward since they have been specified within OpenID Connect. 'openid profile email' would be sufficient and are supported at practically all OIDC providers. In the end of the flow FancyEMailClient gets back an OAuth authorization_code.
- The user only shares his credentials with EMailProvider. He types them into the EMailProviders login page and EMailProvider will validate them against his LDAP server. (LDAP server may be a database or any other system that maintains user details)
- After receiving the OAuth authorization_code FancyEMailClient exchanges this short lived token for an OAuth access_token. That access_token provides access to resource APIs. I hope it is obvious that this 'exchange' request is a backchannel request, no browser is involved!
- FancyEMailClient accesses /provider/email and /provider/userinfo by providing the OAuth access_token which it received earlier. Although both APIs require an access_token, there is one difference. /provider/userinfo is an OpenID Connect API where as /provider/email is an API proprietary to the EMailProvider. Let's call it a plain OAuth protected API
- In this area I wanted to emphasize the role of the LDAP server. As you can see, it is almost involved during all requests.
Case: The old days
The same app without using OAuth would probably look something like this:
A user would share his credentials with FancyEMailClient. And he would do this for each single provider he has an account with. FancyEMailClient would probably also ask for other details so that an API such as /provider/userinfo would not even be necessary. FancyEMailClient would now collect all this sensitive data and could do whatever it wants with it. That is a big disadvantage!
Another disadvantage is the fact that the users credentials are now used for each single request. That increases the chances for them being exposed.
OAuth, OpenID Connect and LDAP are connected with each other. But I hope it becomes visible which component plays which role and one cannot replace the other. You may say that my explanation is very 'black & white', but I still hope that it clarifies the overall understanding.
As usual, let me know if you have any questions, positive feedback or constructive criticism.