Consentor Plugin#
Plugin Descriptor interface:
ConsentorPluginDescriptor
A Consentor Plugin implements logic required to obtain authorization consent from users.
See User Consent for more information.
Reading the OAuth client#
Declare RequestingOAuthClient on the plugin’s configuration interface to obtain the client that triggered the consent flow. This gives the plugin the client’s metadata, and, through its scope map and claim set, the resolved scope and claim configuration needed to render a consent screen.
public interface MyConsentorConfiguration extends Configuration
{
RequestingOAuthClient getRequestingOAuthClient();
}
The consent attributes carry scope and claim names. Resolve those names against the client to get descriptions and the rest of the configuration:
public final class MyConsentorHandler implements ConsentorCompletionRequestHandler<Request>
{
private final IntermediateConsentState _consentState;
private final OAuthClient _client;
public MyConsentorHandler(MyConsentorConfiguration configuration, IntermediateConsentState consentState)
{
_consentState = consentState;
_client = configuration.getRequestingOAuthClient().getClient();
}
@Override
public Request preProcess(Request request, Response response)
{
ConsentAttributes consent = _consentState.getConsentAttributes();
Set<ScopeValue> scopes = _client.getScopeMap().getAllMatching(consent.getScopeNames());
Set<ClaimConfig> claims = _client.getClaimSet()
.filtered(Set.copyOf(consent.getClaimNames()))
.getAll()
.stream()
.filter(claim -> claim.isConsentable() && !claim.isSystemClaim())
.collect(Collectors.toSet());
response.setResponseModel(ResponseModel.templateResponseModel(Map.of(
"clientName", _client.getName().orElse(_client.getId()),
"clientDescription", _client.getDescription().orElse(""),
"logoUri", _client.getLogoUri().filter(MyConsentorHandler::isHttpUri)
.map(URI::toString).orElse(""),
"scopes", scopes,
"claims", claims),
"index"), Response.ResponseModelScope.ANY);
return request;
}
private static boolean isHttpUri(URI uri)
{
return "https".equalsIgnoreCase(uri.getScheme()) || "http".equalsIgnoreCase(uri.getScheme());
}
}
Templates do not escape values automatically, and a dynamically registered client controls its own name, description, and URIs.
Encode text with $_tr.encodeHtml($clientName) and attribute values with
$_tr.encodeHtmlAttribute($clientName), and place an encoded attribute value in a double-quoted attribute.
Restrict URI-valued metadata to the http and https schemes before it reaches the template, as the example
above does for the logo URI.
Each ScopeValue exposes the scope’s description, the claims it entitles, and whether it is required. For a prefix
scope, it also exposes the suffix. Each ClaimConfig exposes the claim’s description, whether it is required, and
whether it is a system claim.
To show every scope the client may request, rather than only those in the current request, read
_client.getScopeMap().getScopeValues() instead. This is useful on screens that present the full set of permissions
an application can ask for.
Scopes that entitle claims#
Only scopes that entitle no claims and that are consentable appear in ConsentAttributes.getScopeNames(). A scope
that entitles claims is presented through those claims instead, so its name is absent from getScopeNames() while
its claims appear in getClaimNames().
A consent screen that renders only getScopeNames() therefore looks empty for a request such as
openid profile email, because profile and email entitle claims. Render both collections, as in the example
above. The built-in consent screen behaves the same way.