Before initiating the protocol, the client registers with the authorization server. The means through which the client registers with the authorization server are not defined in OAuth 2.0 specification.
As an extension, we have implemented client registration/on-boarding as a micro service that exposes several endpoints.
Unlike other OAuth 2.0 providers, we have extend the client registration to define the relationship between client and service (service registers itself) and service’s endpoints.
Before digging into the details of implementation, let’s clarify some concepts about client.
OAuth 2.0 defines two client types, based on their ability to authenticate securely with the authorization server (i.e., ability to maintain the confidentiality of their client credentials).
Clients capable of maintaining the confidentiality of their credentials (e.g., client implemented on a secure server with restricted access to the client credentials), or capable of secure client authentication using other means.
Clients incapable of maintaining the confidentiality of their credentials (e.g., clients executing on the device used by the resource owner, such as an installed native application or a web browser-based application), and incapable of secure client authentication via any other means.
Extended Client Type
Above are standard client types defined in the specification and we have added another two client types to control which client can issue resource owner password credentials grant request or customized grant types and which client will receive by-reference tokens or by-value tokens.
These clients are marked as trusted and they are the only clients that can issue resource owner password credentials grant type. For API management team, please make sure that trusted client is also confidential and the client and resource must be deployed and managed by the same organization as this flow is not as secure as authorization code and client credentials flows.
When using customized grant types, the client must be marked as trusted as these grant type normally makes a lot assumptions and might not be working at the same security level as authorization code and client credentials grant types.
For some of the organizations, it is not comfortable to send a JWT to a third party client, user’s device or browser. In this case, the client can be registered as external client type and the token issued to the client will be just a UUID. Once the requests come back to the corporate network, a BFF can go to the AS to exchange the by-reference token to a JWT. A BFF client id can be registered as well optionally so that the AS can authorize only one client can send request to exchange the opaque token to a JWT.
The client type designation is based on the authorization server’s definition of secure authentication and its acceptable exposure levels of client credentials. The authorization server does not make assumptions about the client type.
A client may be implemented as a distributed set of components or services, each with a different client type and security context (e.g., a distributed client with both a confidential server-based component and a public browser-based component). In this case, the client should register each component or service as a separate client.
In a microservices architecture, a service might call other services to fulfill its request, in this case, it should register itself as a service and a client. That means the owner needs to follow both service on-boarding and client on-boarding processes.
This specification has been designed around the following client profiles:
web application (web server)
A web application is a confidential client running on a web server. Resource owners access the client via an HTML user interface rendered in a user-agent on the device used by the resource owner. The client credentials as well as any access token issued to the client are stored on the web server and are not exposed to or accessible by the resource owner.
user-agent-based application (browser)
A user-agent-based application is a public client in which the client code is downloaded from a web server and executes within a user-agent (e.g., web browser) on the device used by the resource owner. Protocol data and credentials are easily accessible (and often visible) to the resource owner. Since such applications reside within the user-agent, they can make seamless use of the user-agent
capabilities when requesting authorization.
native application (mobile)
A native application is a public client installed and executed on the device used by the resource owner. Protocol data and credentials are accessible to the resource owner. It is assumed that any client authentication credentials included in the application can be extracted. On the other hand, dynamically issued credentials such as access tokens or refresh tokens can receive an acceptable level of protection. At a minimum, these credentials are protected from hostile servers with which the application may interact. On some platforms, these credentials might be protected from other applications residing on the same device.
The specification only mentioned above client profiles and the following two profiles are added in our OAuth 2.0 implementation.
batch application (batch)
Batch jobs are very similar with web application but they are managed by enterprise scheduler and executed in a projected environment. It is considered as confidential client.
Services are usually protected as resources but in a microservices architecture, a service can also be a client to call other services or resources. These services normally running within light-weight containers in a secured environment. And they are considered as confidential clients.
The authorization server issues the registered client a client identifier - a unique string representing the registration information provided by the client. The client identifier is not a secret; it is exposed to the resource owner and MUST NOT be used alone for client authentication. The client identifier is unique to the authorization server. In our implementation, it is a UUID generated on the server. Here is an example:
Clients in possession of a client secret MAY use the HTTP Basic authentication scheme as defined in [RFC2617] to authenticate with the authorization server. The client identifier is encoded using the “application/x-www-form-urlencoded” encoding algorithm , and the encoded value is used as the username; the client secret is encoded using the same algorithm and used as the password. The authorization server supports the HTTP Basic authentication scheme for authenticating clients that were issued a client secret.
The client secret is generated on the client service and sent in the registration response. This is the only time you can receive the client secret. It MUST be write down as there is no way to recover it later on.
For example (with extra line breaks for display purposes only):
When registering a client, you can specify which authenticate class will be used in the authenticate_class column. Your own authenticate class can be added as a plugin in the service.yml configuration file. In a typical organization, you might need to support vary authentication providers. For example, your API portal supports employee to be authenticated with SPNEGO/Kerberos SSO with AD and customers with a user table in a database.
By default, we have implemented LDAP, SPNEGO/Kerberos, User table and GitHub repo for authentication and authorization. Other authentication method can be easily supported if there are requests from our users.
Due to security reasons, all client must be registered before authenticated on the server. Unregistered clients are not supported on this implementation.
Client Micro Service
This service has several endpoints and listening to port 6884.
This endpoint gets all the clients from client service with filter and sorted on clientName. A page query parameter is mandatory and pageSize and clientName filter are optional.
Page number which must be specified. It starts with 1 and an empty list will be returned if the page is greater than the last page.
Default pageSize is 10 and you can overwrite it with another number. Please don’t use a big number due to performance reason.
This is the only filter available and it supports filter by start with a few characters. For example, “clientName=abc” means any clientName starts with “abc”. The result is also sorted by clientName in the pagination.
The following validation will be performed in the service.
If page is missing from the query parameter, an error will be returned.
"description": "Query parameter '%s' is required on path '%s' but not found in request."
This endpoint adds one or more endpoints of a service to a client. It removes all existing links and insert new ones. Once the insert is done, the client’s scope is recalculated based on the updated info.
The response body will contains the old scope and new scope for the client. Here is an example.