The Rule Types section tells, that a default rule can be used as a base to inherit behavior for the regular rule.
In principle, there is a need to differentiate two things:
the defined rule, which is what you define
the effective rule, which is what is executed at runtime
This is comparable to the polymorphism concept in programming languages. So, how does it work?
Imagine, the concept of a rule is e.g. an interface written in Java defining the following methods:
public interface Rule {
public void executeAuthenticationStage(req Request)
public void executeAuthorizationStage(req Request)
public void executeFinalizationStage(req Request)
public void handleError(req Request)
}
And the logic described in Execution of Rules is implemented similar to what is shown in the snippet below
Rule rule = findMatchingRule(req)
if (rule == null) {
throw new NotFoundError()
}
try {
// execution of the authentication & authorization pipeline
rule.executeAuthenticationStage(req)
rule.executeAuthorizationStage(req)
rule.executeFinalizationStage(req)
// further logic related to response creation
} catch(Exception e) {
// execution of the error pipeline
rule.handleError(req)
// further logic related to response creation
}
with findMatchingRule
returning a specific instance of a class implementing our Rule
interface matching the request.
Since there is some default behaviour in place, like error handling, if the error pipeline is empty, and some stages of the authentication & authorization pipeline is optional, internally, there is some kind of base rule in place, all other rules inherit from. So something like shown in the snippet below.
public abstract class BaseRule implements Rule {
public abstract void executeAuthenticationStage(req Request)
public void executeAuthorizationStage(req Request) {}
public void executeFinalizationStage(req Request) {}
public void handleError(req Request) { handlerErrorDefault(req) }
}
If there is no default rule configured, an upstream specific rule can then be considered as a class inheriting from that BaseRule
and must implement at least the executeAuthenticationStage
method, similar to what is shown below
public class MySpecificRule extends BaseRule {
public void executeAuthenticationStage(req Request) { ... }
}
If however, there is a default rule configured, on one hand, it can be considered as yet another class deriving from our BaseClass
. So, something like
public class DefaultRule extends BaseRule {
public void executeAuthenticationStage(req Request) { ... }
public void executeAuthorizationStage(req Request) { ... }
public void executeFinalizationStage(req Request) { ... }
public void handleError(req Request) { ... }
}
with at least the aforesaid executeAuthenticationStage
method being implemented, as this is also required for the regular rule.
On the other hand, the definition of a regular, respectively upstream specific rule is then not a class deriving from the BaseRule
, but from the DefaultRule
. That way, upstream specific rules are only required, if the behavior of the default rule would not fit the given requirements of a particular service, respectively endpoint. So, if e.g. a rule requires only the authentication stage to be different from the default rule, you would only specify the required authentication mechanisms. That would result in something like shown in the snippet below.
public class SpecificRule extends DefaultRule {
public void executeAuthenticationStage(req Request) { ... }
}
And if there is a need to have the authorization stage deviating from the default rule, you would only specify the required authorization and contextualization mechanisms, resulting in something like
public class SpecificRule extends DefaultRule {
public void executeAuthorizationStage(req Request) { ... }
}
| You cannot override a single mechanism of a particular stage. As soon as you define a single mechanism in a pipeline, belonging to the one or the other stage, the entire stage is overridden. |