Circular dependency in microservices architecture for Authentication

microservicesoauth2

We are planning on using OAuth2 / OpenID-connect for Authentication & Authorization and I'm looking at what services would be required. So far I've identified that I need at a minimum:

  • An OpenID-connect authorization service, e.g. implemented using Identity Server
  • Service(s) for registering and managing users
  • Service(s) for registered and managing client applications

(My assumption here is that I'm better off having these as separate services rather than bundling all of these into some sort of authentication mini-monolith)

When servicing auth requests Identity Server will need to lookup the client id, and may also need to lookup user details. To me, it seems like the simplest solution would be a REST / HTTP request, e.g. something like this (where the password is contained in the body)

POST https://users.api/users/justinp/authenticate

It also seems to me that I want requests to this API to be authenticated, however, that creates a sort of circular dependency whereby the authorization service depends on the user service to fulfill requests, but the user service (and similarly the client app service) depend on the authorization service for authorization. This doesn't cause issues at runtime as the authorization server can, of course, generate its own valid authorization tokens, but the design still doesn't seem "quite right".

I can see how I could avoid this in various ways, e.g. by using CQRS / Event Sourcing – have the user and client app services push changes so that the authorization service can maintain its own internal list of users and clients, however this does up the complexity and I'm not entirely sure that it's necessary.

Is this "circular dependency" actually fine in this case, or is this architecture a bit wonky?

Best Answer

Before you do anything else, you should read this introductory article on HTTP authentication to get started.

Oath2 protocol flow is shown below as described in The OAuth 2.0 Authorization Framework:

 +--------+                               +---------------+
 |        |--(A)- Authorization Request ->|   Resource    |
 |        |                               |     Owner     |
 |        |<-(B)-- Authorization Grant ---|               |
 |        |                               +---------------+
 |        |
 |        |                               +---------------+
 |        |--(C)-- Authorization Grant -->| Authorization |
 | Client |                               |     Server    |
 |        |<-(D)----- Access Token -------|               |
 |        |                               +---------------+
 |        |
 |        |                               +---------------+
 |        |--(E)----- Access Token ------>|    Resource   |
 |        |                               |     Server    |
 |        |<-(F)--- Protected Resource ---|               |
 +--------+                               +---------------+

                 Figure 1: Abstract Protocol Flow

The abstract OAuth 2.0 flow illustrated in Figure 1 describes the
interaction between the four roles and includes the following steps:

(A)  The client requests authorization from the resource owner.

(B)  The client receives an authorization grant, which is a
     credential representing the resource owner's authorization

(C)  The client requests an access token by authenticating with the
     authorization server and presenting the authorization grant.

(D)  The authorization server authenticates the client and validates
     the authorization grant, and if valid, issues an access token.

All the resource services need to be able to validate the token. There are "many different and valid ways" to do OAuth2 but I would recommend using cryptographic signatures on the tokens. Then your resource servers can validate the token without reaching out to anything else. Revocation may be a concern however. I gather that initially the token specification was vendor specific but that there is now a standard around this.

As far as username recovery and password resetting goes, I would not consider that part of the authentication service. I would separate that out into it's own process and set of services that is independent of the authentication service.

Related Topic