Skip to content
This repository was archived by the owner on Jul 3, 2020. It is now read-only.

Minor fixes - NPE checks and additional client validations #81

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,137 +39,139 @@
@Named
public class AuthenticationFilter implements Filter {

private static final Logger LOG = LoggerFactory.getLogger(AuthenticationFilter.class);

private AbstractAuthenticator authenticator;

@Inject
private AuthorizationRequestRepository authorizationRequestRepository;

@Inject
private OAuth2Validator oAuth2Validator;

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

/*
* Create an authorizationRequest from the request parameters.
* This can be either a valid or an invalid request, which will be determined by the oAuth2Validator.
*/
AuthorizationRequest authorizationRequest = extractAuthorizationRequest(request);
final ValidationResponse validationResponse = oAuth2Validator.validate(authorizationRequest);

if (authenticator.canCommence(request)) {
/*
* Ok, the authenticator wants to have control again (because he stepped
* out)
*/
authenticator.doFilter(request, response, chain);
} else if (validationResponse.valid()) {
// Request contains correct parameters to be a real OAuth2 request.
handleInitialRequest(authorizationRequest, request);
authenticator.doFilter(request, response, chain);
} else {
// not an initial request but authentication module cannot handle it either
sendError(response, authorizationRequest, validationResponse);
}
}

protected AuthorizationRequest extractAuthorizationRequest(HttpServletRequest request) {
String responseType = request.getParameter("response_type");
String clientId = request.getParameter("client_id");
String redirectUri = request.getParameter("redirect_uri");

List<String> requestedScopes = null;
if (StringUtils.isNotBlank(request.getParameter("scope"))) {
requestedScopes = Arrays.asList(request.getParameter("scope").split(","));
}

String state = request.getParameter("state");
String authState = getAuthStateValue();

return new AuthorizationRequest(responseType, clientId, redirectUri, requestedScopes, state, authState);
}

private boolean handleInitialRequest(AuthorizationRequest authReq, HttpServletRequest request) throws
ServletException {

try {
authorizationRequestRepository.save(authReq);
} catch (Exception e) {
LOG.error("while saving authorization request", e);
throw new ServletException("Cannot save authorization request");
}

request.setAttribute(AbstractAuthenticator.AUTH_STATE, authReq.getAuthState());
request.setAttribute(AbstractAuthenticator.RETURN_URI, request.getRequestURI());
return true;
}

protected String getAuthStateValue() {
return UUID.randomUUID().toString();
}

private void sendError(HttpServletResponse response, AuthorizationRequest authReq, ValidationResponse validate)
throws IOException {
LOG.info("Will send error response for authorization request '{}', validation result: {}", authReq, validate);
String redirectUri = authReq.getRedirectUri();
String state = authReq.getState();
if (isValidUri(redirectUri)) {
redirectUri = redirectUri.concat(redirectUri.contains("?") ? "&" : "?");
redirectUri = redirectUri
.concat("error=").concat(validate.getValue())
.concat("&error_description=").concat(validate.getDescription())
.concat(StringUtils.isBlank(state) ? "" : "&state=".concat(URLEncoder.encode(state, "UTF-8")));
LOG.info("Sending error response, a redirect to: {}", redirectUri);
response.sendRedirect(redirectUri);
} else {
LOG.info("Sending error response 'bad request': {}", validate.getDescription());
response.sendError(HttpServletResponse.SC_BAD_REQUEST, validate.getDescription());
}
}

@Override
public void destroy() {
}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

public void setAuthenticator(AbstractAuthenticator authenticator) {
this.authenticator = authenticator;
}

public static boolean isValidUri(String redirectUri) {
try {
URI uri = new URI(redirectUri);
if (uri.getScheme() != null) {
return true;
} else {
return false;
}
} catch (URISyntaxException e) {
return false;
}
}

/**
* @param authorizationRequestRepository
* the authorizationRequestRepository to set
*/
public void setAuthorizationRequestRepository(AuthorizationRequestRepository authorizationRequestRepository) {
this.authorizationRequestRepository = authorizationRequestRepository;
}

/**
* @param oAuth2Validator
* the oAuth2Validator to set
*/
public void setOAuth2Validator(OAuth2Validator oAuth2Validator) {
this.oAuth2Validator = oAuth2Validator;
}
private static final Logger LOG = LoggerFactory.getLogger(AuthenticationFilter.class);

private AbstractAuthenticator authenticator;

@Inject
private AuthorizationRequestRepository authorizationRequestRepository;

@Inject
private OAuth2Validator oAuth2Validator;

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

/*
* Create an authorizationRequest from the request parameters. This can
* be either a valid or an invalid request, which will be determined by
* the oAuth2Validator.
*/
AuthorizationRequest authorizationRequest = extractAuthorizationRequest(request);
final ValidationResponse validationResponse = oAuth2Validator.validate(authorizationRequest);

if (authenticator.canCommence(request)) {
/*
* Ok, the authenticator wants to have control again (because he
* stepped out)
*/
authenticator.doFilter(request, response, chain);
} else if (validationResponse.valid()) {
// Request contains correct parameters to be a real OAuth2 request.
handleInitialRequest(authorizationRequest, request);
authenticator.doFilter(request, response, chain);
} else {
// not an initial request but authentication module cannot handle it
// either
sendError(response, authorizationRequest, validationResponse);
}
}

protected AuthorizationRequest extractAuthorizationRequest(HttpServletRequest request) {
String responseType = request.getParameter("response_type");
String clientId = request.getParameter("client_id");
String redirectUri = request.getParameter("redirect_uri");

List<String> requestedScopes = null;
if (StringUtils.isNotBlank(request.getParameter("scope"))) {
requestedScopes = Arrays.asList(request.getParameter("scope").split(","));
}

String state = request.getParameter("state");
String authState = getAuthStateValue();

return new AuthorizationRequest(responseType, clientId, redirectUri, requestedScopes, state, authState);
}

private boolean handleInitialRequest(AuthorizationRequest authReq, HttpServletRequest request) throws ServletException {

try {
authorizationRequestRepository.save(authReq);
} catch (Exception e) {
LOG.error("while saving authorization request", e);
throw new ServletException("Cannot save authorization request");
}

request.setAttribute(AbstractAuthenticator.AUTH_STATE, authReq.getAuthState());
request.setAttribute(AbstractAuthenticator.RETURN_URI, request.getRequestURI());
return true;
}

protected String getAuthStateValue() {
return UUID.randomUUID().toString();
}

private void sendError(HttpServletResponse response, AuthorizationRequest authReq, ValidationResponse validate) throws IOException {
LOG.info("Will send error response for authorization request '{}', validation result: {}", authReq, validate);
String redirectUri = authReq.getRedirectUri();
String state = authReq.getState();
if (isValidUri(redirectUri)) {
redirectUri = redirectUri.concat(redirectUri.contains("?") ? "&" : "?");
redirectUri = redirectUri.concat("error=").concat(validate.getValue()).concat("&error_description=").concat(validate.getDescription())
.concat(StringUtils.isBlank(state) ? "" : "&state=".concat(URLEncoder.encode(state, "UTF-8")));
LOG.info("Sending error response, a redirect to: {}", redirectUri);
response.sendRedirect(redirectUri);
} else {
LOG.info("Sending error response 'bad request': {}", validate.getDescription());
response.sendError(HttpServletResponse.SC_BAD_REQUEST, validate.getDescription());
}
}

@Override
public void destroy() {
}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

public void setAuthenticator(AbstractAuthenticator authenticator) {
this.authenticator = authenticator;
}

public static boolean isValidUri(String redirectUri) {
if (StringUtils.isEmpty(redirectUri)) {
return false;
}

try {
URI uri = new URI(redirectUri);
if (uri.getScheme() != null) {
return true;
} else {
return false;
}
} catch (URISyntaxException e) {
return false;
}
}

/**
* @param authorizationRequestRepository
* the authorizationRequestRepository to set
*/
public void setAuthorizationRequestRepository(AuthorizationRequestRepository authorizationRequestRepository) {
this.authorizationRequestRepository = authorizationRequestRepository;
}

/**
* @param oAuth2Validator
* the oAuth2Validator to set
*/
public void setOAuth2Validator(OAuth2Validator oAuth2Validator) {
this.oAuth2Validator = oAuth2Validator;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ enum ValidationResponse {

REDIRECT_URI_NOT_URI("invalid_request", "The redirect_uri is not a valid URI"),

REDIRECT_URI_DIFFERENT("invaid_request","The redirect_uri does not match the initial authorization request"),
REDIRECT_URI_DIFFERENT("invalid_request","The redirect_uri does not match the initial authorization request"),

SCOPE_NOT_VALID("invalid_scope", "The requested scope is invalid, unknown, malformed, " +
"or exceeds the scope granted by the resource owner."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ protected void validateClient(AccessTokenRequest accessTokenRequest,
// Use the request parameters to obtain the client
client = getClient(accessTokenRequest.getClientId(), accessTokenRequest.getClientSecret(),
UNKNOWN_CLIENT_ID);
} else {
throw new ValidationResponseException(UNKNOWN_CLIENT_ID);
}

// Record the associated client
Expand Down
Loading