in org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/extensions/oidc_rp/impl/OidcCallbackServlet.java [92:171]
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
throws ServletException, IOException {
try {
StringBuffer requestURL = request.getRequestURL();
if ( request.getQueryString() != null )
requestURL.append('?').append(request.getQueryString());
AuthenticationResponse authResponse = AuthenticationResponseParser.parse(new URI(requestURL.toString()));
OidcStateManager stateManager = OidcStateManager.stateFor(request);
if ( authResponse.getState() == null || !stateManager.isValidState(authResponse.getState()))
throw new ServletException("Failed state check");
if ( response instanceof AuthenticationErrorResponse )
throw new ServletException(authResponse.toErrorResponse().getErrorObject().toString());
Optional<String> redirect = stateManager.getStateAttribute(authResponse.getState(), OidcStateManager.PARAMETER_NAME_REDIRECT);
String authCode = authResponse.toSuccessResponse().getAuthorizationCode().getValue();
Optional<String> desiredConnectionName = stateManager.getStateAttribute(authResponse.getState(), OidcStateManager.PARAMETER_NAME_CONNECTION);
stateManager.unregisterState(authResponse.getState());
if ( desiredConnectionName.isEmpty() ) {
logger.warn("Did not find any connection in stateManager");
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
OidcConnection connection = connections.get(desiredConnectionName.get());
if ( connection == null ) {
logger.warn("Requested unknown connection {}", desiredConnectionName.get());
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
if ( connection.baseUrl() == null )
throw new ServletException("Misconfigured baseUrl");
ClientID clientId = new ClientID(connection.clientId());
Secret clientSecret = new Secret(connection.clientSecret());
ClientSecretBasic clientCredentials = new ClientSecretBasic(clientId, clientSecret);
AuthorizationCode code = new AuthorizationCode(authCode);
OIDCProviderMetadata providerMetadata = metadataRegistry.getProviderMetadata(connection.baseUrl());
TokenRequest tokenRequest = new TokenRequest(
providerMetadata.getTokenEndpointURI(),
clientCredentials,
new AuthorizationCodeGrant(code, new URI(getCallbackUri(request)))
);
OIDCTokenResponse tokenResponse = OIDCTokenResponse.parse(tokenRequest.toHTTPRequest().send());
if ( !tokenResponse.indicatesSuccess() ) {
TokenErrorResponse errorResponse = tokenResponse.toErrorResponse();
logger.warn("Error returned when trying to obtain access token : {}, {}",
errorResponse.getErrorObject().getCode(), errorResponse.getErrorObject().getDescription());
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
// TODO - additional validations for the id_token
// - does the 'aud' claim match the client id of our connection
// - nonce validation (?)
// - iat/exp validation (?)
tokenStore.persistTokens(connection, request.getResourceResolver(), tokenResponse.getOIDCTokens());
if ( redirect.isEmpty() ) {
response.setStatus(HttpServletResponse.SC_OK);
response.addHeader("Content-Type", "text/plain");
response.getWriter().write("OK");
response.getWriter().flush();
response.getWriter().close();
} else {
response.sendRedirect(URLDecoder.decode(redirect.get(), StandardCharsets.UTF_8));
}
} catch (ParseException | URISyntaxException | IOException e) {
throw new ServletException(e);
}
}