Multiple components work together to form the authentication and authorization flows in Microbus
.
To get started, the client submits credentials to an authenticator microservice. In the simplest form, credentials are a username and a password obtained from the user via a web form. If the credentials are valid, a JWT token is issued and returned back to the client.
Microbus
does not include authenticators out of the box. The login example microservice demonstrates how such a microservice may look like when the client is a browser. A Set-Cookie
response header returns the JWT to the browser, which in turn sends it back with all consecutive requests in the Cookie
request header. The cookie is named Authorization
to allow the authorization middleware to easily locate it.
The login example microservice utilizes the token issuer core microservice to issue and validate JWTs. It is possible to replace the token issuer core microservice with a custom token validator.
Now that the client is in possession of a JWT, it’s expected to be included in the header of consecutive requests. The authorization middleware examines the HTTP request headers for a JWT in the Authorization: Bearer
header or in a Cookie
named Authorization
. It identifies the appropriate token issuer microservice by examining the validator
claim and validates the token with the issuer to get the actor associated with it. The actor is then propagated downstream to the target microservice and the rest of the call stack thereafter.
Cookie: Authorization=<JWT>
Authorization: Bearer <JWT>
The connector of each microservice allows a request to continue if the actor associated with the request satisfies a set of requirements expressed as a boolean expression over the properties of the actor. Requirements are specified during the definition of the endpoint, most commonly via service.yaml
, or using the sub.Actor
option when creating subscriptions manually.
For example, the SalesReport
endpoint below is restricted to sales directors or managers only. Requests from actors that do not satisfy these requirements will be denied with a 401 Unauthorized
or 403 Forbidden
error.
functions:
- signature: SalesReport(from time.Time, to time.Time) (sales SalesData)
actor: groups.sales && (roles.director || roles.manager)
By default, 401 Unauthorized
and 403 Forbidden
errors are returned to the client in the form of an HTTP status code accompanied by an error message. The error page redirect middleware can improve user experience by redirecting to a more user-friendly page. Redirection is contingent upon the Sec-Fetch-Mode
and Sec-Fetch-Dest
request headers indicating that the user is using a browser to navigate to a new document, thus avoiding interfering with requests from single-page applications.
Sec-Fetch-Mode: navigate
Sec-Fetch-Dest: document
A 401 Unauthorized
error indicates that the user is not logged in. The following redirects to a login page where the user can begin the authentication flow.
httpIngressProxy := httpingress.NewService()
httpIngressProxy.Middleware().Append("401Redirect", middleware.ErrorPageRedirect(http.StatusUnauthorized, "/login"))
A 403 Forbidden
error indicates the user is attempting to access a page or API they are not authorized for. The following redirects to a dedicated error page.
httpIngressProxy.Middleware().Append("403Redirect", middleware.ErrorPageRedirect(http.StatusForbidden, "/access-denied"))