added OAuth error display page, closes #559
parent
118237ab05
commit
4655650a68
|
@ -38,7 +38,8 @@
|
||||||
request-validator-ref="oauthRequestValidator"
|
request-validator-ref="oauthRequestValidator"
|
||||||
redirect-resolver-ref="blacklistAwareRedirectResolver"
|
redirect-resolver-ref="blacklistAwareRedirectResolver"
|
||||||
authorization-endpoint-url="/authorize"
|
authorization-endpoint-url="/authorize"
|
||||||
token-endpoint-url="/token">
|
token-endpoint-url="/token"
|
||||||
|
error-page="/error">
|
||||||
|
|
||||||
<oauth:authorization-code authorization-code-services-ref="defaultOAuth2AuthorizationCodeService"/>
|
<oauth:authorization-code authorization-code-services-ref="defaultOAuth2AuthorizationCodeService"/>
|
||||||
<oauth:implicit />
|
<oauth:implicit />
|
||||||
|
@ -53,6 +54,7 @@
|
||||||
|
|
||||||
<bean id="oauthRequestValidator" class="org.mitre.oauth2.token.StructuredScopeAwareOAuth2RequestValidator" />
|
<bean id="oauthRequestValidator" class="org.mitre.oauth2.token.StructuredScopeAwareOAuth2RequestValidator" />
|
||||||
|
|
||||||
|
<!-- Error page handler. -->
|
||||||
|
<mvc:view-controller path="/error" view-name="error" />
|
||||||
|
|
||||||
</beans>
|
</beans>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
|
||||||
|
<%@ taglib prefix="o" tagdir="/WEB-INF/tags"%>
|
||||||
|
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
|
||||||
|
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
|
||||||
|
|
||||||
|
<spring:message code="error.title" var="title"/>
|
||||||
|
<o:header title="${title}" />
|
||||||
|
<o:topbar pageName="Error" />
|
||||||
|
<div class="container-fluid main">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="offset1 span10">
|
||||||
|
<div class="hero-unit">
|
||||||
|
<h1>Error:</h1>
|
||||||
|
<h2 class="text-error"><c:out value="${error.getOAuth2ErrorCode()}" /></h2>
|
||||||
|
<p>
|
||||||
|
There was an error processing your request. The server's message was:
|
||||||
|
<blockquote class="text-error"><b><c:out value="${error.message}" /></b></blockquote>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<o:footer />
|
|
@ -103,131 +103,129 @@ public class AuthorizationRequestFilter extends GenericFilterBean {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we have to create our own auth request in order to get at all the parmeters appropriately
|
|
||||||
AuthorizationRequest authRequest = authRequestFactory.createAuthorizationRequest(createRequestMap(request.getParameterMap()));
|
|
||||||
|
|
||||||
ClientDetailsEntity client = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// we have to create our own auth request in order to get at all the parmeters appropriately
|
||||||
|
AuthorizationRequest authRequest = null;
|
||||||
|
|
||||||
|
ClientDetailsEntity client = null;
|
||||||
|
|
||||||
|
authRequest = authRequestFactory.createAuthorizationRequest(createRequestMap(request.getParameterMap()));
|
||||||
client = clientService.loadClientByClientId(authRequest.getClientId());
|
client = clientService.loadClientByClientId(authRequest.getClientId());
|
||||||
} catch (InvalidClientException e) {
|
|
||||||
// no need to worry about this here, it would be caught elsewhere
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
// no need to worry about this here, it would be caught elsewhere
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// save the login hint to the session
|
|
||||||
if (authRequest.getExtensions().get(LOGIN_HINT) != null) {
|
|
||||||
session.setAttribute(LOGIN_HINT, authRequest.getExtensions().get(LOGIN_HINT));
|
|
||||||
} else {
|
|
||||||
session.removeAttribute(LOGIN_HINT);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (authRequest.getExtensions().get(PROMPT) != null) {
|
|
||||||
// we have a "prompt" parameter
|
|
||||||
String prompt = (String)authRequest.getExtensions().get(PROMPT);
|
|
||||||
List<String> prompts = Splitter.on(PROMPT_SEPARATOR).splitToList(Strings.nullToEmpty(prompt));
|
|
||||||
|
|
||||||
if (prompts.contains(PROMPT_NONE)) {
|
|
||||||
// see if the user's logged in
|
|
||||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
|
||||||
|
|
||||||
if (auth != null) {
|
|
||||||
// user's been logged in already (by session management)
|
|
||||||
// we're OK, continue without prompting
|
|
||||||
chain.doFilter(req, res);
|
|
||||||
} else {
|
|
||||||
logger.info("Client requested no prompt");
|
|
||||||
// user hasn't been logged in, we need to "return an error"
|
|
||||||
if (client != null && authRequest.getRedirectUri() != null) {
|
|
||||||
|
|
||||||
// if we've got a redirect URI then we'll send it
|
|
||||||
|
|
||||||
String url = redirectResolver.resolveRedirect(authRequest.getRedirectUri(), client);
|
|
||||||
|
|
||||||
try {
|
|
||||||
URIBuilder uriBuilder = new URIBuilder(url);
|
|
||||||
|
|
||||||
uriBuilder.addParameter(ERROR, LOGIN_REQUIRED);
|
|
||||||
if (!Strings.isNullOrEmpty(authRequest.getState())) {
|
|
||||||
uriBuilder.addParameter(STATE, authRequest.getState()); // copy the state parameter if one was given
|
|
||||||
}
|
|
||||||
|
|
||||||
response.sendRedirect(uriBuilder.toString());
|
|
||||||
return;
|
|
||||||
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
logger.error("Can't build redirect URI for prompt=none, sending error instead", e);
|
|
||||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (prompts.contains(PROMPT_LOGIN)) {
|
|
||||||
|
|
||||||
// first see if the user's already been prompted in this session
|
|
||||||
if (session.getAttribute(PROMPTED) == null) {
|
|
||||||
// user hasn't been PROMPTED yet, we need to check
|
|
||||||
|
|
||||||
session.setAttribute(PROMPT_REQUESTED, Boolean.TRUE);
|
|
||||||
|
|
||||||
|
// save the login hint to the session
|
||||||
|
if (authRequest.getExtensions().get(LOGIN_HINT) != null) {
|
||||||
|
session.setAttribute(LOGIN_HINT, authRequest.getExtensions().get(LOGIN_HINT));
|
||||||
|
} else {
|
||||||
|
session.removeAttribute(LOGIN_HINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authRequest.getExtensions().get(PROMPT) != null) {
|
||||||
|
// we have a "prompt" parameter
|
||||||
|
String prompt = (String)authRequest.getExtensions().get(PROMPT);
|
||||||
|
List<String> prompts = Splitter.on(PROMPT_SEPARATOR).splitToList(Strings.nullToEmpty(prompt));
|
||||||
|
|
||||||
|
if (prompts.contains(PROMPT_NONE)) {
|
||||||
// see if the user's logged in
|
// see if the user's logged in
|
||||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
|
||||||
if (auth != null) {
|
if (auth != null) {
|
||||||
// user's been logged in already (by session management)
|
// user's been logged in already (by session management)
|
||||||
// log them out and continue
|
// we're OK, continue without prompting
|
||||||
SecurityContextHolder.getContext().setAuthentication(null);
|
|
||||||
chain.doFilter(req, res);
|
chain.doFilter(req, res);
|
||||||
} else {
|
} else {
|
||||||
// user hasn't been logged in yet, we can keep going since we'll get there
|
logger.info("Client requested no prompt");
|
||||||
|
// user hasn't been logged in, we need to "return an error"
|
||||||
|
if (client != null && authRequest.getRedirectUri() != null) {
|
||||||
|
|
||||||
|
// if we've got a redirect URI then we'll send it
|
||||||
|
|
||||||
|
String url = redirectResolver.resolveRedirect(authRequest.getRedirectUri(), client);
|
||||||
|
|
||||||
|
try {
|
||||||
|
URIBuilder uriBuilder = new URIBuilder(url);
|
||||||
|
|
||||||
|
uriBuilder.addParameter(ERROR, LOGIN_REQUIRED);
|
||||||
|
if (!Strings.isNullOrEmpty(authRequest.getState())) {
|
||||||
|
uriBuilder.addParameter(STATE, authRequest.getState()); // copy the state parameter if one was given
|
||||||
|
}
|
||||||
|
|
||||||
|
response.sendRedirect(uriBuilder.toString());
|
||||||
|
return;
|
||||||
|
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
logger.error("Can't build redirect URI for prompt=none, sending error instead", e);
|
||||||
|
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (prompts.contains(PROMPT_LOGIN)) {
|
||||||
|
|
||||||
|
// first see if the user's already been prompted in this session
|
||||||
|
if (session.getAttribute(PROMPTED) == null) {
|
||||||
|
// user hasn't been PROMPTED yet, we need to check
|
||||||
|
|
||||||
|
session.setAttribute(PROMPT_REQUESTED, Boolean.TRUE);
|
||||||
|
|
||||||
|
// see if the user's logged in
|
||||||
|
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
if (auth != null) {
|
||||||
|
// user's been logged in already (by session management)
|
||||||
|
// log them out and continue
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(null);
|
||||||
|
chain.doFilter(req, res);
|
||||||
|
} else {
|
||||||
|
// user hasn't been logged in yet, we can keep going since we'll get there
|
||||||
|
chain.doFilter(req, res);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// user has been PROMPTED, we're fine
|
||||||
|
|
||||||
|
// but first, undo the prompt tag
|
||||||
|
session.removeAttribute(PROMPTED);
|
||||||
chain.doFilter(req, res);
|
chain.doFilter(req, res);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// user has been PROMPTED, we're fine
|
// prompt parameter is a value we don't care about, not our business
|
||||||
|
|
||||||
// but first, undo the prompt tag
|
|
||||||
session.removeAttribute(PROMPTED);
|
|
||||||
chain.doFilter(req, res);
|
chain.doFilter(req, res);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// prompt parameter is a value we don't care about, not our business
|
} else if (authRequest.getExtensions().get(MAX_AGE) != null ||
|
||||||
chain.doFilter(req, res);
|
(client != null && client.getDefaultMaxAge() != null)) {
|
||||||
}
|
|
||||||
|
// default to the client's stored value, check the string parameter
|
||||||
} else if (authRequest.getExtensions().get(MAX_AGE) != null ||
|
Integer max = (client != null ? client.getDefaultMaxAge() : null);
|
||||||
(client != null && client.getDefaultMaxAge() != null)) {
|
String maxAge = (String) authRequest.getExtensions().get(MAX_AGE);
|
||||||
|
if (maxAge != null) {
|
||||||
// default to the client's stored value, check the string parameter
|
max = Integer.parseInt(maxAge);
|
||||||
Integer max = (client != null ? client.getDefaultMaxAge() : null);
|
}
|
||||||
String maxAge = (String) authRequest.getExtensions().get(MAX_AGE);
|
|
||||||
if (maxAge != null) {
|
if (max != null) {
|
||||||
max = Integer.parseInt(maxAge);
|
|
||||||
}
|
Date authTime = (Date) session.getAttribute(AuthenticationTimeStamper.AUTH_TIMESTAMP);
|
||||||
|
|
||||||
if (max != null) {
|
Date now = new Date();
|
||||||
|
if (authTime != null) {
|
||||||
Date authTime = (Date) session.getAttribute(AuthenticationTimeStamper.AUTH_TIMESTAMP);
|
long seconds = (now.getTime() - authTime.getTime()) / 1000;
|
||||||
|
if (seconds > max) {
|
||||||
Date now = new Date();
|
// session is too old, log the user out and continue
|
||||||
if (authTime != null) {
|
SecurityContextHolder.getContext().setAuthentication(null);
|
||||||
long seconds = (now.getTime() - authTime.getTime()) / 1000;
|
}
|
||||||
if (seconds > max) {
|
|
||||||
// session is too old, log the user out and continue
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
chain.doFilter(req, res);
|
||||||
|
} else {
|
||||||
|
// no prompt parameter, not our business
|
||||||
|
chain.doFilter(req, res);
|
||||||
}
|
}
|
||||||
chain.doFilter(req, res);
|
|
||||||
} else {
|
} catch (InvalidClientException e) {
|
||||||
// no prompt parameter, not our business
|
// we couldn't find the client, move on and let the rest of the system catch the error
|
||||||
chain.doFilter(req, res);
|
chain.doFilter(req, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue