Saturday, July 31, 2021

The struggles of a wannabe security programmer

 Yeah, I'm impressed that I have been able to sort of grok what goes by the name OAuth2.0 and its bastard child OpenID Connect or OIDC. And can at least make sense of a conversation on SAML. That in itself is no mean feat, frankly. YouTube was quite helpful at that, which is a rarity in my case. But what to do beyond that? I want to try this stuff with my own hands and I am frankly out of depth here. I have a laptop or two where I can set stuff up and tinker with things. How do I get started?

Maybe auth0 is the place? Or maybe ory/hydra + ory/kratos? Could it be dex? But they can't write a paragraph without talking about kubernetes! Maybe the do-it-all grand daddy of the trade - Shibboleth? Or the really cool Authelia? How about caddy-auth-portal.

There lies the problem. There's plenty to grok on the topic, all of it in the open source. But almost everything is so hostile to a beginner that unless you're ready to read code and try all kinds of google searches, and YouTube videos and piece together a picture for yourself, nothing will let you get to the heart of it and build an understanding by doing stuff in an isolated environment with minimal dependencies. Yeah, I hate it when you start talking about how to run this thing with docker or docker-compose without bothering to write a paragraph about the architecture and dependencies. But such is true open source these days. If you aren't doing this, you aren't doing it right I guess. The thing is, good man pages and documentation go a long, long way to building understanding. It seems that they are also incredibly hard, because making your writing useful (as opposed to merely legible) requires empathy.

Yeah, ranting! But ok, what are my key takeaways on OAuth2.0 and OIDC?

  1. It's complicated. You can still grok it.
  2. Ultimately, it is a mechanism for granting a time-bound token (the access token) to an application (the client app) to access protected information (the resource).
    1. In general, the token can be used to query a defined set of data from a protected service (called the resource server). This means the token is only good for accessing data it was supposed to be used for and not have an unrestrained access on the resource server.
    2. In the case of OIDC, that protected information is actually information about a user who has been authenticated by the process. Basic info is available as a second token, a JWT token called the ID token. For additional info, you 
  3. How does it work? Through a system of redirects.
    1. The center of all action is the client app. If it is unable to figure out the access tokens to use, it redirects to an authorization server, which protects access to the resource server.
    2. Now obviously, it is the user (called the resource owner) who can authorize the request. They do so by:
      1. Authenticating themselves at the authorization server.
      2. Consenting to allowing access to specific resources (referred to as scope) on the resource server.
    3. When the above process completes, the authorization server redirects the request back to the client app with an authorization key and some other identifiers. This authorization key allows the client to initiate interaction with the resource server, on behalf of the resource owner.
    4. You'd have thought that this is the end of the story. But not really. This key just allows the client app to initiate communication, but to continue it, the client app must get an access token in exchange of this auth key. This is where the details we so far overlooked start to matter.
      1. How does the auth server know which client app URL to redirect to?
        Actually, each client app must individually pre-register with the authorization server. When they do this, they get a client identifier, and a client secret. These are sent as part of the initial redirect to the authorization server.
      2. Why does the auth server issue an access token to the client app only after getting the authorization key from the client?
        The authorization server keeps track of each authorization key it issues and the client it issues it for. Assuming that the client is not compromised, it only trusts a request carrying this authorization server which also carries the correct client id and client secret. That's when it responds directly to the client with the more durable access token.
There is no public key exchange / certificate signing that happens between the resource server and the client app so that they could trust each other via mTLS. Instead the trust is mediated by the resource owner who gives consent to the interaction. But the resource server isn't going to trust any arbitrary caller just on the basis of the resource owner's consent. That's why:
  1. The client app must independently register itself with the authorization server, and obtain its identifiers.
  2. When the resource owner consents to the request from the client app, the authorization server verifies that this is a client they know before issuing the initial authorization code. This wouldn't be possible without step 1.
  3. And finally, the authorization key it sends back to the client app via redirection must come back to it from the same client before it can allow the client to begin a trusted communication with the resource server.
Obvious questions would be:
  1. What does the client do as part of the registration with the authorization server?
  2. How does the resource owner validate the access token in each request from a client?
  3. How does the resource server authorize the request carrying the access token?
I have some idea about these but I will add them here when I know better.

There are actually several flows defined by OAuth 2.0 and the one described above is the Authorization Code flow or simply code flow. There is also an implicit flow which is less secure - which sends the access token to the client app directly instead of sending a temporary auth code first. The OIDC flow likewise is different.

PS. By the way, I forgot to mention that I do have something of an idea about how to try this hands-on. I will go with dex, and try setting up an LDAP authentication server on Linux, then point dex to it. At least that will be a start.


Read more!